/lib/rouge/lexers/php.rb
Ruby | 173 lines | 154 code | 13 blank | 6 comment | 9 complexity | 4c90bbd92bd82e54cb85309e5668f510 MD5 | raw file
- # -*- coding: utf-8 -*- #
- module Rouge
- module Lexers
- class PHP < TemplateLexer
- title "PHP"
- desc "The PHP scripting language (php.net)"
- tag 'php'
- aliases 'php', 'php3', 'php4', 'php5'
- filenames '*.php', '*.php[345]',
- # Support Drupal file extensions, see:
- # https://github.com/gitlabhq/gitlabhq/issues/8900
- '*.module', '*.inc', '*.profile', '*.install', '*.test'
- mimetypes 'text/x-php'
- default_options :parent => 'html'
- def initialize(opts={})
- # if truthy, the lexer starts highlighting with php code
- # (no <?php required)
- @start_inline = opts.delete(:start_inline)
- @funcnamehighlighting = opts.delete(:funcnamehighlighting) { true }
- @disabledmodules = opts.delete(:disabledmodules) { [] }
- super(opts)
- end
- def self.builtins
- load Pathname.new(__FILE__).dirname.join('php/builtins.rb')
- self.builtins
- end
- def builtins
- return [] unless @funcnamehighlighting
- @builtins ||= Set.new.tap do |builtins|
- self.class.builtins.each do |mod, fns|
- next if @disabledmodules.include? mod
- builtins.merge(fns)
- end
- end
- end
- def start_inline?
- !!@start_inline
- end
- start do
- push :php if start_inline?
- end
- def self.keywords
- @keywords ||= Set.new %w(
- and E_PARSE old_function E_ERROR or as E_WARNING parent eval
- PHP_OS break exit case extends PHP_VERSION cfunction FALSE
- print for require continue foreach require_once declare return
- default static do switch die stdClass echo else TRUE elseif
- var empty if xor enddeclare include virtual endfor include_once
- while endforeach global __FILE__ endif list __LINE__ endswitch
- new __sleep endwhile not array __wakeup E_ALL NULL final
- php_user_filter interface implements public private protected
- abstract clone try catch throw this use namespace yield
- )
- end
- def self.analyze_text(text)
- return 1 if text.shebang?('php')
- return 0.3 if /<\?(?!xml)/ =~ text
- 0
- end
- state :root do
- rule /<\?(php|=)?/, Comment::Preproc, :php
- rule(/.*?(?=<\?)|.*/m) { delegate parent }
- end
- state :php do
- rule /\?>/, Comment::Preproc, :pop!
- # heredocs
- rule /<<<('?)([a-z_]\w*)\1\n.*?\n\2;?\n/im, Str::Heredoc
- rule /\s+/, Text
- rule /#.*?\n/, Comment::Single
- rule %r(//.*?\n), Comment::Single
- # empty comment, otherwise seen as the start of a docstring
- rule %r(/\*\*/), Comment::Multiline
- rule %r(/\*\*.*?\*/)m, Str::Doc
- rule %r(/\*.*?\*/)m, Comment::Multiline
- rule /(->|::)(\s*)([a-zA-Z_][a-zA-Z0-9_]*)/ do
- groups Operator, Text, Name::Attribute
- end
- rule /[~!%^&*+=\|:.<>\/?@-]+/, Operator
- rule /[\[\]{}();,]+/, Punctuation
- rule /class\b/, Keyword, :classname
- # anonymous functions
- rule /(function)(\s*)(?=\()/ do
- groups Keyword, Text
- end
- # named functions
- rule /(function)(\s+)(&?)(\s*)/ do
- groups Keyword, Text, Operator, Text
- push :funcname
- end
- rule /(const)(\s+)([a-zA-Z_]\w*)/i do
- groups Keyword, Text, Name::Constant
- end
- rule /(true|false|null)\b/, Keyword::Constant
- rule /\$\{\$+[a-z_]\w*\}/i, Name::Variable
- rule /\$+[a-z_]\w*/i, Name::Variable
- # may be intercepted for builtin highlighting
- rule /[\\a-z_][\\\w]*/i do |m|
- name = m[0]
- if self.class.keywords.include? name
- token Keyword
- elsif self.builtins.include? name
- token Name::Builtin
- else
- token Name::Other
- end
- end
- rule /(\d+\.\d*|\d*\.\d+)(e[+-]?\d+)?/i, Num::Float
- rule /\d+e[+-]?\d+/i, Num::Float
- rule /0[0-7]+/, Num::Oct
- rule /0x[a-f0-9]+/i, Num::Hex
- rule /\d+/, Num::Integer
- rule /'([^'\\]*(?:\\.[^'\\]*)*)'/, Str::Single
- rule /`([^`\\]*(?:\\.[^`\\]*)*)`/, Str::Backtick
- rule /"/, Str::Double, :string
- end
- state :classname do
- rule /\s+/, Text
- rule /[a-z_][\\\w]*/i, Name::Class, :pop!
- end
- state :funcname do
- rule /[a-z_]\w*/i, Name::Function, :pop!
- end
- state :string do
- rule /"/, Str::Double, :pop!
- rule /[^\\{$"]+/, Str::Double
- rule /\\([nrt\"$\\]|[0-7]{1,3}|x[0-9A-Fa-f]{1,2})/,
- Str::Escape
- rule /\$[a-zA-Z_][a-zA-Z0-9_]*(\[\S+\]|->[a-zA-Z_][a-zA-Z0-9_]*)?/, Name::Variable
- rule /\{\$\{/, Str::Interpol, :interp_double
- rule /\{(?=\$)/, Str::Interpol, :interp_single
- rule /(\{)(\S+)(\})/ do
- groups Str::Interpol, Name::Variable, Str::Interpol
- end
- rule /[${\\]+/, Str::Double
- end
- state :interp_double do
- rule /\}\}/, Str::Interpol, :pop!
- mixin :php
- end
- state :interp_single do
- rule /\}/, Str::Interpol, :pop!
- mixin :php
- end
- end
- end
- end