eric6/ThirdParty/Pygments/pygments/lexers/php.py

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

eric ide

mercurial