ThirdParty/Pygments/pygments/lexers/php.py

changeset 4172
4f20dba37ab6
child 4697
c2e9bf425554
equal deleted inserted replaced
4170:8bc578136279 4172:4f20dba37ab6
1 # -*- coding: utf-8 -*-
2 """
3 pygments.lexers.php
4 ~~~~~~~~~~~~~~~~~~~
5
6 Lexers for PHP and related languages.
7
8 :copyright: Copyright 2006-2014 by the Pygments team, see AUTHORS.
9 :license: BSD, see LICENSE for details.
10 """
11
12 import re
13
14 from pygments.lexer import RegexLexer, include, bygroups, default, using, this
15 from pygments.token import Text, Comment, Operator, Keyword, Name, String, \
16 Number, Punctuation, Other
17 from pygments.util import get_bool_opt, get_list_opt, iteritems
18
19 __all__ = ['ZephirLexer', 'PhpLexer']
20
21
22 class ZephirLexer(RegexLexer):
23 """
24 For `Zephir language <http://zephir-lang.com/>`_ source code.
25
26 Zephir is a compiled high level language aimed
27 to the creation of C-extensions for PHP.
28
29 .. versionadded:: 2.0
30 """
31
32 name = 'Zephir'
33 aliases = ['zephir']
34 filenames = ['*.zep']
35
36 zephir_keywords = ['fetch', 'echo', 'isset', 'empty']
37 zephir_type = ['bit', 'bits', 'string']
38
39 flags = re.DOTALL | re.MULTILINE
40
41 tokens = {
42 'commentsandwhitespace': [
43 (r'\s+', Text),
44 (r'//.*?\n', Comment.Single),
45 (r'/\*.*?\*/', Comment.Multiline)
46 ],
47 'slashstartsregex': [
48 include('commentsandwhitespace'),
49 (r'/(\\.|[^[/\\\n]|\[(\\.|[^\]\\\n])*])+/'
50 r'([gim]+\b|\B)', String.Regex, '#pop'),
51 default('#pop')
52 ],
53 'badregex': [
54 (r'\n', Text, '#pop')
55 ],
56 'root': [
57 (r'^(?=\s|/|<!--)', Text, 'slashstartsregex'),
58 include('commentsandwhitespace'),
59 (r'\+\+|--|~|&&|\?|:|\|\||\\(?=\n)|'
60 r'(<<|>>>?|==?|!=?|->|[-<>+*%&|^/])=?', Operator, 'slashstartsregex'),
61 (r'[{(\[;,]', Punctuation, 'slashstartsregex'),
62 (r'[})\].]', Punctuation),
63 (r'(for|in|while|do|break|return|continue|switch|case|default|if|else|loop|'
64 r'require|inline|throw|try|catch|finally|new|delete|typeof|instanceof|void|'
65 r'namespace|use|extends|this|fetch|isset|unset|echo|fetch|likely|unlikely|'
66 r'empty)\b', Keyword, 'slashstartsregex'),
67 (r'(var|let|with|function)\b', Keyword.Declaration, 'slashstartsregex'),
68 (r'(abstract|boolean|bool|char|class|const|double|enum|export|extends|final|'
69 r'native|goto|implements|import|int|string|interface|long|ulong|char|uchar|'
70 r'float|unsigned|private|protected|public|short|static|self|throws|reverse|'
71 r'transient|volatile)\b', Keyword.Reserved),
72 (r'(true|false|null|undefined)\b', Keyword.Constant),
73 (r'(Array|Boolean|Date|_REQUEST|_COOKIE|_SESSION|'
74 r'_GET|_POST|_SERVER|this|stdClass|range|count|iterator|'
75 r'window)\b', Name.Builtin),
76 (r'[$a-zA-Z_][\w\\]*', Name.Other),
77 (r'[0-9][0-9]*\.[0-9]+([eE][0-9]+)?[fd]?', Number.Float),
78 (r'0x[0-9a-fA-F]+', Number.Hex),
79 (r'[0-9]+', Number.Integer),
80 (r'"(\\\\|\\"|[^"])*"', String.Double),
81 (r"'(\\\\|\\'|[^'])*'", String.Single),
82 ]
83 }
84
85
86 class PhpLexer(RegexLexer):
87 """
88 For `PHP <http://www.php.net/>`_ source code.
89 For PHP embedded in HTML, use the `HtmlPhpLexer`.
90
91 Additional options accepted:
92
93 `startinline`
94 If given and ``True`` the lexer starts highlighting with
95 php code (i.e.: no starting ``<?php`` required). The default
96 is ``False``.
97 `funcnamehighlighting`
98 If given and ``True``, highlight builtin function names
99 (default: ``True``).
100 `disabledmodules`
101 If given, must be a list of module names whose function names
102 should not be highlighted. By default all modules are highlighted
103 except the special ``'unknown'`` module that includes functions
104 that are known to php but are undocumented.
105
106 To get a list of allowed modules have a look into the
107 `_php_builtins` module:
108
109 .. sourcecode:: pycon
110
111 >>> from pygments.lexers._php_builtins import MODULES
112 >>> MODULES.keys()
113 ['PHP Options/Info', 'Zip', 'dba', ...]
114
115 In fact the names of those modules match the module names from
116 the php documentation.
117 """
118
119 name = 'PHP'
120 aliases = ['php', 'php3', 'php4', 'php5']
121 filenames = ['*.php', '*.php[345]', '*.inc']
122 mimetypes = ['text/x-php']
123
124 # Note that a backslash is included in the following two patterns
125 # PHP uses a backslash as a namespace separator
126 _ident_char = r'[\\\w]|[^\x00-\x7f]'
127 _ident_begin = r'(?:[\\_a-z]|[^\x00-\x7f])'
128 _ident_end = r'(?:' + _ident_char + ')*'
129 _ident_inner = _ident_begin + _ident_end
130
131 flags = re.IGNORECASE | re.DOTALL | re.MULTILINE
132 tokens = {
133 'root': [
134 (r'<\?(php)?', Comment.Preproc, 'php'),
135 (r'[^<]+', Other),
136 (r'<', Other)
137 ],
138 'php': [
139 (r'\?>', Comment.Preproc, '#pop'),
140 (r'<<<([\'"]?)(' + _ident_inner + r')\1\n.*?\n\s*\2;?\n', String),
141 (r'\s+', Text),
142 (r'#.*?\n', Comment.Single),
143 (r'//.*?\n', Comment.Single),
144 # put the empty comment here, it is otherwise seen as
145 # the start of a docstring
146 (r'/\*\*/', Comment.Multiline),
147 (r'/\*\*.*?\*/', String.Doc),
148 (r'/\*.*?\*/', Comment.Multiline),
149 (r'(->|::)(\s*)(' + _ident_inner + ')',
150 bygroups(Operator, Text, Name.Attribute)),
151 (r'[~!%^&*+=|:.<>/@-]+', Operator),
152 (r'\?', Operator), # don't add to the charclass above!
153 (r'[\[\]{}();,]+', Punctuation),
154 (r'(class)(\s+)', bygroups(Keyword, Text), 'classname'),
155 (r'(function)(\s*)(?=\()', bygroups(Keyword, Text)),
156 (r'(function)(\s+)(&?)(\s*)',
157 bygroups(Keyword, Text, Operator, Text), 'functionname'),
158 (r'(const)(\s+)(' + _ident_inner + ')',
159 bygroups(Keyword, Text, Name.Constant)),
160 (r'(and|E_PARSE|old_function|E_ERROR|or|as|E_WARNING|parent|'
161 r'eval|PHP_OS|break|exit|case|extends|PHP_VERSION|cfunction|'
162 r'FALSE|print|for|require|continue|foreach|require_once|'
163 r'declare|return|default|static|do|switch|die|stdClass|'
164 r'echo|else|TRUE|elseif|var|empty|if|xor|enddeclare|include|'
165 r'virtual|endfor|include_once|while|endforeach|global|__FILE__|'
166 r'endif|list|__LINE__|endswitch|new|__sleep|endwhile|not|'
167 r'array|__wakeup|E_ALL|NULL|final|php_user_filter|interface|'
168 r'implements|public|private|protected|abstract|clone|try|'
169 r'catch|throw|this|use|namespace|trait|yield|'
170 r'finally)\b', Keyword),
171 (r'(true|false|null)\b', Keyword.Constant),
172 (r'\$\{\$+' + _ident_inner + '\}', Name.Variable),
173 (r'\$+' + _ident_inner, Name.Variable),
174 (_ident_inner, Name.Other),
175 (r'(\d+\.\d*|\d*\.\d+)(e[+-]?[0-9]+)?', Number.Float),
176 (r'\d+e[+-]?[0-9]+', Number.Float),
177 (r'0[0-7]+', Number.Oct),
178 (r'0x[a-f0-9]+', Number.Hex),
179 (r'\d+', Number.Integer),
180 (r'0b[01]+', Number.Bin),
181 (r"'([^'\\]*(?:\\.[^'\\]*)*)'", String.Single),
182 (r'`([^`\\]*(?:\\.[^`\\]*)*)`', String.Backtick),
183 (r'"', String.Double, 'string'),
184 ],
185 'classname': [
186 (_ident_inner, Name.Class, '#pop')
187 ],
188 'functionname': [
189 (_ident_inner, Name.Function, '#pop')
190 ],
191 'string': [
192 (r'"', String.Double, '#pop'),
193 (r'[^{$"\\]+', String.Double),
194 (r'\\([nrt"$\\]|[0-7]{1,3}|x[0-9a-f]{1,2})', String.Escape),
195 (r'\$' + _ident_inner + '(\[\S+?\]|->' + _ident_inner + ')?',
196 String.Interpol),
197 (r'(\{\$\{)(.*?)(\}\})',
198 bygroups(String.Interpol, using(this, _startinline=True),
199 String.Interpol)),
200 (r'(\{)(\$.*?)(\})',
201 bygroups(String.Interpol, using(this, _startinline=True),
202 String.Interpol)),
203 (r'(\$\{)(\S+)(\})',
204 bygroups(String.Interpol, Name.Variable, String.Interpol)),
205 (r'[${\\]+', String.Double)
206 ],
207 }
208
209 def __init__(self, **options):
210 self.funcnamehighlighting = get_bool_opt(
211 options, 'funcnamehighlighting', True)
212 self.disabledmodules = get_list_opt(
213 options, 'disabledmodules', ['unknown'])
214 self.startinline = get_bool_opt(options, 'startinline', False)
215
216 # private option argument for the lexer itself
217 if '_startinline' in options:
218 self.startinline = options.pop('_startinline')
219
220 # collect activated functions in a set
221 self._functions = set()
222 if self.funcnamehighlighting:
223 from pygments.lexers._php_builtins import MODULES
224 for key, value in iteritems(MODULES):
225 if key not in self.disabledmodules:
226 self._functions.update(value)
227 RegexLexer.__init__(self, **options)
228
229 def get_tokens_unprocessed(self, text):
230 stack = ['root']
231 if self.startinline:
232 stack.append('php')
233 for index, token, value in \
234 RegexLexer.get_tokens_unprocessed(self, text, stack):
235 if token is Name.Other:
236 if value in self._functions:
237 yield index, Name.Builtin, value
238 continue
239 yield index, token, value
240
241 def analyse_text(text):
242 rv = 0.0
243 if re.search(r'<\?(?!xml)', text):
244 rv += 0.3
245 return rv

eric ide

mercurial