@vituum/vite-plugin-latte 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (201) hide show
  1. package/README.md +39 -0
  2. package/handler.js +9 -0
  3. package/index.js +138 -0
  4. package/index.php +173 -0
  5. package/latte/AssetFilter.php +11 -0
  6. package/latte/FetchFunction.php +28 -0
  7. package/latte/IconFilter.php +14 -0
  8. package/latte/JsonTag.php +64 -0
  9. package/latte/PlaceholderFunction.php +11 -0
  10. package/latte/RandomColorFunction.php +14 -0
  11. package/latte/TelFilter.php +22 -0
  12. package/package.json +35 -0
  13. package/vendor/autoload.php +7 -0
  14. package/vendor/bin/latte-lint +107 -0
  15. package/vendor/composer/ClassLoader.php +572 -0
  16. package/vendor/composer/InstalledVersions.php +350 -0
  17. package/vendor/composer/LICENSE +21 -0
  18. package/vendor/composer/autoload_classmap.php +183 -0
  19. package/vendor/composer/autoload_namespaces.php +9 -0
  20. package/vendor/composer/autoload_psr4.php +9 -0
  21. package/vendor/composer/autoload_real.php +57 -0
  22. package/vendor/composer/autoload_static.php +193 -0
  23. package/vendor/composer/installed.json +93 -0
  24. package/vendor/composer/installed.php +32 -0
  25. package/vendor/composer/platform_check.php +26 -0
  26. package/vendor/latte/latte/bin/latte-lint +29 -0
  27. package/vendor/latte/latte/composer.json +53 -0
  28. package/vendor/latte/latte/license.md +60 -0
  29. package/vendor/latte/latte/ncs.php +14 -0
  30. package/vendor/latte/latte/ncs.xml +9 -0
  31. package/vendor/latte/latte/readme.md +21 -0
  32. package/vendor/latte/latte/src/Bridges/Tracy/BlueScreenPanel.php +114 -0
  33. package/vendor/latte/latte/src/Bridges/Tracy/LattePanel.php +99 -0
  34. package/vendor/latte/latte/src/Bridges/Tracy/templates/LattePanel.panel.phtml +98 -0
  35. package/vendor/latte/latte/src/Bridges/Tracy/templates/LattePanel.tab.phtml +15 -0
  36. package/vendor/latte/latte/src/Latte/Compiler/Block.php +44 -0
  37. package/vendor/latte/latte/src/Latte/Compiler/Escaper.php +244 -0
  38. package/vendor/latte/latte/src/Latte/Compiler/ExpressionBuilder.php +128 -0
  39. package/vendor/latte/latte/src/Latte/Compiler/Node.php +28 -0
  40. package/vendor/latte/latte/src/Latte/Compiler/NodeHelpers.php +132 -0
  41. package/vendor/latte/latte/src/Latte/Compiler/NodeTraverser.php +77 -0
  42. package/vendor/latte/latte/src/Latte/Compiler/Nodes/AreaNode.php +17 -0
  43. package/vendor/latte/latte/src/Latte/Compiler/Nodes/AuxiliaryNode.php +27 -0
  44. package/vendor/latte/latte/src/Latte/Compiler/Nodes/FragmentNode.php +59 -0
  45. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/AttributeNode.php +48 -0
  46. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/BogusTagNode.php +46 -0
  47. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/CommentNode.php +39 -0
  48. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/ElementNode.php +129 -0
  49. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/QuotedValue.php +53 -0
  50. package/vendor/latte/latte/src/Latte/Compiler/Nodes/NopNode.php +21 -0
  51. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ArgumentNode.php +45 -0
  52. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ComplexTypeNode.php +17 -0
  53. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ArrayAccessNode.php +41 -0
  54. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ArrayItemNode.php +52 -0
  55. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ArrayNode.php +94 -0
  56. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AssignNode.php +39 -0
  57. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AssignOpNode.php +45 -0
  58. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/BinaryOpNode.php +65 -0
  59. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/CastNode.php +43 -0
  60. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ClassConstantFetchNode.php +42 -0
  61. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/CloneNode.php +36 -0
  62. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ClosureNode.php +73 -0
  63. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ClosureUseNode.php +37 -0
  64. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ConstantFetchNode.php +37 -0
  65. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/EmptyNode.php +36 -0
  66. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ErrorSuppressNode.php +36 -0
  67. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/FilterCallNode.php +39 -0
  68. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/FunctionCallNode.php +45 -0
  69. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/FunctionCallableNode.php +39 -0
  70. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/InRangeNode.php +42 -0
  71. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/InstanceofNode.php +40 -0
  72. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/IssetNode.php +40 -0
  73. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/MatchNode.php +49 -0
  74. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/MethodCallNode.php +50 -0
  75. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/MethodCallableNode.php +42 -0
  76. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/NewNode.php +45 -0
  77. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/NotNode.php +36 -0
  78. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PostOpNode.php +43 -0
  79. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PreOpNode.php +43 -0
  80. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PropertyFetchNode.php +42 -0
  81. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticCallNode.php +55 -0
  82. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticCallableNode.php +47 -0
  83. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticPropertyFetchNode.php +42 -0
  84. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/TernaryNode.php +50 -0
  85. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/UnaryOpNode.php +45 -0
  86. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/VariableNode.php +40 -0
  87. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ExpressionNode.php +17 -0
  88. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/FilterNode.php +67 -0
  89. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/IdentifierNode.php +36 -0
  90. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/IntersectionTypeNode.php +39 -0
  91. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/MatchArmNode.php +45 -0
  92. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ModifierNode.php +107 -0
  93. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/NameNode.php +89 -0
  94. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/NullableTypeNode.php +35 -0
  95. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ParameterNode.php +54 -0
  96. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/BooleanNode.php +30 -0
  97. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/EncapsedStringNode.php +80 -0
  98. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/EncapsedStringPartNode.php +30 -0
  99. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/FloatNode.php +63 -0
  100. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/IntegerNode.php +70 -0
  101. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/NullNode.php +29 -0
  102. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/StringNode.php +40 -0
  103. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ScalarNode.php +15 -0
  104. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/SuperiorTypeNode.php +29 -0
  105. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/UnionTypeNode.php +39 -0
  106. package/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/VarLikeIdentifierNode.php +21 -0
  107. package/vendor/latte/latte/src/Latte/Compiler/Nodes/StatementNode.php +15 -0
  108. package/vendor/latte/latte/src/Latte/Compiler/Nodes/TemplateNode.php +34 -0
  109. package/vendor/latte/latte/src/Latte/Compiler/Nodes/TextNode.php +37 -0
  110. package/vendor/latte/latte/src/Latte/Compiler/PhpHelpers.php +227 -0
  111. package/vendor/latte/latte/src/Latte/Compiler/Position.php +43 -0
  112. package/vendor/latte/latte/src/Latte/Compiler/PrintContext.php +334 -0
  113. package/vendor/latte/latte/src/Latte/Compiler/Tag.php +117 -0
  114. package/vendor/latte/latte/src/Latte/Compiler/TagLexer.php +399 -0
  115. package/vendor/latte/latte/src/Latte/Compiler/TagParser.php +388 -0
  116. package/vendor/latte/latte/src/Latte/Compiler/TagParserData.php +580 -0
  117. package/vendor/latte/latte/src/Latte/Compiler/TemplateGenerator.php +206 -0
  118. package/vendor/latte/latte/src/Latte/Compiler/TemplateLexer.php +391 -0
  119. package/vendor/latte/latte/src/Latte/Compiler/TemplateParser.php +448 -0
  120. package/vendor/latte/latte/src/Latte/Compiler/TemplateParserHtml.php +506 -0
  121. package/vendor/latte/latte/src/Latte/Compiler/Token.php +259 -0
  122. package/vendor/latte/latte/src/Latte/Compiler/TokenStream.php +151 -0
  123. package/vendor/latte/latte/src/Latte/ContentType.php +22 -0
  124. package/vendor/latte/latte/src/Latte/Engine.php +591 -0
  125. package/vendor/latte/latte/src/Latte/Essential/Blueprint.php +160 -0
  126. package/vendor/latte/latte/src/Latte/Essential/CachingIterator.php +232 -0
  127. package/vendor/latte/latte/src/Latte/Essential/CoreExtension.php +232 -0
  128. package/vendor/latte/latte/src/Latte/Essential/Filters.php +591 -0
  129. package/vendor/latte/latte/src/Latte/Essential/Nodes/BlockNode.php +161 -0
  130. package/vendor/latte/latte/src/Latte/Essential/Nodes/CaptureNode.php +98 -0
  131. package/vendor/latte/latte/src/Latte/Essential/Nodes/ContentTypeNode.php +74 -0
  132. package/vendor/latte/latte/src/Latte/Essential/Nodes/DebugbreakNode.php +53 -0
  133. package/vendor/latte/latte/src/Latte/Essential/Nodes/DefineNode.php +134 -0
  134. package/vendor/latte/latte/src/Latte/Essential/Nodes/DoNode.php +49 -0
  135. package/vendor/latte/latte/src/Latte/Essential/Nodes/DumpNode.php +58 -0
  136. package/vendor/latte/latte/src/Latte/Essential/Nodes/EmbedNode.php +125 -0
  137. package/vendor/latte/latte/src/Latte/Essential/Nodes/ExtendsNode.php +60 -0
  138. package/vendor/latte/latte/src/Latte/Essential/Nodes/FirstLastSepNode.php +81 -0
  139. package/vendor/latte/latte/src/Latte/Essential/Nodes/ForNode.php +91 -0
  140. package/vendor/latte/latte/src/Latte/Essential/Nodes/ForeachNode.php +155 -0
  141. package/vendor/latte/latte/src/Latte/Essential/Nodes/IfChangedNode.php +141 -0
  142. package/vendor/latte/latte/src/Latte/Essential/Nodes/IfContentNode.php +82 -0
  143. package/vendor/latte/latte/src/Latte/Essential/Nodes/IfNode.php +180 -0
  144. package/vendor/latte/latte/src/Latte/Essential/Nodes/ImportNode.php +49 -0
  145. package/vendor/latte/latte/src/Latte/Essential/Nodes/IncludeBlockNode.php +140 -0
  146. package/vendor/latte/latte/src/Latte/Essential/Nodes/IncludeFileNode.php +81 -0
  147. package/vendor/latte/latte/src/Latte/Essential/Nodes/IterateWhileNode.php +94 -0
  148. package/vendor/latte/latte/src/Latte/Essential/Nodes/NAttrNode.php +105 -0
  149. package/vendor/latte/latte/src/Latte/Essential/Nodes/NClassNode.php +54 -0
  150. package/vendor/latte/latte/src/Latte/Essential/Nodes/NTagNode.php +79 -0
  151. package/vendor/latte/latte/src/Latte/Essential/Nodes/ParametersNode.php +84 -0
  152. package/vendor/latte/latte/src/Latte/Essential/Nodes/PrintNode.php +70 -0
  153. package/vendor/latte/latte/src/Latte/Essential/Nodes/RawPhpNode.php +46 -0
  154. package/vendor/latte/latte/src/Latte/Essential/Nodes/RollbackNode.php +37 -0
  155. package/vendor/latte/latte/src/Latte/Essential/Nodes/SkipNode.php +71 -0
  156. package/vendor/latte/latte/src/Latte/Essential/Nodes/SpacelessNode.php +62 -0
  157. package/vendor/latte/latte/src/Latte/Essential/Nodes/SwitchNode.php +118 -0
  158. package/vendor/latte/latte/src/Latte/Essential/Nodes/TemplatePrintNode.php +39 -0
  159. package/vendor/latte/latte/src/Latte/Essential/Nodes/TemplateTypeNode.php +38 -0
  160. package/vendor/latte/latte/src/Latte/Essential/Nodes/TraceNode.php +35 -0
  161. package/vendor/latte/latte/src/Latte/Essential/Nodes/TranslateNode.php +104 -0
  162. package/vendor/latte/latte/src/Latte/Essential/Nodes/TryNode.php +75 -0
  163. package/vendor/latte/latte/src/Latte/Essential/Nodes/VarNode.php +106 -0
  164. package/vendor/latte/latte/src/Latte/Essential/Nodes/VarPrintNode.php +40 -0
  165. package/vendor/latte/latte/src/Latte/Essential/Nodes/VarTypeNode.php +36 -0
  166. package/vendor/latte/latte/src/Latte/Essential/Nodes/WhileNode.php +81 -0
  167. package/vendor/latte/latte/src/Latte/Essential/Passes.php +115 -0
  168. package/vendor/latte/latte/src/Latte/Essential/RawPhpExtension.php +28 -0
  169. package/vendor/latte/latte/src/Latte/Essential/RollbackException.php +16 -0
  170. package/vendor/latte/latte/src/Latte/Essential/Tracer.php +117 -0
  171. package/vendor/latte/latte/src/Latte/Essential/TranslatorExtension.php +101 -0
  172. package/vendor/latte/latte/src/Latte/Extension.php +97 -0
  173. package/vendor/latte/latte/src/Latte/Helpers.php +96 -0
  174. package/vendor/latte/latte/src/Latte/Loader.php +37 -0
  175. package/vendor/latte/latte/src/Latte/Loaders/FileLoader.php +95 -0
  176. package/vendor/latte/latte/src/Latte/Loaders/StringLoader.php +76 -0
  177. package/vendor/latte/latte/src/Latte/Policy.php +24 -0
  178. package/vendor/latte/latte/src/Latte/PositionAwareException.php +50 -0
  179. package/vendor/latte/latte/src/Latte/Runtime/Block.php +24 -0
  180. package/vendor/latte/latte/src/Latte/Runtime/FilterExecutor.php +151 -0
  181. package/vendor/latte/latte/src/Latte/Runtime/FilterInfo.php +39 -0
  182. package/vendor/latte/latte/src/Latte/Runtime/Filters.php +234 -0
  183. package/vendor/latte/latte/src/Latte/Runtime/Html.php +35 -0
  184. package/vendor/latte/latte/src/Latte/Runtime/HtmlStringable.php +17 -0
  185. package/vendor/latte/latte/src/Latte/Runtime/Template.php +381 -0
  186. package/vendor/latte/latte/src/Latte/Sandbox/Nodes/FunctionCallNode.php +30 -0
  187. package/vendor/latte/latte/src/Latte/Sandbox/Nodes/FunctionCallableNode.php +29 -0
  188. package/vendor/latte/latte/src/Latte/Sandbox/Nodes/MethodCallNode.php +32 -0
  189. package/vendor/latte/latte/src/Latte/Sandbox/Nodes/MethodCallableNode.php +30 -0
  190. package/vendor/latte/latte/src/Latte/Sandbox/Nodes/PropertyFetchNode.php +32 -0
  191. package/vendor/latte/latte/src/Latte/Sandbox/Nodes/SandboxNode.php +73 -0
  192. package/vendor/latte/latte/src/Latte/Sandbox/Nodes/StaticCallNode.php +31 -0
  193. package/vendor/latte/latte/src/Latte/Sandbox/Nodes/StaticCallableNode.php +30 -0
  194. package/vendor/latte/latte/src/Latte/Sandbox/Nodes/StaticPropertyFetchNode.php +32 -0
  195. package/vendor/latte/latte/src/Latte/Sandbox/RuntimeChecker.php +116 -0
  196. package/vendor/latte/latte/src/Latte/Sandbox/SandboxExtension.php +132 -0
  197. package/vendor/latte/latte/src/Latte/Sandbox/SecurityPolicy.php +185 -0
  198. package/vendor/latte/latte/src/Latte/Strict.php +101 -0
  199. package/vendor/latte/latte/src/Latte/attributes.php +24 -0
  200. package/vendor/latte/latte/src/Latte/exceptions.php +69 -0
  201. package/vendor/latte/latte/src/Tools/Linter.php +175 -0
