PageRenderTime 60ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/rouge/lexers/php.rb

https://gitlab.com/lukas.mesicek/gitlab-rouge
Ruby | 173 lines | 154 code | 13 blank | 6 comment | 9 complexity | 4c90bbd92bd82e54cb85309e5668f510 MD5 | raw file
  1. # -*- coding: utf-8 -*- #
  2. module Rouge
  3. module Lexers
  4. class PHP < TemplateLexer
  5. title "PHP"
  6. desc "The PHP scripting language (php.net)"
  7. tag 'php'
  8. aliases 'php', 'php3', 'php4', 'php5'
  9. filenames '*.php', '*.php[345]',
  10. # Support Drupal file extensions, see:
  11. # https://github.com/gitlabhq/gitlabhq/issues/8900
  12. '*.module', '*.inc', '*.profile', '*.install', '*.test'
  13. mimetypes 'text/x-php'
  14. default_options :parent => 'html'
  15. def initialize(opts={})
  16. # if truthy, the lexer starts highlighting with php code
  17. # (no <?php required)
  18. @start_inline = opts.delete(:start_inline)
  19. @funcnamehighlighting = opts.delete(:funcnamehighlighting) { true }
  20. @disabledmodules = opts.delete(:disabledmodules) { [] }
  21. super(opts)
  22. end
  23. def self.builtins
  24. load Pathname.new(__FILE__).dirname.join('php/builtins.rb')
  25. self.builtins
  26. end
  27. def builtins
  28. return [] unless @funcnamehighlighting
  29. @builtins ||= Set.new.tap do |builtins|
  30. self.class.builtins.each do |mod, fns|
  31. next if @disabledmodules.include? mod
  32. builtins.merge(fns)
  33. end
  34. end
  35. end
  36. def start_inline?
  37. !!@start_inline
  38. end
  39. start do
  40. push :php if start_inline?
  41. end
  42. def self.keywords
  43. @keywords ||= Set.new %w(
  44. and E_PARSE old_function E_ERROR or as E_WARNING parent eval
  45. PHP_OS break exit case extends PHP_VERSION cfunction FALSE
  46. print for require continue foreach require_once declare return
  47. default static do switch die stdClass echo else TRUE elseif
  48. var empty if xor enddeclare include virtual endfor include_once
  49. while endforeach global __FILE__ endif list __LINE__ endswitch
  50. new __sleep endwhile not array __wakeup E_ALL NULL final
  51. php_user_filter interface implements public private protected
  52. abstract clone try catch throw this use namespace yield
  53. )
  54. end
  55. def self.analyze_text(text)
  56. return 1 if text.shebang?('php')
  57. return 0.3 if /<\?(?!xml)/ =~ text
  58. 0
  59. end
  60. state :root do
  61. rule /<\?(php|=)?/, Comment::Preproc, :php
  62. rule(/.*?(?=<\?)|.*/m) { delegate parent }
  63. end
  64. state :php do
  65. rule /\?>/, Comment::Preproc, :pop!
  66. # heredocs
  67. rule /<<<('?)([a-z_]\w*)\1\n.*?\n\2;?\n/im, Str::Heredoc
  68. rule /\s+/, Text
  69. rule /#.*?\n/, Comment::Single
  70. rule %r(//.*?\n), Comment::Single
  71. # empty comment, otherwise seen as the start of a docstring
  72. rule %r(/\*\*/), Comment::Multiline
  73. rule %r(/\*\*.*?\*/)m, Str::Doc
  74. rule %r(/\*.*?\*/)m, Comment::Multiline
  75. rule /(->|::)(\s*)([a-zA-Z_][a-zA-Z0-9_]*)/ do
  76. groups Operator, Text, Name::Attribute
  77. end
  78. rule /[~!%^&*+=\|:.<>\/?@-]+/, Operator
  79. rule /[\[\]{}();,]+/, Punctuation
  80. rule /class\b/, Keyword, :classname
  81. # anonymous functions
  82. rule /(function)(\s*)(?=\()/ do
  83. groups Keyword, Text
  84. end
  85. # named functions
  86. rule /(function)(\s+)(&?)(\s*)/ do
  87. groups Keyword, Text, Operator, Text
  88. push :funcname
  89. end
  90. rule /(const)(\s+)([a-zA-Z_]\w*)/i do
  91. groups Keyword, Text, Name::Constant
  92. end
  93. rule /(true|false|null)\b/, Keyword::Constant
  94. rule /\$\{\$+[a-z_]\w*\}/i, Name::Variable
  95. rule /\$+[a-z_]\w*/i, Name::Variable
  96. # may be intercepted for builtin highlighting
  97. rule /[\\a-z_][\\\w]*/i do |m|
  98. name = m[0]
  99. if self.class.keywords.include? name
  100. token Keyword
  101. elsif self.builtins.include? name
  102. token Name::Builtin
  103. else
  104. token Name::Other
  105. end
  106. end
  107. rule /(\d+\.\d*|\d*\.\d+)(e[+-]?\d+)?/i, Num::Float
  108. rule /\d+e[+-]?\d+/i, Num::Float
  109. rule /0[0-7]+/, Num::Oct
  110. rule /0x[a-f0-9]+/i, Num::Hex
  111. rule /\d+/, Num::Integer
  112. rule /'([^'\\]*(?:\\.[^'\\]*)*)'/, Str::Single
  113. rule /`([^`\\]*(?:\\.[^`\\]*)*)`/, Str::Backtick
  114. rule /"/, Str::Double, :string
  115. end
  116. state :classname do
  117. rule /\s+/, Text
  118. rule /[a-z_][\\\w]*/i, Name::Class, :pop!
  119. end
  120. state :funcname do
  121. rule /[a-z_]\w*/i, Name::Function, :pop!
  122. end
  123. state :string do
  124. rule /"/, Str::Double, :pop!
  125. rule /[^\\{$"]+/, Str::Double
  126. rule /\\([nrt\"$\\]|[0-7]{1,3}|x[0-9A-Fa-f]{1,2})/,
  127. Str::Escape
  128. rule /\$[a-zA-Z_][a-zA-Z0-9_]*(\[\S+\]|->[a-zA-Z_][a-zA-Z0-9_]*)?/, Name::Variable
  129. rule /\{\$\{/, Str::Interpol, :interp_double
  130. rule /\{(?=\$)/, Str::Interpol, :interp_single
  131. rule /(\{)(\S+)(\})/ do
  132. groups Str::Interpol, Name::Variable, Str::Interpol
  133. end
  134. rule /[${\\]+/, Str::Double
  135. end
  136. state :interp_double do
  137. rule /\}\}/, Str::Interpol, :pop!
  138. mixin :php
  139. end
  140. state :interp_single do
  141. rule /\}/, Str::Interpol, :pop!
  142. mixin :php
  143. end
  144. end
  145. end
  146. end