@@ -0,0 +1,399 @@
1
+ <?php
2
+
3
+ /**
4
+ * This file is part of the Latte (https://latte.nette.org)
5
+ * Copyright (c) 2008 David Grudl (https://davidgrudl.com)
6
+ */
7
+
8
+ declare(strict_types=1);
9
+
10
+ namespace Latte\Compiler;
11
+
12
+ use Latte;
13
+ use Latte\CompileException;
14
+ use Latte\RegexpException;
15
+
16
+
17
+ /**
18
+ * Lexer for PHP-like expression language used in tags.
19
+ */
20
+ final class TagLexer
21
+ {
22
+ use Latte\Strict;
23
+
24
+ private const Keywords = [
25
+ 'and' => Token::Php_LogicalAnd,
26
+ 'array' => Token::Php_Array,
27
+ 'clone' => Token::Php_Clone,
28
+ 'default' => Token::Php_Default,
29
+ 'in' => Token::Php_In,
30
+ 'instanceof' => Token::Php_Instanceof,
31
+ 'new' => Token::Php_New,
32
+ 'or' => Token::Php_LogicalOr,
33
+ 'return' => Token::Php_Return,
34
+ 'xor' => Token::Php_LogicalXor,
35
+ 'null' => Token::Php_Null,
36
+ 'true' => Token::Php_True,
37
+ 'false' => Token::Php_False,
38
+ ];
39
+
40
+ private const KeywordsFollowed = [ // must follows ( & =
41
+ 'empty' => Token::Php_Empty,
42
+ 'fn' => Token::Php_Fn,
43
+ 'function' => Token::Php_Function,
44
+ 'isset' => Token::Php_Isset,
45
+ 'list' => Token::Php_List,
46
+ 'match' => Token::Php_Match,
47
+ 'use' => Token::Php_Use,
48
+ ];
49
+
50
+ /** @var Token[] */
51
+ private array $tokens;
52
+ private string $input;
53
+ private int $offset;
54
+ private Position $position;
55
+
56
+
57
+ /** @return Token[] */
58
+ public function tokenize(string $input, ?Position $position = null): array
59
+ {
60
+ $position ??= new Position(1, 1, 0);
61
+ $this->tokens = $this->tokenizePartially($input, $position, 0);
62
+ if ($this->offset !== strlen($input)) {
63
+ $token = str_replace("\n", '\n', substr($input, $this->offset, 10));
64
+ throw new CompileException("Unexpected '$token'", $position);
65
+ }
66
+
67
+ $this->tokens[] = new Token(Token::End, '', $position);
68
+ return $this->tokens;
69
+ }
70
+
71
+
72
+ /** @return Token[] */
73
+ public function tokenizePartially(string $input, Position &$position, int $ofs = null): array
74
+ {
75
+ $this->input = $input;
76
+ $this->offset = $ofs ?? $position->offset;
77
+ $this->position = &$position;
78
+ $this->tokens = [];
79
+ $this->tokenizeCode();
80
+ return $this->tokens;
81
+ }
82
+
83
+
84
+ /** @return Token[]|null */
85
+ public function tokenizeUnquotedString(string $input, Position $position, bool $colon, int $offsetDelta): ?array
86
+ {
87
+ preg_match(
88
+ $colon
89
+ ? '~ ( [./@_a-z0-9#!-] | :(?!:) | \{\$ [_a-z0-9\[\]()>-]+ })++ (?=\s+[!"\'$(\[{,\\|\~\w-] | [,|] | \s*$) ~xAi'
90
+ : '~ ( [./@_a-z0-9#!-] | \{\$ [_a-z0-9\[\]()>-]+ })++ (?=\s+[!"\'$(\[{,\\|\~\w-] | [,:|] | \s*$) ~xAi',
91
+ $input,
92
+ $match,
93
+ offset: $position->offset - $offsetDelta,
94
+ );
95
+ $position = new Position($position->line, $position->column - 1, $position->offset - 1);
96
+ return $match && !is_numeric($match[0])
97
+ ? $this->tokenize('"' . $match[0] . '"', $position)
98
+ : null;
99
+ }
100
+
101
+
102
+ private function tokenizeCode(): void
103
+ {
104
+ $re = <<<'XX'
105
+ ~(?J)(?n) # allow duplicate named groups, no auto capture
106
+ (?(DEFINE) (?<label> [a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]* ) )
107
+
108
+ (?<Php_Whitespace> [ \t\r\n]+ )|
109
+ ( (?<Php_ConstantEncapsedString> ' ) (?<rest> ( \\. | [^'\\] )* ' )? )|
110
+ ( (?<string> " ) .* )|
111
+ ( (?<Php_StartHeredoc> <<< [ \t]* (?: (?&label) | ' (?&label) ' | " (?&label) " ) \r?\n ) .* )|
112
+ ( (?<Php_Comment> /\* ) (?<rest> .*?\*/ )? )|
113
+ (?<Php_Variable> \$ (?&label) )|
114
+ (?<Php_Float>
115
+ ((?&lnum) | (?&dnum)) [eE][+-]? (?&lnum)|
116
+ (?<dnum> (?&lnum)? \. (?&lnum) | (?&lnum) \. (?&lnum)? )
117
+ )|
118
+ (?<Php_Integer>
119
+ 0[xX][0-9a-fA-F]+(_[0-9a-fA-F]+)*|
120
+ 0[bB][01]+(_[01]+)*|
121
+ 0[oO][0-7]+(_[0-7]+)*|
122
+ (?<lnum> [0-9]+(_[0-9]+)* )
123
+ )|
124
+ (?<Php_NameFullyQualified> \\ (?&label) ( \\ (?&label) )* )|
125
+ (?<Php_NameQualified> (?&label) ( \\ (?&label) )+ )|
126
+ (?<Php_Identifier> TRUE \b | FALSE \b | NULL \b )|
127
+ (?<Php_Constant> [A-Z_][A-Z0-9_]{2,} \b)|
128
+ (?<Php_IdentifierFollowed> (?&label) (?= [ \t\r\n]* [(&=] ) )|
129
+ (?<Php_Identifier> (?&label)(--?[a-zA-Z0-9_\x80-\xff]+)* )|
130
+ (
131
+ (
132
+ (?<Php_ObjectOperator> -> )|
133
+ (?<Php_NullsafeObjectOperator> \?-> )|
134
+ (?<Php_UndefinedsafeObjectOperator> \?\?-> )
135
+ )
136
+ (?<Php_Whitespace> [ \t\r\n]+ )?
137
+ (?<Php_Identifier> (?&label) )?
138
+ )|
139
+ (?<Php_DoubleArrow> => )|
140
+ (?<Php_PlusEqual> \+= )|
141
+ (?<Php_MinusEqual> -= )|
142
+ (?<Php_MulEqual> \*= )|
143
+ (?<Php_DivEqual> /= )|
144
+ (?<Php_ConcatEqual> \.= )|
145
+ (?<Php_ModEqual> %= )|
146
+ (?<Php_AndEqual> &= )|
147
+ (?<Php_OrEqual> \|= )|
148
+ (?<Php_XorEqual> \^= )|
149
+ (?<Php_SlEqual> <<= )|
150
+ (?<Php_SrEqual> >>= )|
151
+ (?<Php_PowEqual> \*\*= )|
152
+ (?<Php_CoalesceEqual> \?\?= )|
153
+ (?<Php_Coalesce> \?\? )|
154
+ (?<Php_BooleanOr> \|\| )|
155
+ (?<Php_BooleanAnd> && )|
156
+ (?<Php_AmpersandFollowed> & (?= [ \t\r\n]* (\$|\.\.\.) ) )|
157
+ (?<Php_AmpersandNotFollowed> & )|
158
+ (?<Php_IsIdentical> === )|
159
+ (?<Php_IsNotIdentical> !== )|
160
+ (?<Php_IsEqual> == )|
161
+ (?<Php_IsNotEqual> != | <> )|
162
+ (?<Php_Spaceship> <=> )|
163
+ (?<Php_IsSmallerOrEqual> <= )|
164
+ (?<Php_IsGreaterOrEqual> >= )|
165
+ (?<Php_Sl> << )|
166
+ (?<Php_Sr> >> )|
167
+ (?<Php_Inc> \+\+ )|
168
+ (?<Php_Dec> -- )|
169
+ (?<Php_Pow> \*\* )|
170
+ (?<Php_PaamayimNekudotayim> :: )|
171
+ (?<Php_NsSeparator> \\ )|
172
+ (?<Php_Ellipsis> \.\.\. )|
173
+ (?<Php_IntCast> \( [ \t]* int [ \t]* \) )|
174
+ (?<Php_FloatCast> \( [ \t]* float [ \t]* \) )|
175
+ (?<Php_StringCast> \( [ \t]* string [ \t]* \) )|
176
+ (?<Php_ArrayCast> \( [ \t]* array [ \t]* \) )|
177
+ (?<Php_ObjectCast> \( [ \t]* object [ \t]* \) )|
178
+ (?<Php_BoolCast> \( [ \t]* bool [ \t]* \) )|
179
+ (?<Php_ExpandCast> \( [ \t]* expand [ \t]* \) )|
180
+ ( (?<end> /?} ) .* )|
181
+ (?<char> [;:,.|^&+/*=%!\~$<>?@#(){[\]-] )|
182
+ (?<badchar> . )
183
+ ~xsA
184
+ XX;
185
+
186
+ $depth = 0;
187
+ matchRE:
188
+ preg_match_all($re, $this->input, $matches, PREG_SET_ORDER | PREG_UNMATCHED_AS_NULL, $this->offset);
189
+ if (preg_last_error()) {
190
+ throw new RegexpException;
191
+ }
192
+
193
+ foreach ($matches as $m) {
194
+ if (isset($m['char'])) {
195
+ if ($m['char'] === '{') {
196
+ $depth++;
197
+ }
198
+ $this->addToken(null, $m['char']);
199
+
200
+ } elseif (isset($m['end'])) {
201
+ $depth--;
202
+ if ($depth < 0) {
203
+ return;
204
+ }
205
+ foreach (str_split($m['end']) as $ch) {
206
+ $this->addToken(null, $ch);
207
+ }
208
+
209
+ goto matchRE;
210
+
211
+ } elseif (isset($m[$type = 'Php_ObjectOperator'])
212
+ || isset($m[$type = 'Php_NullsafeObjectOperator'])
213
+ || isset($m[$type = 'Php_UndefinedsafeObjectOperator'])
214
+ ) {
215
+ $this->addToken(constant(Token::class . '::' . $type), $m[$type]);
216
+ if (isset($m['Php_Whitespace'])) {
217
+ $this->addToken(Token::Php_Whitespace, $m['Php_Whitespace']);
218
+ }
219
+ if (isset($m['Php_Identifier'])) {
220
+ $this->addToken(Token::Php_Identifier, $m['Php_Identifier']);
221
+ }
222
+
223
+ } elseif (isset($m['Php_Identifier'])) {
224
+ $lower = strtolower($m['Php_Identifier']);
225
+ $this->addToken(self::Keywords[$lower] ?? Token::Php_Identifier, $m['Php_Identifier']);
226
+
227
+ } elseif (isset($m['Php_IdentifierFollowed'])) {
228
+ $lower = strtolower($m['Php_IdentifierFollowed']);
229
+ $this->addToken(self::KeywordsFollowed[$lower] ?? self::Keywords[$lower] ?? Token::Php_Identifier, $m['Php_IdentifierFollowed']);
230
+
231
+ } elseif (isset($m['Php_ConstantEncapsedString'])) {
232
+ isset($m['rest'])
233
+ ? $this->addToken(Token::Php_ConstantEncapsedString, "'" . $m['rest'])
234
+ : throw new CompileException('Unterminated string.', $this->position);
235
+
236
+ } elseif (isset($m['string'])) {
237
+ $pos = $this->position;
238
+ $this->addToken(null, '"');
239
+ $count = count($this->tokens);
240
+ $this->tokenizeString('"');
241
+ $token = $this->tokens[$count] ?? null;
242
+ $this->addToken(null, '"');
243
+ if (
244
+ count($this->tokens) <= $count + 2
245
+ && (!$token || $token->type === Token::Php_EncapsedAndWhitespace)
246
+ ) {
247
+ array_splice($this->tokens, $count - 1, null, [new Token(Token::Php_ConstantEncapsedString, '"' . $token?->text . '"', $pos)]);
248
+ }
249
+ goto matchRE;
250
+
251
+ } elseif (isset($m['Php_Integer'])) {
252
+ $num = PhpHelpers::decodeNumber($m['Php_Integer']);
253
+ $this->addToken(is_float($num) ? Token::Php_Float : Token::Php_Integer, $m['Php_Integer']);
254
+
255
+ } elseif (isset($m['Php_StartHeredoc'])) {
256
+ $this->addToken(Token::Php_StartHeredoc, $m['Php_StartHeredoc']);
257
+ $endRe = '(?<=\n)[ \t]*' . trim($m['Php_StartHeredoc'], "< \t\r\n'\"") . '\b';
258
+ if (str_contains($m['Php_StartHeredoc'], "'")) { // nowdoc
259
+ if (!preg_match('~(.*?)(' . $endRe . ')~sA', $this->input, $m, 0, $this->offset)) {
260
+ throw new CompileException('Unterminated NOWDOC.', $this->position);
261
+ } elseif ($m[1] !== '') {
262
+ $this->addToken(Token::Php_EncapsedAndWhitespace, $m[1]);
263
+ }
264
+ $this->addToken(Token::Php_EndHeredoc, $m[2]);
265
+ } else {
266
+ $end = $this->tokenizeString($endRe);
267
+ $this->addToken(Token::Php_EndHeredoc, $end);
268
+ }
269
+ goto matchRE;
270
+
271
+ } elseif (isset($m['Php_Comment'])) {
272
+ isset($m['rest'])
273
+ ? $this->addToken(Token::Php_Comment, '/*' . $m['rest'])
274
+ : throw new CompileException('Unterminated comment.', $this->position);
275
+
276
+ } elseif (isset($m['badchar'])) {
277
+ throw new CompileException("Unexpected '$m[badchar]'", $this->position);
278
+
279
+ } else {
280
+ foreach ($m as $type => $text) {
281
+ if ($text !== null && !is_int($type)) {
282
+ $this->addToken(constant(Token::class . '::' . $type), $text);
283
+ break;
284
+ }
285
+ }
286
+ }
287
+ }
288
+ }
289
+
290
+
291
+ private function tokenizeString(string $endRe): string
292
+ {
293
+ $re = <<<'XX'
294
+ ~(?J)(?n) # allow duplicate named groups, no auto capture
295
+ (?(DEFINE) (?<label> [a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]* ) )
296
+
297
+ ( (?<Php_CurlyOpen> \{\$ ) .* )|
298
+ (?<Php_DollarOpenCurlyBraces> \$\{ )|
299
+ ( (?<Php_Variable> \$ (?&label) )
300
+ (
301
+ (
302
+ (?<Php_ObjectOperator> -> )|
303
+ (?<Php_NullsafeObjectOperator> \?-> )|
304
+ (?<Php_UndefinedsafeObjectOperator> \?\?-> )
305
+ )
306
+ (?<Php_Identifier> (?&label) )
307
+ |
308
+ (?<offset> \[ )
309
+ (
310
+ (?<offsetVar> \$ (?&label) )|
311
+ (?<offsetString> (?&label) )|
312
+ (?<offsetMinus> - )?
313
+ (?<Php_NumString>
314
+ 0[xX][0-9a-fA-F]+(_[0-9a-fA-F]+)*|
315
+ 0[bB][01]+(_[01]+)*|
316
+ 0[oO][0-7]+(_[0-7]+)*|
317
+ [0-9]+(_[0-9]+)*
318
+ )
319
+ )?
320
+ (?<offsetEnd> ] )?
321
+ |
322
+ )
323
+ )|
324
+ XX . "
325
+ ((?<end> $endRe ) .* )|
326
+ (?<char> ( \\\\. | [^\\\\] ) )
327
+ ~xsA";
328
+
329
+ matchRE:
330
+ preg_match_all($re, $this->input, $matches, PREG_SET_ORDER | PREG_UNMATCHED_AS_NULL, $this->offset);
331
+ if (preg_last_error()) {
332
+ throw new RegexpException;
333
+ }
334
+
335
+ $buffer = '';
336
+ foreach ($matches as $m) {
337
+ if (isset($m['char'])) {
338
+ $buffer .= $m['char'];
339
+ continue;
340
+ } elseif ($buffer !== '') {
341
+ $this->addToken(Token::Php_EncapsedAndWhitespace, $buffer);
342
+ $buffer = '';
343
+ }
344
+
345
+ if (isset($m['Php_CurlyOpen'])) {
346
+ $this->addToken(Token::Php_CurlyOpen, '{');
347
+ $this->tokenizeCode();
348
+ if (($this->input[$this->offset] ?? null) === '}') {
349
+ $this->addToken(null, '}');
350
+ }
351
+ goto matchRE;
352
+
353
+ } elseif (isset($m['Php_DollarOpenCurlyBraces'])) {
354
+ throw new CompileException('Syntax ${...} is not supported.', $this->position);
355
+
356
+ } elseif (isset($m['Php_Variable'])) {
357
+ $this->addToken(Token::Php_Variable, $m['Php_Variable']);
358
+ if (isset($m[$type = 'Php_ObjectOperator'])
359
+ || isset($m[$type = 'Php_NullsafeObjectOperator'])
360
+ || isset($m[$type = 'Php_UndefinedsafeObjectOperator'])
361
+ ) {
362
+ $this->addToken(constant(Token::class . '::' . $type), $m[$type]);
363
+ $this->addToken(Token::Php_Identifier, $m['Php_Identifier']);
364
+
365
+ } elseif (isset($m['offset'])) {
366
+ $this->addToken(null, '[');
367
+ if (!isset($m['offsetEnd'])) {
368
+ throw new CompileException("Missing ']'", $this->position);
369
+ } elseif (isset($m['offsetVar'])) {
370
+ $this->addToken(Token::Php_Variable, $m['offsetVar']);
371
+ } elseif (isset($m['offsetString'])) {
372
+ $this->addToken(Token::Php_Identifier, $m['offsetString']);
373
+ } elseif (isset($m['Php_NumString'])) {
374
+ if (isset($m['offsetMinus'])) {
375
+ $this->addToken(null, '-');
376
+ }
377
+ $this->addToken(Token::Php_NumString, $m['Php_NumString']);
378
+ } else {
379
+ throw new CompileException("Unexpected '" . substr($this->input, $this->offset - 1, 5) . "'", $this->position);
380
+ }
381
+ $this->addToken(null, ']');
382
+ }
383
+
384
+ } elseif (isset($m['end'])) {
385
+ return $m['end'];
386
+ }
387
+ }
388
+
389
+ throw new CompileException('Unterminated string.', $this->position->advance($buffer));
390
+ }
391
+
392
+
393
+ private function addToken(?int $type, string $text): void
394
+ {
395
+ $this->tokens[] = new Token($type ?? ord($text), $text, $this->position);
396
+ $this->position = $this->position->advance($text);
397
+ $this->offset += strlen($text);
398
+ }
399
+ }