diff --git a/src/Latte/Compiler/Nodes/Php/Expression/FilterCallNode.php b/src/Latte/Compiler/Nodes/Php/Expression/FilterCallNode.php index 966a9fe01..1d25c363f 100644 --- a/src/Latte/Compiler/Nodes/Php/Expression/FilterCallNode.php +++ b/src/Latte/Compiler/Nodes/Php/Expression/FilterCallNode.php @@ -25,9 +25,25 @@ public function __construct( } - public function print(PrintContext $context): string + public function print(PrintContext $context, ?callable $outer = null): string { - return $this->filter->printSimple($context, $this->expr->print($context)); + $outer ??= fn($x) => $x; + return $this->expr instanceof self + ? $this->expr->print( + $context, + fn(string $expr) => $this->printExpr($context, $expr, $outer) + ) + : $this->printExpr($context, $this->expr->print($context), $outer); + } + + + private function printExpr(PrintContext $context, string $expr, callable $outer): string + { + return $this->filter->nullsafe + ? '(($ʟ_fv = ' . $expr . ') === null ? null : ' + . $outer($this->filter->printSimple($context, '$ʟ_fv')) + . ')' + : $outer($this->filter->printSimple($context, $expr)); } diff --git a/src/Latte/Compiler/Nodes/Php/FilterNode.php b/src/Latte/Compiler/Nodes/Php/FilterNode.php index 666f67c72..5b1071cdd 100644 --- a/src/Latte/Compiler/Nodes/Php/FilterNode.php +++ b/src/Latte/Compiler/Nodes/Php/FilterNode.php @@ -20,6 +20,7 @@ public function __construct( public IdentifierNode $name, /** @var ArgumentNode[] */ public array $args = [], + public bool $nullsafe = false, public ?Position $position = null, ) { (function (ArgumentNode ...$args) {})(...$args); diff --git a/src/Latte/Compiler/TagLexer.php b/src/Latte/Compiler/TagLexer.php index 936c41a2f..a01ee9897 100644 --- a/src/Latte/Compiler/TagLexer.php +++ b/src/Latte/Compiler/TagLexer.php @@ -145,6 +145,7 @@ private function tokenizeCode(): void (? \*\*= )| (? \?\?= )| (? \?\? )| + (? \?\| )| (? \|\| )| (? && )| (? & (?= [ \t\r\n]* (\$|\.\.\.) ) )| diff --git a/src/Latte/Compiler/TagParserData.php b/src/Latte/Compiler/TagParserData.php index c5a9bdca3..03c9050ce 100644 --- a/src/Latte/Compiler/TagParserData.php +++ b/src/Latte/Compiler/TagParserData.php @@ -26,196 +26,199 @@ abstract class TagParserData /** Rule number signifying that an unexpected token was encountered */ protected const UnexpectedTokenRule = 8191; - protected const Yy2Tblstate = 263; + protected const Yy2Tblstate = 273; /** Number of non-leaf states */ - protected const NumNonLeafStates = 360; + protected const NumNonLeafStates = 368; /** Map of lexer tokens to internal symbols */ protected const TokenToSymbol = [ - 0, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, - 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 48, 108, 113, 109, 47, 113, 113, - 102, 103, 45, 43, 2, 44, 39, 46, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 22, 106, - 35, 7, 37, 21, 59, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, - 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 61, 113, 107, 27, 113, 113, 100, 113, 113, - 113, 98, 101, 113, 113, 113, 113, 113, 113, 99, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, - 113, 113, 113, 104, 26, 105, 50, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, - 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, - 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, - 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, - 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, - 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, - 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 1, 3, 4, 5, - 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 23, 24, 25, 28, 29, 30, - 31, 32, 33, 34, 36, 38, 40, 41, 42, 49, 51, 52, 53, 54, 55, 56, 57, 58, 60, 62, - 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, - 83, 84, 85, 86, 87, 88, 89, 90, 110, 91, 92, 93, 94, 111, 112, 95, 96, 97, + 0, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 47, 109, 114, 110, 46, 114, 114, + 102, 103, 44, 42, 2, 43, 38, 45, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 22, 107, + 34, 7, 36, 21, 58, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 60, 114, 108, 26, 114, 114, 100, 114, 114, + 114, 98, 101, 114, 114, 114, 114, 114, 114, 99, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 104, 106, 105, 49, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 1, 3, 4, 5, + 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 23, 24, 25, 27, 28, 29, + 30, 31, 32, 33, 35, 37, 39, 40, 41, 48, 50, 51, 52, 53, 54, 55, 56, 57, 59, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 88, 89, 111, 90, 91, 92, 93, 112, 113, 94, 95, 96, 97, ]; /** Map of states to a displacement into the self::Action table. The corresponding action for this * state/symbol pair is self::Action[self::ActionBase[$state] + $symbol]. If self::ActionBase[$state] is 0, the * action is defaulted, i.e. self::ActionDefault[$state] should be used instead. */ protected const ActionBase = [ - 297, 326, 326, 326, 326, 99, 121, 326, 273, 177, 230, 326, 406, 406, 406, 406, 406, 256, 256, 256, - 256, 296, 296, 295, 298, 402, 403, 404, 405, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, - -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, - -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, - -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, - -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, 145, 214, 235, 416, 432, 427, 436, 462, 463, 460, - 466, 472, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 137, 182, 528, 213, - 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 549, 549, 549, - 437, 362, 204, 412, 38, 110, 110, 513, 513, 513, 513, 513, 447, 447, 447, 447, 81, 81, 81, 81, - 500, 500, 271, 271, 271, 271, 271, 271, 271, 271, 271, 272, 135, 135, 454, 13, 275, 275, 275, 228, - 228, 228, 228, 228, 181, 108, 108, 108, 236, 355, 409, 285, 207, 207, 207, 207, 207, 207, 304, 473, - -21, 132, 132, 205, 167, 167, 132, 378, -13, 122, -34, 208, 332, 221, 143, 158, 2, 411, 259, 277, - 303, 142, 142, 142, 142, 256, 450, 450, 256, 256, 256, 64, 64, 64, 147, 180, 39, 309, 133, 445, - 309, 309, 309, 42, 26, -74, 357, 268, 352, 354, 62, 98, 65, 360, 363, 357, 357, 104, 65, 65, - 291, 290, 312, 134, 76, 312, 294, 294, 109, 35, 374, 369, 375, 351, 344, 451, 240, 253, 292, 288, - 342, 316, 252, 374, 369, 375, 278, 6, 337, 299, 299, 299, 299, 299, 299, 299, 299, 299, 299, 240, - 468, 36, 317, 376, 385, 17, 397, 398, 453, 300, 455, 299, 305, 331, 306, 469, 341, 24, 240, 470, - 408, 287, 319, 329, 395, 301, 471, 400, 310, 457, 140, 386, 185, 458, 198, 452, 260, 401, 467, 459, - 0, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, - -43, -43, -43, -43, -43, -43, -43, -43, -43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 317, 363, 363, 363, 363, 98, 151, 363, 310, 204, 257, 363, 442, 442, 442, 442, 442, 240, 240, 240, + 240, 336, 336, 303, 341, 407, 408, 409, 410, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, + -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, + -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, + -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, + -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, 323, 297, 302, 420, 423, 422, 424, 437, 438, 436, + 441, 459, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 148, 35, 352, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 349, 349, 349, + 322, 41, 179, 448, -41, 109, 109, 548, 548, 548, 548, 548, 483, 483, 483, 483, 483, 483, 483, 483, + 81, 81, 81, 81, 536, 536, 39, 39, 39, 39, 39, 39, 39, 39, 39, 218, 49, 49, 318, 121, + 56, 56, 56, 12, 12, 12, 12, 12, 215, 205, 205, 205, 154, 210, 260, 333, 129, 129, 129, 129, + 129, 129, 346, 461, 313, 316, 316, 391, 230, 230, 316, 47, 123, -46, 62, 87, 229, 299, 300, 220, + 185, 419, 326, 328, 353, 26, 26, 26, 26, 26, 26, 26, 26, 304, 240, 386, 386, 240, 240, 240, + 100, 175, 175, 175, -31, 149, -28, 238, 296, 430, 296, 296, 296, 32, 184, -70, 379, 376, 377, 127, + 178, 155, 380, 382, 379, 379, 193, 155, 155, 345, 358, 343, 217, 159, 343, 331, 331, 196, 72, 387, + 383, 389, 375, 374, 340, 214, 256, 344, 338, 373, 284, 387, 383, 389, 339, 17, 350, 319, 319, 319, + 319, 319, 319, 319, 319, 319, 319, 214, 428, 107, 354, 390, 392, 31, 398, 399, 388, 332, 429, 319, + 342, 348, 329, 446, 372, 34, 214, 457, 330, 394, 443, 294, 397, 337, 458, 402, 347, 433, 268, 393, + 280, 434, 295, 431, 309, 403, 440, 435, 0, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, + -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 0, 447, 52, 52, 52, 52, 52, 52, 52, 0, 0, 0, 0, 108, 108, 108, 108, - -22, -22, -22, -22, -22, -22, -22, -22, -22, -22, -22, 108, -22, -22, -22, -22, -22, -22, -22, -22, - -22, -22, -22, -22, 0, 0, 0, 0, 0, 0, 0, 378, 294, 294, 294, 294, 294, 294, 378, 378, - 0, 0, 0, 0, 108, 108, 0, 0, 378, 294, 0, 0, 0, 0, 0, 0, 0, 256, 256, 256, - 378, 0, 0, 0, 0, 0, 294, 294, 0, 0, 0, 0, 0, 0, 0, 0, 0, 299, 0, 36, - 299, 299, 299, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 0, 483, 52, 52, 52, 52, 52, 52, 52, + 0, 0, 0, 0, 0, 0, 0, 0, 205, 205, 205, 205, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 205, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 0, 0, 0, 0, + 0, 0, 0, 123, 331, 331, 331, 331, 331, 331, 123, 123, 0, 0, 0, 0, 205, 205, 0, 0, + 0, 123, 331, 0, 0, 0, 0, 0, 0, 240, 240, 240, 123, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 331, 331, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 319, 107, 319, 319, + 319, ]; /** Table of actions. Indexed according to self::ActionBase comment. */ protected const Action = [ - 35, 36, -268, 33, -268, 37, -50, 38, 182, 183, 39, 40, 41, 42, 43, 44, 45, -48, 1, 196, - 46, 562, 563, 208, -47, 544, 387, -221, 16, 560, 290, 527, 248, 249, 199, 0, 291, 292, 7, -47, - -219, 293, 294, 211, 542, 181, 544, -221, -221, -221, 546, 545, 568, 566, 567, 55, 56, 57, -8190, 30, - -219, -219, -219, 422, 11, 227, 295, 15, 200, -219, 201, 546, 545, 24, 571, 58, 59, 60, 22, 61, - 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, - 102, 198, 368, 369, 367, -268, 194, 387, 424, -268, 423, 237, 82, -8190, -8190, -8190, -8191, -8191, -8191, -8191, - 73, 74, 75, 76, 368, 369, 367, 366, 365, 451, 385, -8190, 386, -8190, -8190, -8190, 389, -8190, -8190, -8190, - -8190, 378, 99, -78, 12, -78, 106, 295, 372, 366, 365, 77, 78, 79, 80, 81, 199, 198, -266, 175, - -266, 197, 47, 378, 13, 204, 345, 302, 82, -78, 372, 174, 303, 374, 238, 239, 373, 379, 304, 305, - 368, 369, 367, 197, 47, -8190, -8190, 204, 646, 302, 25, 107, 647, -216, 303, 374, 238, 239, 373, 379, - 304, 305, 433, -22, 108, 366, 365, -8190, -8190, -8190, -8190, -8190, 26, -216, -216, -216, -8190, -8190, -8190, 378, - 18, -264, -216, -264, 433, -8190, 372, -8190, -8190, -8190, 424, -8190, 423, 368, 369, 367, 510, -183, -52, 197, - 47, 20, -222, 204, 14, 302, -78, 96, 210, -183, 303, 374, 238, 239, 373, 379, 304, 305, 366, 365, - 97, -266, -222, -222, -222, -266, 32, 109, 27, 31, -182, -182, 378, 385, -23, 386, 368, 369, 367, 372, - 433, -17, -182, -182, 366, 365, 215, 216, 217, 212, 213, 214, 197, 47, 172, 247, 204, -222, 302, -16, - 19, 366, 365, 303, 374, 238, 239, 373, 379, 304, 305, 100, 74, 75, 76, 378, 295, -222, -222, -222, - 98, 28, 372, 424, -264, 423, -182, 105, -264, 368, 369, 367, 1, 433, 195, 197, 47, 255, -182, 204, - 387, 302, 173, 560, 387, 202, 303, 374, 238, 239, 373, 379, 304, 305, 366, 365, 294, 203, 198, 82, - -8190, 103, 328, 387, 101, -8190, -8190, -8190, 378, 351, 283, 648, 572, 50, -8190, 372, 433, 51, -191, 227, - 295, 397, 164, -8190, 295, -8190, -8190, -8190, 197, 47, 280, 573, 204, 229, 302, 34, 267, 3, 180, 303, - 374, 238, 239, 373, 379, 304, 305, 246, -251, 368, 369, 367, -250, 251, 252, 253, -218, 48, 49, 17, - 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, -249, 366, 365, -218, -218, -218, -225, - -8190, -8190, -8190, -224, -223, -218, 2, 387, 378, 635, 368, 369, 367, 4, 5, 372, 6, -225, -8190, 8, - -8190, -8190, 9, 473, 475, 10, 23, 186, 197, 47, -217, 29, 204, -216, 302, 199, 52, 53, 192, 303, - 374, 238, 239, 373, 379, 304, 305, 193, 245, 378, -217, -217, -217, -216, -216, -216, 372, 101, 282, -217, - 515, 558, -216, 434, 530, 536, 538, 540, 590, 371, 370, -224, 21, 382, -29, 383, -8190, -8190, -8190, 336, - 375, 374, 377, 376, 373, 379, 380, 381, 366, 365, 340, -8190, -8190, -8190, -8190, 549, -8190, -8190, -8190, 516, - -8190, -8190, -8190, -8191, -8191, -8191, -8191, -8191, 615, 424, 104, 423, -8190, -8190, -8190, 54, 265, -29, 643, 295, - 645, 1, 398, 644, 526, 348, 255, 642, 599, 387, -8190, 613, 560, 359, 0, 557, 587, 603, 638, 353, - 0, 561, 0, 0, 293, 294, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 50, 0, 0, 0, 0, 0, 227, 295, + 35, 36, -8190, -8190, -8190, 37, 33, 38, 186, 187, 39, 40, 41, 42, 43, 44, 45, -50, 1, 200, + 46, 574, 575, 212, -8190, 556, 395, 395, 12, 572, 299, -48, 257, 258, -47, 539, 300, 301, -8190, -8190, + 583, 302, 303, 215, -8190, -8190, -8190, -78, 13, -78, 558, 557, 580, 578, 579, 55, 56, 57, -187, 204, + 30, -186, -8190, 99, -8190, -8190, -8190, 232, 304, 304, 203, -187, 0, 24, -186, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 1, + 202, 376, 377, 375, 266, 353, 432, 395, 431, 7, 572, 82, -8190, -8190, -8190, -8191, -8191, -8191, -8191, 73, + 74, 75, 76, 303, 395, 374, 373, 658, 14, 11, -8190, 659, -8190, -8190, -8190, -8190, -8190, -8190, 205, 386, + -8190, 50, 203, 432, -78, 431, 380, -225, 232, 304, -78, -8190, -52, -78, 376, 377, 375, 15, 51, 201, + 47, 22, 554, 208, 556, 310, 304, -225, -225, -225, 311, 382, 242, 243, 381, 387, 312, 313, 374, 373, + 102, 430, -8190, -8190, -8190, -272, 16, -272, 25, 558, 557, 395, 386, 647, 393, 198, 394, 172, 241, 380, + -8190, 441, -8190, -8190, -8190, -8190, 173, 376, 377, 375, 23, 190, 201, 47, -226, 432, 208, 431, 310, 397, + -270, 96, -270, 311, 382, 242, 243, 381, 387, 312, 313, 374, 373, 100, -226, -226, -226, -22, -47, 304, + 393, 26, 394, -186, 185, 386, 174, 77, 78, 79, 80, 81, 380, 202, 441, 175, -186, 74, 75, 76, + 376, 377, 375, 97, 82, 201, 47, 374, 373, 208, -222, 310, -8190, -8190, 106, -226, 311, 382, 242, 243, + 381, 387, 312, 313, 374, 373, 107, 463, -272, 31, -222, -222, -222, -272, 27, -226, -226, -226, 386, -222, + -268, 108, -268, 18, -186, 380, -23, 441, 20, 216, 217, 218, -229, 376, 377, 375, 109, -186, 201, 47, + -221, 207, 208, -270, 310, -8190, -8190, -8190, -270, 311, 382, 242, 243, 381, 387, 312, 313, 374, 373, 203, + -221, -221, -221, -8190, 202, -8190, -8190, 28, -17, -221, -16, 386, -8190, -8190, -8190, -8190, -8190, -8190, 380, 234, + 441, 19, -228, 98, 105, 199, 376, 377, 375, 336, -8190, 201, 47, -223, 104, 208, -220, 310, 82, 261, + 262, 263, 311, 382, 242, 243, 381, 387, 312, 313, 374, 373, 103, -223, -223, -223, -220, -220, -220, 395, + 101, 178, -223, -268, 386, -220, 660, 522, -268, 292, 179, 380, 432, 441, 431, 34, 260, 3, 184, 584, + 176, -29, 359, -8190, 201, 47, 214, -195, 208, 177, 310, -255, 585, 164, 21, 311, 382, 242, 243, 381, + 387, 312, 313, 255, 54, 376, 377, 375, 405, -254, -253, 32, -229, 48, 49, 17, 83, 84, 85, 86, + 87, 88, 89, 90, 91, 92, 93, 94, 95, 374, 373, 219, 220, 221, -228, -227, 2, 4, 5, 6, + 256, 8, 9, 386, 10, 29, 376, 377, 375, 52, 380, 53, 196, 655, 197, 254, 304, 289, 485, 487, + 291, 527, 570, 201, 47, 442, 542, 208, -220, 310, 548, 550, 552, 602, 311, 382, 242, 243, 381, 387, + 312, 313, -29, 344, 386, 348, 561, 528, -220, -220, -220, 380, 101, 627, 657, 275, 569, -220, 406, 656, + 538, 356, 654, 611, 379, 378, 625, 367, 390, 206, 391, -8190, -8190, -8190, 599, 383, 382, 385, 384, 381, + 387, 388, 389, 374, 373, 615, 650, 361, 0, -8190, 573, -8190, -8190, -8190, -8190, -8190, -8190, -8191, -8191, -8191, + -8191, -8191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 266, 0, 0, 395, 0, 0, 572, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 302, + 303, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 0, + 0, 0, 0, 0, 0, 232, 304, ]; /** Table indexed analogously to self::Action. If self::ActionCheck[self::ActionBase[$state] + $symbol] != $symbol * then the action is defaulted, i.e. self::ActionDefault[$state] should be used instead. */ protected const ActionCheck = [ - 43, 44, 0, 77, 2, 48, 0, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 0, 61, 62, - 63, 64, 65, 66, 0, 68, 69, 61, 2, 72, 73, 105, 75, 76, 21, 0, 79, 80, 2, 0, - 61, 84, 85, 86, 66, 6, 68, 81, 82, 83, 93, 94, 95, 96, 97, 3, 4, 5, 71, 102, - 81, 82, 83, 85, 2, 108, 109, 2, 26, 90, 28, 93, 94, 21, 87, 23, 24, 25, 2, 27, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 2, 49, 3, 4, 5, 103, 2, 69, 95, 107, 97, 2, 60, 3, 4, 5, 35, 36, 37, 38, - 39, 40, 41, 42, 3, 4, 5, 28, 29, 103, 66, 21, 68, 23, 24, 25, 2, 27, 28, 29, - 3, 42, 104, 0, 2, 2, 6, 109, 49, 28, 29, 43, 44, 45, 46, 47, 21, 49, 0, 26, - 2, 62, 63, 42, 22, 66, 44, 68, 60, 26, 49, 26, 73, 74, 75, 76, 77, 78, 79, 80, - 3, 4, 5, 62, 63, 3, 4, 66, 66, 68, 91, 6, 70, 61, 73, 74, 75, 76, 77, 78, - 79, 80, 103, 22, 6, 28, 29, 3, 4, 5, 43, 44, 91, 81, 82, 83, 3, 4, 5, 42, - 6, 0, 90, 2, 103, 21, 49, 23, 24, 25, 95, 27, 97, 3, 4, 5, 103, 90, 103, 62, - 63, 6, 61, 66, 102, 68, 103, 7, 103, 102, 73, 74, 75, 76, 77, 78, 79, 80, 28, 29, - 7, 103, 81, 82, 83, 107, 61, 7, 91, 61, 90, 90, 42, 66, 22, 68, 3, 4, 5, 49, - 103, 22, 102, 102, 28, 29, 81, 82, 83, 81, 82, 83, 62, 63, 26, 90, 66, 61, 68, 22, - 22, 28, 29, 73, 74, 75, 76, 77, 78, 79, 80, 104, 40, 41, 42, 42, 109, 81, 82, 83, - 22, 91, 49, 95, 103, 97, 90, 22, 107, 3, 4, 5, 61, 103, 22, 62, 63, 66, 102, 66, - 69, 68, 26, 72, 69, 26, 73, 74, 75, 76, 77, 78, 79, 80, 28, 29, 85, 28, 49, 60, - 85, 61, 67, 69, 91, 3, 4, 5, 42, 78, 74, 70, 87, 102, 71, 49, 103, 102, 90, 108, - 109, 91, 90, 21, 109, 23, 24, 25, 62, 63, 103, 87, 66, 61, 68, 98, 99, 100, 101, 73, - 74, 75, 76, 77, 78, 79, 80, 90, 102, 3, 4, 5, 102, 81, 82, 83, 61, 91, 92, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 102, 28, 29, 81, 82, 83, 102, - 3, 4, 5, 102, 102, 90, 102, 69, 42, 71, 3, 4, 5, 102, 102, 49, 102, 102, 21, 102, - 23, 24, 102, 51, 52, 102, 88, 89, 62, 63, 61, 102, 66, 61, 68, 21, 102, 102, 102, 73, - 74, 75, 76, 77, 78, 79, 80, 102, 102, 42, 81, 82, 83, 81, 82, 83, 49, 91, 103, 90, - 103, 103, 90, 103, 103, 103, 103, 103, 103, 62, 63, 102, 104, 66, 103, 68, 3, 4, 5, 103, - 73, 74, 75, 76, 77, 78, 79, 80, 28, 29, 103, 3, 4, 5, 21, 103, 23, 24, 25, 103, - 27, 28, 29, 30, 31, 32, 33, 34, 103, 95, 22, 97, 3, 4, 5, 104, 104, 103, 105, 109, - 105, 61, 105, 105, 105, 105, 66, 105, 105, 69, 21, 105, 72, 106, -1, 107, 107, 107, 107, 107, - -1, 108, -1, -1, 84, 85, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 102, -1, -1, -1, -1, -1, 108, 109, + 42, 43, 3, 4, 5, 47, 76, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 0, 60, 61, + 62, 63, 64, 65, 70, 67, 68, 68, 2, 71, 72, 0, 74, 75, 0, 105, 78, 79, 3, 4, + 86, 83, 84, 85, 3, 4, 5, 0, 22, 2, 92, 93, 94, 95, 96, 3, 4, 5, 89, 27, + 102, 89, 21, 104, 23, 24, 25, 109, 110, 110, 21, 102, 0, 21, 102, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 60, + 48, 3, 4, 5, 65, 43, 94, 68, 96, 2, 71, 59, 3, 4, 5, 34, 35, 36, 37, 38, + 39, 40, 41, 84, 68, 27, 28, 65, 102, 2, 21, 69, 23, 24, 25, 26, 27, 28, 106, 41, + 84, 102, 21, 94, 97, 96, 48, 60, 109, 110, 103, 3, 103, 106, 3, 4, 5, 2, 102, 61, + 62, 2, 65, 65, 67, 67, 110, 80, 81, 82, 72, 73, 74, 75, 76, 77, 78, 79, 27, 28, + 2, 84, 3, 4, 5, 0, 2, 2, 90, 92, 93, 68, 41, 70, 65, 2, 67, 97, 2, 48, + 21, 103, 23, 24, 25, 26, 106, 3, 4, 5, 87, 88, 61, 62, 60, 94, 65, 96, 67, 2, + 0, 7, 2, 72, 73, 74, 75, 76, 77, 78, 79, 27, 28, 104, 80, 81, 82, 22, 0, 110, + 65, 90, 67, 89, 6, 41, 97, 42, 43, 44, 45, 46, 48, 48, 103, 106, 102, 39, 40, 41, + 3, 4, 5, 7, 59, 61, 62, 27, 28, 65, 60, 67, 42, 43, 6, 60, 72, 73, 74, 75, + 76, 77, 78, 79, 27, 28, 6, 103, 103, 60, 80, 81, 82, 108, 90, 80, 81, 82, 41, 89, + 0, 6, 2, 6, 89, 48, 22, 103, 6, 80, 81, 82, 102, 3, 4, 5, 7, 102, 61, 62, + 60, 27, 65, 103, 67, 3, 4, 5, 108, 72, 73, 74, 75, 76, 77, 78, 79, 27, 28, 21, + 80, 81, 82, 21, 48, 23, 24, 90, 22, 89, 22, 41, 3, 4, 5, 3, 4, 5, 48, 60, + 103, 22, 102, 22, 22, 22, 3, 4, 5, 66, 21, 61, 62, 60, 22, 65, 60, 67, 59, 80, + 81, 82, 72, 73, 74, 75, 76, 77, 78, 79, 27, 28, 60, 80, 81, 82, 80, 81, 82, 68, + 90, 97, 89, 103, 41, 89, 69, 103, 108, 73, 106, 48, 94, 103, 96, 98, 99, 100, 101, 86, + 97, 103, 77, 70, 61, 62, 103, 89, 65, 106, 67, 102, 86, 89, 104, 72, 73, 74, 75, 76, + 77, 78, 79, 89, 104, 3, 4, 5, 90, 102, 102, 60, 102, 90, 91, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 27, 28, 80, 81, 82, 102, 102, 102, 102, 102, 102, + 89, 102, 102, 41, 102, 102, 3, 4, 5, 102, 48, 102, 102, 105, 102, 102, 110, 103, 50, 51, + 103, 103, 103, 61, 62, 103, 103, 65, 60, 67, 103, 103, 103, 103, 72, 73, 74, 75, 76, 77, + 78, 79, 103, 103, 41, 103, 103, 103, 80, 81, 82, 48, 90, 103, 105, 104, 108, 89, 105, 105, + 105, 105, 105, 105, 61, 62, 105, 107, 65, 106, 67, 3, 4, 5, 108, 72, 73, 74, 75, 76, + 77, 78, 79, 27, 28, 108, 108, 108, -1, 21, 109, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 60, -1, -1, -1, + -1, 65, -1, -1, 68, -1, -1, 71, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 83, + 84, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 102, -1, + -1, -1, -1, -1, -1, 109, 110, ]; /** Map of states to their default action */ protected const ActionDefault = [ - 8191, 262, 262, 31, 262, 8191, 8191, 262, 8191, 8191, 8191, 29, 8191, 8191, 8191, 29, 8191, 8191, 8191, 8191, - 8191, 39, 29, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 214, 214, 214, 8191, 8191, 8191, 8191, 8191, 8191, + 8191, 266, 266, 31, 266, 8191, 8191, 266, 8191, 8191, 8191, 29, 8191, 8191, 8191, 29, 8191, 8191, 8191, 8191, + 8191, 39, 29, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 218, 218, 218, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 10, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, - 8191, 8191, 29, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 263, 263, 8191, 8191, 8191, 8191, 8191, 8191, 8191, - 8191, 8191, 1, 269, 270, 83, 77, 215, 265, 267, 79, 82, 80, 43, 44, 56, 119, 121, 153, 120, - 95, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 93, 94, 165, 154, 152, 151, - 117, 118, 124, 92, 8191, 122, 123, 141, 142, 139, 140, 143, 8191, 8191, 8191, 8191, 144, 145, 146, 147, - 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 125, 69, 69, 69, 8191, 8191, 11, 8191, 8191, - 8191, 8191, 8191, 8191, 205, 131, 132, 134, 205, 204, 149, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, - 210, 114, 116, 188, 126, 127, 96, 8191, 8191, 8191, 209, 8191, 277, 216, 216, 216, 216, 34, 34, 34, - 8191, 88, 88, 88, 88, 34, 8191, 8191, 34, 34, 34, 8191, 8191, 8191, 194, 222, 216, 137, 8191, 8191, - 128, 129, 130, 57, 8191, 8191, 192, 8191, 181, 8191, 28, 28, 28, 8191, 235, 236, 237, 28, 28, 28, - 169, 36, 71, 28, 28, 71, 8191, 8191, 28, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 199, 8191, 220, - 233, 2, 184, 15, 20, 21, 8191, 199, 218, 135, 136, 138, 157, 158, 159, 160, 161, 162, 163, 260, - 8191, 256, 187, 8191, 8191, 216, 8191, 8191, 276, 8191, 216, 133, 8191, 195, 240, 8191, 217, 216, 261, 8191, - 8191, 8191, 59, 60, 8191, 8191, 8191, 8191, 196, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 55, 8191, 8191, 8191, + 8191, 8191, 29, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 267, 267, 8191, 8191, 8191, 8191, 8191, 8191, 8191, + 8191, 8191, 1, 273, 274, 83, 77, 219, 269, 271, 79, 82, 80, 43, 44, 56, 123, 125, 157, 124, + 99, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 97, 98, 169, 158, 156, 155, + 121, 122, 128, 96, 8191, 126, 127, 145, 146, 143, 144, 147, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, + 148, 149, 150, 151, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 129, 69, 69, 69, 8191, + 8191, 11, 8191, 8191, 8191, 8191, 8191, 8191, 209, 135, 136, 138, 209, 208, 153, 8191, 8191, 8191, 8191, 8191, + 8191, 8191, 8191, 8191, 214, 118, 120, 192, 130, 131, 100, 220, 8191, 8191, 8191, 213, 8191, 281, 220, 220, + 220, 34, 34, 34, 8191, 92, 92, 92, 92, 92, 92, 92, 92, 8191, 34, 8191, 8191, 34, 34, 34, + 8191, 8191, 8191, 8191, 198, 2, 226, 220, 141, 8191, 132, 133, 134, 57, 8191, 8191, 196, 185, 8191, 28, + 28, 28, 8191, 239, 240, 241, 28, 28, 28, 173, 36, 71, 28, 28, 71, 8191, 8191, 28, 8191, 8191, + 8191, 8191, 8191, 8191, 8191, 8191, 203, 8191, 224, 237, 188, 15, 20, 21, 8191, 203, 222, 139, 140, 142, + 161, 162, 163, 164, 165, 166, 167, 264, 8191, 260, 191, 8191, 8191, 220, 8191, 8191, 280, 8191, 220, 137, + 8191, 199, 244, 8191, 221, 220, 265, 8191, 8191, 8191, 59, 60, 8191, 8191, 8191, 8191, 200, 8191, 8191, 8191, + 8191, 8191, 8191, 8191, 55, 8191, 8191, 8191, ]; /** Map of non-terminals to a displacement into the self::Goto table. The corresponding goto state for this * non-terminal/state pair is self::Goto[self::GotoBase[$nonTerminal] + $state] (unless defaulted) */ protected const GotoBase = [ - 0, 0, -1, 0, 0, 0, 108, 0, 166, 27, 30, -17, 0, 240, 26, 0, 0, 0, 0, 172, - 213, 65, -2, 243, 17, 60, 0, 62, 0, 77, -79, 0, 0, -63, 1, -261, 104, -11, 0, 0, - -68, 0, 75, 0, 0, 139, 0, 0, 0, 32, 0, 0, 0, 0, -55, -44, 0, 0, 28, 39, - 7, 50, 57, -67, 0, 0, -51, -24, 0, 36, 110, 4, 41, 0, 0, + 0, 0, -1, 0, 0, 0, 108, 0, 130, -60, 35, -27, 0, 111, -59, 0, 0, 0, 0, 99, + 95, -50, 1, 116, 22, -33, 0, -2, 0, 56, 68, 0, 0, -44, -18, -270, 126, -11, 0, 0, + -104, 0, -5, 0, 0, 97, 0, 0, 0, 23, 0, 0, 0, 0, 62, -25, 0, 0, 33, 44, + 7, 55, 24, 82, 0, 0, -51, 63, 0, -4, 112, 4, 80, 0, 0, ]; /** Table of states to goto after reduction. Indexed according to self::GotoBase comment. */ protected const Goto = [ - 112, 112, 111, 112, 436, 436, 112, 535, 537, 327, 111, 617, 539, 589, 591, 592, 140, 128, 129, 128, - 125, 125, 117, 138, 130, 130, 130, 130, 125, 110, 127, 127, 127, 122, 309, 310, 257, 311, 312, 313, - 314, 315, 316, 317, 318, 459, 459, 123, 124, 113, 114, 115, 116, 118, 136, 137, 139, 157, 160, 161, - 162, 165, 166, 167, 168, 169, 170, 171, 176, 177, 178, 179, 191, 205, 206, 207, 224, 225, 260, 261, - 262, 331, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 158, 119, 120, - 130, 131, 121, 159, 132, 133, 156, 134, 135, 184, 184, 184, 184, 334, 259, 184, 278, 279, 264, 184, - 418, 425, 427, 426, 428, 187, 189, 190, 189, 421, 421, 421, 421, 541, 541, 541, 421, 421, 421, 421, - 421, 322, 322, 322, 228, 602, 602, 602, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, 543, - 240, 614, 614, 614, 614, 614, 614, 306, 306, 306, 306, 339, 358, 306, 447, 444, 445, 306, 256, 337, - 221, 222, 233, 325, 330, 226, 234, 235, 236, 275, 276, 604, 605, 606, 402, 600, 600, 307, 307, 559, - 559, 559, 559, 559, 559, 559, 559, 559, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 579, - 579, 579, 579, 579, 579, 579, 579, 579, 579, 579, 308, 308, 308, 308, 308, 308, 308, 308, 308, 308, - 308, 232, 326, 392, 319, 319, 406, 319, 232, 232, 319, 393, 633, 344, 441, 347, 414, 232, 232, 649, - 411, 450, 449, 338, 323, 324, 354, 400, 633, 634, 232, 531, 432, 508, 323, 324, 281, 532, 639, 640, - 641, 634, 607, 608, 219, 0, 355, 0, 185, 185, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 356, 534, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 333, 0, 0, 0, 0, 0, 0, 0, 241, 242, - 243, 244, 0, 0, 0, 395, 395, 395, 0, 0, 0, 0, 0, 395, 0, 0, 395, 395, 395, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 409, 409, + 112, 112, 111, 112, 444, 444, 112, 547, 549, 335, 111, 629, 551, 601, 603, 604, 140, 128, 129, 128, + 125, 125, 117, 138, 130, 130, 130, 130, 125, 110, 127, 127, 127, 122, 317, 318, 268, 319, 320, 321, + 322, 323, 324, 325, 326, 471, 471, 123, 124, 113, 114, 115, 116, 118, 136, 137, 139, 157, 160, 161, + 162, 165, 166, 167, 168, 169, 170, 171, 180, 181, 182, 183, 195, 209, 210, 211, 228, 229, 270, 271, + 272, 339, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 158, 119, 120, + 130, 131, 121, 159, 132, 133, 156, 134, 135, 188, 188, 188, 188, 342, 400, 188, 269, 327, 327, 188, + 327, 410, 401, 327, 334, 191, 193, 194, 193, 347, 366, 314, 314, 314, 314, 414, 346, 314, 287, 288, + 274, 314, 456, 459, 458, 453, 452, 455, 454, 614, 614, 614, 429, 429, 429, 429, 553, 553, 553, 429, + 429, 429, 429, 429, 352, 626, 626, 626, 626, 626, 626, 555, 555, 555, 555, 555, 555, 555, 555, 555, + 555, 555, 555, 331, 332, 267, 345, 225, 226, 238, 333, 338, 230, 231, 239, 240, 422, 520, 331, 332, + 290, 651, 652, 653, 612, 612, 315, 315, 571, 571, 571, 571, 571, 571, 571, 571, 571, 593, 593, 593, + 593, 593, 593, 593, 593, 593, 593, 593, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, 316, + 316, 316, 316, 316, 316, 316, 316, 316, 316, 316, 237, 619, 620, 449, 355, 440, 223, 237, 237, 419, + 462, 461, 330, 330, 330, 362, 408, 237, 237, 661, 543, 426, 435, 433, 434, 436, 363, 544, 0, 237, + 284, 285, 616, 617, 618, 0, 0, 0, 0, 0, 0, 0, 189, 189, 341, 645, 0, 233, 0, 0, + 417, 417, 245, 246, 247, 248, 249, 250, 251, 252, 0, 0, 645, 646, 244, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 646, 0, 0, 0, 0, 0, 364, 546, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 403, 403, 403, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 403, 0, 0, 403, 403, 403, ]; /** Table indexed analogously to self::Goto. If self::GotoCheck[self::GotoBase[$nonTerminal] + $state] != $nonTerminal @@ -226,31 +229,28 @@ abstract class TagParserData 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 66, 70, 6, 36, 36, 36, 6, - 30, 30, 30, 30, 30, 6, 6, 6, 6, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, - 33, 54, 54, 54, 63, 66, 66, 66, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, - 63, 66, 66, 66, 66, 66, 66, 8, 8, 8, 8, 45, 45, 8, 40, 40, 40, 8, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 67, 67, 67, 67, 67, 19, 66, 66, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 59, - 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, - 61, 10, 20, 13, 23, 23, 21, 23, 10, 10, 23, 13, 72, 25, 11, 11, 27, 10, 10, 10, - 11, 11, 11, 23, 14, 14, 11, 11, 72, 72, 10, 11, 29, 42, 14, 14, 14, 49, 9, 9, - 9, 72, 69, 69, 62, -1, 34, -1, 6, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, 10, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, -1, -1, -1, -1, -1, 8, 8, - 8, 8, -1, -1, -1, 6, 6, 6, -1, -1, -1, -1, -1, 6, -1, -1, 6, 6, 6, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 23, 23, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 66, 13, 6, 70, 23, 23, 6, + 23, 19, 13, 23, 20, 6, 6, 6, 6, 45, 45, 8, 8, 8, 8, 21, 23, 8, 36, 36, + 36, 8, 40, 40, 40, 40, 40, 40, 40, 66, 66, 66, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 25, 66, 66, 66, 66, 66, 66, 55, 55, 55, 55, 55, 55, 55, 55, 55, + 55, 55, 55, 14, 14, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 27, 42, 14, 14, + 14, 9, 9, 9, 66, 66, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, + 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 10, 69, 69, 11, 11, 29, 62, 10, 10, 11, + 11, 11, 54, 54, 54, 11, 11, 10, 10, 10, 11, 30, 30, 30, 30, 30, 34, 49, -1, 10, + 67, 67, 67, 67, 67, -1, -1, -1, -1, -1, -1, -1, 6, 6, 8, 72, -1, 63, -1, -1, + 23, 23, 8, 8, 8, 8, 8, 8, 8, 8, -1, -1, 72, 72, 63, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 72, -1, -1, -1, -1, -1, 10, 10, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, 6, 6, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 6, -1, -1, 6, 6, 6, ]; /** Map of non-terminals to the default state to goto after their reduction */ protected const GotoDefault = [ - -8192, 289, 126, 301, 363, 364, 188, 384, 332, 612, 598, 390, 270, 619, 287, 286, 458, 349, 284, 401, - 350, 405, 163, 296, 297, 341, 277, 413, 250, 430, 263, 342, 343, 268, 352, 553, 272, 435, 271, 258, - 446, 457, 266, 524, 285, 335, 528, 357, 288, 533, 588, 269, 298, 273, 550, 254, 223, 299, 230, 220, - 320, 209, 218, 632, 231, 300, 586, 274, 594, 601, 321, 618, 631, 329, 346, + -8192, 298, 126, 265, 371, 372, 192, 392, 340, 624, 610, 398, 279, 631, 296, 295, 470, 357, 293, 409, + 358, 413, 163, 305, 306, 349, 286, 421, 259, 438, 273, 350, 351, 277, 360, 565, 281, 443, 280, 253, + 457, 469, 276, 536, 294, 343, 540, 365, 297, 545, 600, 278, 307, 282, 562, 264, 227, 308, 235, 224, + 328, 213, 222, 644, 236, 309, 598, 283, 606, 613, 329, 630, 643, 337, 354, ]; /** Map of rules to the non-terminal on their left-hand side, i.e. the non-terminal to use for @@ -260,17 +260,17 @@ abstract class TagParserData 7, 7, 8, 8, 8, 9, 9, 10, 11, 11, 4, 4, 12, 12, 14, 14, 15, 15, 16, 17, 17, 18, 18, 19, 19, 5, 5, 21, 21, 21, 21, 25, 25, 26, 26, 27, 27, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 32, 32, 28, 28, 34, 34, 35, 35, 36, 36, 37, 37, 37, - 37, 20, 38, 38, 39, 39, 3, 3, 40, 40, 40, 40, 2, 2, 2, 2, 2, 2, 2, 2, + 37, 20, 38, 38, 39, 39, 39, 39, 3, 3, 3, 3, 40, 40, 40, 40, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 41, 44, 44, 47, 48, 48, 49, 50, 50, 50, 50, 50, - 50, 54, 33, 33, 55, 55, 55, 42, 42, 42, 52, 52, 46, 46, 58, 59, 59, 24, 61, 61, - 61, 61, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 45, 45, 57, 57, 57, 57, - 64, 64, 64, 51, 51, 51, 65, 65, 65, 65, 65, 65, 65, 22, 22, 22, 22, 22, 66, 66, - 69, 68, 56, 56, 56, 56, 56, 56, 56, 53, 53, 53, 67, 67, 67, 23, 60, 70, 70, 71, - 71, 71, 71, 13, 13, 13, 13, 13, 13, 13, 13, 62, 62, 62, 62, 63, 73, 72, 72, 72, - 72, 72, 72, 72, 72, 72, 74, 74, 74, 74, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 41, 44, 44, 47, 48, 48, 49, 50, + 50, 50, 50, 50, 50, 54, 33, 33, 55, 55, 55, 42, 42, 42, 52, 52, 46, 46, 58, 59, + 59, 24, 61, 61, 61, 61, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 45, 45, + 57, 57, 57, 57, 64, 64, 64, 51, 51, 51, 65, 65, 65, 65, 65, 65, 65, 22, 22, 22, + 22, 22, 66, 66, 69, 68, 56, 56, 56, 56, 56, 56, 56, 53, 53, 53, 67, 67, 67, 23, + 60, 70, 70, 71, 71, 71, 71, 13, 13, 13, 13, 13, 13, 13, 13, 62, 62, 62, 62, 63, + 73, 72, 72, 72, 72, 72, 72, 72, 72, 72, 74, 74, 74, 74, ]; /** Map of rules to the length of their right-hand side, which is the number of elements that have to @@ -280,17 +280,17 @@ abstract class TagParserData 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 2, 0, 1, 3, 0, 1, 0, 1, 7, 0, 2, 1, 3, 3, 4, 1, 3, 1, 2, 1, 1, 2, 0, 1, 3, 4, 6, 1, 2, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 0, 1, 0, 2, 2, 4, 1, 3, 1, 2, 2, - 3, 2, 3, 1, 4, 4, 3, 4, 0, 3, 3, 3, 1, 3, 3, 3, 4, 1, 1, 2, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, 3, 3, 4, 4, 2, 2, 2, - 2, 2, 2, 2, 1, 8, 12, 9, 3, 0, 4, 2, 1, 3, 2, 2, 4, 2, 4, 4, - 6, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 0, 1, 1, 3, 5, 3, 4, 1, - 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 3, 0, 1, 1, 3, 1, 1, - 1, 1, 1, 1, 3, 1, 1, 4, 1, 4, 6, 4, 4, 1, 1, 3, 3, 3, 1, 4, - 1, 3, 1, 4, 3, 3, 3, 3, 3, 1, 3, 1, 1, 3, 1, 4, 1, 3, 1, 1, - 1, 3, 0, 1, 2, 3, 4, 3, 4, 2, 2, 2, 2, 1, 2, 1, 1, 1, 4, 3, - 3, 3, 3, 3, 6, 3, 1, 1, 2, 1, + 3, 2, 3, 1, 4, 4, 4, 4, 3, 3, 4, 4, 0, 3, 3, 3, 1, 3, 3, 3, + 4, 1, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, + 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, 3, 3, 4, + 4, 2, 2, 2, 2, 2, 2, 2, 1, 8, 12, 9, 3, 0, 4, 2, 1, 3, 2, 2, + 4, 2, 4, 4, 6, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 0, 1, 1, 3, + 5, 3, 4, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 3, 0, 1, + 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 1, 4, 1, 4, 6, 4, 4, 1, 1, 3, + 3, 3, 1, 4, 1, 3, 1, 4, 3, 3, 3, 3, 3, 1, 3, 1, 1, 3, 1, 4, + 1, 3, 1, 1, 1, 3, 0, 1, 2, 3, 4, 3, 4, 2, 2, 2, 2, 1, 2, 1, + 1, 1, 4, 3, 3, 3, 3, 3, 6, 3, 1, 1, 2, 1, ]; /** Map of symbols to their names */ @@ -321,7 +321,6 @@ abstract class TagParserData "'??'", "'||'", "'&&'", - "'|'", "'^'", "'&'", "'&'", @@ -393,6 +392,7 @@ abstract class TagParserData "'null'", "'true'", "'false'", + "'?|'", "'e'", "'m'", "'a'", @@ -401,6 +401,7 @@ abstract class TagParserData "')'", "'{'", "'}'", + "'|'", "';'", "']'", "'\"'", @@ -423,15 +424,15 @@ abstract class TagParserData protected function reduce(int $rule, int $pos): void { (match ($rule) { - 0, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 28, 29, 57, 70, 72, 92, 97, 98, 164, 181, 183, 187, 188, 190, 191, 193, 204, 209, 210, 215, 216, 218, 219, 220, 221, 223, 225, 226, 228, 233, 234, 238, 242, 249, 251, 252, 254, 259, 277, 289 => fn() => $this->semValue = $this->semStack[$pos], + 0, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 28, 29, 57, 70, 72, 96, 101, 102, 168, 185, 187, 191, 192, 194, 195, 197, 208, 213, 214, 219, 220, 222, 223, 224, 225, 227, 229, 230, 232, 237, 238, 242, 246, 253, 255, 256, 258, 263, 281, 293 => fn() => $this->semValue = $this->semStack[$pos], 2 => fn() => $this->semValue = new Node\ModifierNode($this->semStack[$pos], position: $this->startTokenStack[$pos]->position), 3 => fn() => $this->semValue = new Expression\ArrayNode($this->semStack[$pos], position: $this->startTokenStack[$pos]->position), 22, 23, 24, 25, 26, 62, 63, 64 => fn() => $this->semValue = new Node\IdentifierNode($this->semStack[$pos], $this->startTokenStack[$pos]->position), 27 => fn() => $this->semValue = new Expression\VariableNode(substr($this->semStack[$pos], 1), $this->startTokenStack[$pos]->position), - 30, 40, 51, 81, 89, 90, 91, 149, 150, 170, 171, 189, 217, 224, 250, 253, 285 => fn() => $this->semValue = $this->semStack[$pos - 1], - 31, 39, 52, 73, 88, 169, 192 => fn() => $this->semValue = [], - 32, 41, 53, 75, 83, 172, 258, 273 => fn() => $this->semValue = [$this->semStack[$pos]], - 33, 42, 54, 66, 68, 76, 82, 173, 257 => function () use ($pos) { + 30, 40, 51, 81, 93, 94, 95, 153, 154, 174, 175, 193, 221, 228, 254, 257, 289 => fn() => $this->semValue = $this->semStack[$pos - 1], + 31, 39, 52, 73, 92, 173, 196 => fn() => $this->semValue = [], + 32, 41, 53, 75, 83, 176, 262, 277 => fn() => $this->semValue = [$this->semStack[$pos]], + 33, 42, 54, 66, 68, 76, 82, 177, 261 => function () use ($pos) { $this->semStack[$pos - 2][] = $this->semStack[$pos]; $this->semValue = $this->semStack[$pos - 2]; }, @@ -452,133 +453,139 @@ protected function reduce(int $rule, int $pos): void 60 => fn() => $this->semValue = new Node\IntersectionTypeNode($this->semStack[$pos], $this->startTokenStack[$pos]->position), 61 => fn() => $this->semValue = TagParser::handleBuiltinTypes($this->semStack[$pos]), 65, 67 => fn() => $this->semValue = [$this->semStack[$pos - 2], $this->semStack[$pos]], - 69, 71, 214 => fn() => $this->semValue = null, + 69, 71, 218 => fn() => $this->semValue = null, 74 => fn() => $this->semValue = $this->semStack[$pos - 2], 77 => fn() => $this->semValue = new Node\ArgumentNode($this->semStack[$pos], false, false, null, $this->startTokenStack[$pos]->position), 78 => fn() => $this->semValue = new Node\ArgumentNode($this->semStack[$pos], true, false, null, $this->startTokenStack[$pos - 1]->position), 79 => fn() => $this->semValue = new Node\ArgumentNode($this->semStack[$pos], false, true, null, $this->startTokenStack[$pos - 1]->position), 80 => fn() => $this->semValue = new Node\ArgumentNode($this->semStack[$pos], false, false, $this->semStack[$pos - 2], $this->startTokenStack[$pos - 2]->position), - 84, 85 => fn() => $this->semValue = new Expression\FilterCallNode($this->semStack[$pos - 3], new Node\FilterNode($this->semStack[$pos - 1], $this->semStack[$pos], $this->startTokenStack[$pos - 3]->position), $this->startTokenStack[$pos - 3]->position), - 86 => fn() => $this->semValue = [new Node\FilterNode($this->semStack[$pos - 1], $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position)], - 87 => function () use ($pos) { - $this->semStack[$pos - 3][] = new Node\FilterNode($this->semStack[$pos - 1], $this->semStack[$pos], $this->startTokenStack[$pos - 3]->position); + 84, 86 => fn() => $this->semValue = new Expression\FilterCallNode($this->semStack[$pos - 3], new Node\FilterNode($this->semStack[$pos - 1], $this->semStack[$pos], false, $this->startTokenStack[$pos - 3]->position), $this->startTokenStack[$pos - 3]->position), + 85, 87 => fn() => $this->semValue = new Expression\FilterCallNode($this->semStack[$pos - 3], new Node\FilterNode($this->semStack[$pos - 1], $this->semStack[$pos], true, $this->startTokenStack[$pos - 3]->position), $this->startTokenStack[$pos - 3]->position), + 88 => fn() => $this->semValue = [new Node\FilterNode($this->semStack[$pos - 1], $this->semStack[$pos], false, $this->startTokenStack[$pos - 2]->position)], + 89 => fn() => $this->semValue = [new Node\FilterNode($this->semStack[$pos - 1], $this->semStack[$pos], true, $this->startTokenStack[$pos - 2]->position)], + 90 => function () use ($pos) { + $this->semStack[$pos - 3][] = new Node\FilterNode($this->semStack[$pos - 1], $this->semStack[$pos], false, $this->startTokenStack[$pos - 3]->position); + $this->semValue = $this->semStack[$pos - 3]; + }, + 91 => function () use ($pos) { + $this->semStack[$pos - 3][] = new Node\FilterNode($this->semStack[$pos - 1], $this->semStack[$pos], true, $this->startTokenStack[$pos - 3]->position); $this->semValue = $this->semStack[$pos - 3]; }, - 93, 95 => fn() => $this->semValue = new Expression\AssignNode($this->semStack[$pos - 2], $this->semStack[$pos], false, $this->startTokenStack[$pos - 2]->position), - 94 => fn() => $this->semValue = new Expression\AssignNode($this->convertArrayToList($this->semStack[$pos - 2]), $this->semStack[$pos], false, $this->startTokenStack[$pos - 2]->position), - 96 => fn() => $this->semValue = new Expression\AssignNode($this->semStack[$pos - 3], $this->semStack[$pos], true, $this->startTokenStack[$pos - 3]->position), - 99 => fn() => $this->semValue = new Expression\CloneNode($this->semStack[$pos], $this->startTokenStack[$pos - 1]->position), - 100 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '+', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 101 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '-', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 102 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '*', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 103 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '/', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 104 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '.', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 105 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '%', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 106 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '&', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 107 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '|', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 108 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '^', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 109 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '<<', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 110 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '>>', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 111 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '**', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 112 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '??', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 113 => fn() => $this->semValue = new Expression\PostOpNode($this->semStack[$pos - 1], '++', $this->startTokenStack[$pos - 1]->position), - 114 => fn() => $this->semValue = new Expression\PreOpNode($this->semStack[$pos], '++', $this->startTokenStack[$pos - 1]->position), - 115 => fn() => $this->semValue = new Expression\PostOpNode($this->semStack[$pos - 1], '--', $this->startTokenStack[$pos - 1]->position), - 116 => fn() => $this->semValue = new Expression\PreOpNode($this->semStack[$pos], '--', $this->startTokenStack[$pos - 1]->position), - 117 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '||', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 118 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '&&', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 119 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], 'or', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 120 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], 'and', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 121 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], 'xor', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 122, 123 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '&', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 124 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '^', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 125 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '.', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 126 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '+', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 127 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '-', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 128 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '*', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 129 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '/', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 130 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '%', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 131 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '<<', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 132 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '>>', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 133 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '**', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 134 => fn() => $this->semValue = new Expression\InNode($this->semStack[$pos - 2], $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 135 => fn() => $this->semValue = new Expression\UnaryOpNode($this->semStack[$pos], '+', $this->startTokenStack[$pos - 1]->position), - 136 => fn() => $this->semValue = new Expression\UnaryOpNode($this->semStack[$pos], '-', $this->startTokenStack[$pos - 1]->position), - 137 => fn() => $this->semValue = new Expression\NotNode($this->semStack[$pos], $this->startTokenStack[$pos - 1]->position), - 138 => fn() => $this->semValue = new Expression\UnaryOpNode($this->semStack[$pos], '~', $this->startTokenStack[$pos - 1]->position), - 139 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '===', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 140 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '!==', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 141 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '==', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 142 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '!=', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 143 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '<=>', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 144 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '<', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 145 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '<=', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 146 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '>', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 147 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '>=', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 148 => fn() => $this->semValue = new Expression\InstanceofNode($this->semStack[$pos - 2], $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 151 => fn() => $this->semValue = new Expression\TernaryNode($this->semStack[$pos - 4], $this->semStack[$pos - 2], $this->semStack[$pos], $this->startTokenStack[$pos - 4]->position), - 152 => fn() => $this->semValue = new Expression\TernaryNode($this->semStack[$pos - 3], null, $this->semStack[$pos], $this->startTokenStack[$pos - 3]->position), - 153 => fn() => $this->semValue = new Expression\TernaryNode($this->semStack[$pos - 2], $this->semStack[$pos], null, $this->startTokenStack[$pos - 2]->position), - 154 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '??', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 155 => fn() => $this->semValue = new Expression\IssetNode($this->semStack[$pos - 1], $this->startTokenStack[$pos - 3]->position), - 156 => fn() => $this->semValue = new Expression\EmptyNode($this->semStack[$pos - 1], $this->startTokenStack[$pos - 3]->position), - 157 => fn() => $this->semValue = new Expression\CastNode('int', $this->semStack[$pos], $this->startTokenStack[$pos - 1]->position), - 158 => fn() => $this->semValue = new Expression\CastNode('float', $this->semStack[$pos], $this->startTokenStack[$pos - 1]->position), - 159 => fn() => $this->semValue = new Expression\CastNode('string', $this->semStack[$pos], $this->startTokenStack[$pos - 1]->position), - 160 => fn() => $this->semValue = new Expression\CastNode('array', $this->semStack[$pos], $this->startTokenStack[$pos - 1]->position), - 161 => fn() => $this->semValue = new Expression\CastNode('object', $this->semStack[$pos], $this->startTokenStack[$pos - 1]->position), - 162 => fn() => $this->semValue = new Expression\CastNode('bool', $this->semStack[$pos], $this->startTokenStack[$pos - 1]->position), - 163 => fn() => $this->semValue = new Expression\ErrorSuppressNode($this->semStack[$pos], $this->startTokenStack[$pos - 1]->position), - 165 => fn() => $this->semValue = new Expression\ClosureNode((bool) $this->semStack[$pos - 6], $this->semStack[$pos - 4], [], $this->semStack[$pos - 2], $this->semStack[$pos], $this->startTokenStack[$pos - 7]->position), - 166 => fn() => $this->semValue = new Expression\ClosureNode((bool) $this->semStack[$pos - 10], $this->semStack[$pos - 8], $this->semStack[$pos - 6], $this->semStack[$pos - 5], $this->semStack[$pos - 2], $this->startTokenStack[$pos - 11]->position), - 167 => fn() => $this->semValue = new Expression\ClosureNode((bool) $this->semStack[$pos - 7], $this->semStack[$pos - 5], $this->semStack[$pos - 3], $this->semStack[$pos - 2], null, $this->startTokenStack[$pos - 8]->position), - 168 => fn() => $this->semValue = new Expression\NewNode($this->semStack[$pos - 1], $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 174 => fn() => $this->semValue = new Node\ClosureUseNode($this->semStack[$pos], $this->semStack[$pos - 1], $this->startTokenStack[$pos - 1]->position), - 175, 177 => fn() => $this->semValue = $this->checkFunctionName(new Expression\FunctionCallNode($this->semStack[$pos - 1], $this->semStack[$pos], $this->startTokenStack[$pos - 1]->position)), - 176, 178 => fn() => $this->semValue = $this->checkFunctionName(new Expression\FunctionCallableNode($this->semStack[$pos - 3], $this->startTokenStack[$pos - 3]->position)), - 179 => fn() => $this->semValue = new Expression\StaticMethodCallNode($this->semStack[$pos - 3], $this->semStack[$pos - 1], $this->semStack[$pos], $this->startTokenStack[$pos - 3]->position), - 180 => fn() => $this->semValue = new Expression\StaticMethodCallableNode($this->semStack[$pos - 5], $this->semStack[$pos - 3], $this->startTokenStack[$pos - 5]->position), - 182, 184, 185 => fn() => $this->semValue = new Node\NameNode($this->semStack[$pos], Node\NameNode::KindNormal, $this->startTokenStack[$pos]->position), - 186 => fn() => $this->semValue = new Node\NameNode($this->semStack[$pos], Node\NameNode::KindFullyQualified, $this->startTokenStack[$pos]->position), - 194 => fn() => $this->semValue = new Expression\ConstantFetchNode($this->semStack[$pos], $this->startTokenStack[$pos]->position), - 195 => fn() => $this->semValue = new Expression\ClassConstantFetchNode($this->semStack[$pos - 2], $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 196 => fn() => $this->semValue = new Expression\ClassConstantFetchNode($this->semStack[$pos - 4], $this->semStack[$pos - 1], $this->startTokenStack[$pos - 4]->position), - 197 => fn() => $this->semValue = new Expression\ArrayNode($this->semStack[$pos - 1], $this->startTokenStack[$pos - 2]->position), - 198 => fn() => $this->semValue = new Expression\ArrayNode($this->semStack[$pos - 1], $this->startTokenStack[$pos - 3]->position), - 199 => function () use ($pos) { + 97, 99 => fn() => $this->semValue = new Expression\AssignNode($this->semStack[$pos - 2], $this->semStack[$pos], false, $this->startTokenStack[$pos - 2]->position), + 98 => fn() => $this->semValue = new Expression\AssignNode($this->convertArrayToList($this->semStack[$pos - 2]), $this->semStack[$pos], false, $this->startTokenStack[$pos - 2]->position), + 100 => fn() => $this->semValue = new Expression\AssignNode($this->semStack[$pos - 3], $this->semStack[$pos], true, $this->startTokenStack[$pos - 3]->position), + 103 => fn() => $this->semValue = new Expression\CloneNode($this->semStack[$pos], $this->startTokenStack[$pos - 1]->position), + 104 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '+', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 105 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '-', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 106 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '*', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 107 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '/', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 108 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '.', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 109 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '%', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 110 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '&', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 111 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '|', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 112 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '^', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 113 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '<<', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 114 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '>>', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 115 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '**', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 116 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '??', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 117 => fn() => $this->semValue = new Expression\PostOpNode($this->semStack[$pos - 1], '++', $this->startTokenStack[$pos - 1]->position), + 118 => fn() => $this->semValue = new Expression\PreOpNode($this->semStack[$pos], '++', $this->startTokenStack[$pos - 1]->position), + 119 => fn() => $this->semValue = new Expression\PostOpNode($this->semStack[$pos - 1], '--', $this->startTokenStack[$pos - 1]->position), + 120 => fn() => $this->semValue = new Expression\PreOpNode($this->semStack[$pos], '--', $this->startTokenStack[$pos - 1]->position), + 121 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '||', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 122 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '&&', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 123 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], 'or', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 124 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], 'and', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 125 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], 'xor', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 126, 127 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '&', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 128 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '^', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 129 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '.', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 130 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '+', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 131 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '-', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 132 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '*', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 133 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '/', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 134 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '%', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 135 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '<<', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 136 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '>>', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 137 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '**', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 138 => fn() => $this->semValue = new Expression\InNode($this->semStack[$pos - 2], $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 139 => fn() => $this->semValue = new Expression\UnaryOpNode($this->semStack[$pos], '+', $this->startTokenStack[$pos - 1]->position), + 140 => fn() => $this->semValue = new Expression\UnaryOpNode($this->semStack[$pos], '-', $this->startTokenStack[$pos - 1]->position), + 141 => fn() => $this->semValue = new Expression\NotNode($this->semStack[$pos], $this->startTokenStack[$pos - 1]->position), + 142 => fn() => $this->semValue = new Expression\UnaryOpNode($this->semStack[$pos], '~', $this->startTokenStack[$pos - 1]->position), + 143 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '===', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 144 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '!==', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 145 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '==', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 146 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '!=', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 147 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '<=>', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 148 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '<', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 149 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '<=', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 150 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '>', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 151 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '>=', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 152 => fn() => $this->semValue = new Expression\InstanceofNode($this->semStack[$pos - 2], $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 155 => fn() => $this->semValue = new Expression\TernaryNode($this->semStack[$pos - 4], $this->semStack[$pos - 2], $this->semStack[$pos], $this->startTokenStack[$pos - 4]->position), + 156 => fn() => $this->semValue = new Expression\TernaryNode($this->semStack[$pos - 3], null, $this->semStack[$pos], $this->startTokenStack[$pos - 3]->position), + 157 => fn() => $this->semValue = new Expression\TernaryNode($this->semStack[$pos - 2], $this->semStack[$pos], null, $this->startTokenStack[$pos - 2]->position), + 158 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '??', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 159 => fn() => $this->semValue = new Expression\IssetNode($this->semStack[$pos - 1], $this->startTokenStack[$pos - 3]->position), + 160 => fn() => $this->semValue = new Expression\EmptyNode($this->semStack[$pos - 1], $this->startTokenStack[$pos - 3]->position), + 161 => fn() => $this->semValue = new Expression\CastNode('int', $this->semStack[$pos], $this->startTokenStack[$pos - 1]->position), + 162 => fn() => $this->semValue = new Expression\CastNode('float', $this->semStack[$pos], $this->startTokenStack[$pos - 1]->position), + 163 => fn() => $this->semValue = new Expression\CastNode('string', $this->semStack[$pos], $this->startTokenStack[$pos - 1]->position), + 164 => fn() => $this->semValue = new Expression\CastNode('array', $this->semStack[$pos], $this->startTokenStack[$pos - 1]->position), + 165 => fn() => $this->semValue = new Expression\CastNode('object', $this->semStack[$pos], $this->startTokenStack[$pos - 1]->position), + 166 => fn() => $this->semValue = new Expression\CastNode('bool', $this->semStack[$pos], $this->startTokenStack[$pos - 1]->position), + 167 => fn() => $this->semValue = new Expression\ErrorSuppressNode($this->semStack[$pos], $this->startTokenStack[$pos - 1]->position), + 169 => fn() => $this->semValue = new Expression\ClosureNode((bool) $this->semStack[$pos - 6], $this->semStack[$pos - 4], [], $this->semStack[$pos - 2], $this->semStack[$pos], $this->startTokenStack[$pos - 7]->position), + 170 => fn() => $this->semValue = new Expression\ClosureNode((bool) $this->semStack[$pos - 10], $this->semStack[$pos - 8], $this->semStack[$pos - 6], $this->semStack[$pos - 5], $this->semStack[$pos - 2], $this->startTokenStack[$pos - 11]->position), + 171 => fn() => $this->semValue = new Expression\ClosureNode((bool) $this->semStack[$pos - 7], $this->semStack[$pos - 5], $this->semStack[$pos - 3], $this->semStack[$pos - 2], null, $this->startTokenStack[$pos - 8]->position), + 172 => fn() => $this->semValue = new Expression\NewNode($this->semStack[$pos - 1], $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 178 => fn() => $this->semValue = new Node\ClosureUseNode($this->semStack[$pos], $this->semStack[$pos - 1], $this->startTokenStack[$pos - 1]->position), + 179, 181 => fn() => $this->semValue = $this->checkFunctionName(new Expression\FunctionCallNode($this->semStack[$pos - 1], $this->semStack[$pos], $this->startTokenStack[$pos - 1]->position)), + 180, 182 => fn() => $this->semValue = $this->checkFunctionName(new Expression\FunctionCallableNode($this->semStack[$pos - 3], $this->startTokenStack[$pos - 3]->position)), + 183 => fn() => $this->semValue = new Expression\StaticMethodCallNode($this->semStack[$pos - 3], $this->semStack[$pos - 1], $this->semStack[$pos], $this->startTokenStack[$pos - 3]->position), + 184 => fn() => $this->semValue = new Expression\StaticMethodCallableNode($this->semStack[$pos - 5], $this->semStack[$pos - 3], $this->startTokenStack[$pos - 5]->position), + 186, 188, 189 => fn() => $this->semValue = new Node\NameNode($this->semStack[$pos], Node\NameNode::KindNormal, $this->startTokenStack[$pos]->position), + 190 => fn() => $this->semValue = new Node\NameNode($this->semStack[$pos], Node\NameNode::KindFullyQualified, $this->startTokenStack[$pos]->position), + 198 => fn() => $this->semValue = new Expression\ConstantFetchNode($this->semStack[$pos], $this->startTokenStack[$pos]->position), + 199 => fn() => $this->semValue = new Expression\ClassConstantFetchNode($this->semStack[$pos - 2], $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 200 => fn() => $this->semValue = new Expression\ClassConstantFetchNode($this->semStack[$pos - 4], $this->semStack[$pos - 1], $this->startTokenStack[$pos - 4]->position), + 201 => fn() => $this->semValue = new Expression\ArrayNode($this->semStack[$pos - 1], $this->startTokenStack[$pos - 2]->position), + 202 => fn() => $this->semValue = new Expression\ArrayNode($this->semStack[$pos - 1], $this->startTokenStack[$pos - 3]->position), + 203 => function () use ($pos) { $this->semValue = $this->semStack[$pos]; $this->shortArrays->attach($this->semValue); }, - 200 => fn() => $this->semValue = Scalar\StringNode::parse($this->semStack[$pos], $this->startTokenStack[$pos]->position), - 201 => fn() => $this->semValue = Scalar\InterpolatedStringNode::parse($this->semStack[$pos - 1], $this->startTokenStack[$pos - 2]->position), - 202 => fn() => $this->semValue = Scalar\IntegerNode::parse($this->semStack[$pos], $this->startTokenStack[$pos]->position), - 203 => fn() => $this->semValue = Scalar\FloatNode::parse($this->semStack[$pos], $this->startTokenStack[$pos]->position), - 205, 286 => fn() => $this->semValue = new Scalar\StringNode($this->semStack[$pos], $this->startTokenStack[$pos]->position), - 206 => fn() => $this->semValue = new Scalar\BooleanNode(true, $this->startTokenStack[$pos]->position), - 207 => fn() => $this->semValue = new Scalar\BooleanNode(false, $this->startTokenStack[$pos]->position), - 208 => fn() => $this->semValue = new Scalar\NullNode($this->startTokenStack[$pos]->position), - 211 => fn() => $this->semValue = $this->parseDocString($this->semStack[$pos - 2], [$this->semStack[$pos - 1]], $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position, $this->startTokenStack[$pos]->position), - 212 => fn() => $this->semValue = $this->parseDocString($this->semStack[$pos - 1], [], $this->semStack[$pos], $this->startTokenStack[$pos - 1]->position, $this->startTokenStack[$pos]->position), - 213 => fn() => $this->semValue = $this->parseDocString($this->semStack[$pos - 2], $this->semStack[$pos - 1], $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position, $this->startTokenStack[$pos]->position), - 222 => fn() => $this->semValue = new Expression\ConstantFetchNode(new Node\NameNode($this->semStack[$pos], Node\NameNode::KindNormal, $this->startTokenStack[$pos]->position), $this->startTokenStack[$pos]->position), - 227, 243, 278 => fn() => $this->semValue = new Expression\ArrayAccessNode($this->semStack[$pos - 3], $this->semStack[$pos - 1], $this->startTokenStack[$pos - 3]->position), - 229 => fn() => $this->semValue = new Expression\MethodCallNode($this->semStack[$pos - 3], $this->semStack[$pos - 1], $this->semStack[$pos], false, $this->startTokenStack[$pos - 3]->position), - 230 => fn() => $this->semValue = new Expression\MethodCallableNode($this->semStack[$pos - 5], $this->semStack[$pos - 3], $this->startTokenStack[$pos - 5]->position), - 231 => fn() => $this->semValue = new Expression\MethodCallNode($this->semStack[$pos - 3], $this->semStack[$pos - 1], $this->semStack[$pos], true, $this->startTokenStack[$pos - 3]->position), - 232 => fn() => $this->semValue = new Expression\MethodCallNode(new Expression\BinaryOpNode($this->semStack[$pos - 3], '??', new Scalar\NullNode($this->startTokenStack[$pos - 3]->position), $this->startTokenStack[$pos - 3]->position), $this->semStack[$pos - 1], $this->semStack[$pos], true, $this->startTokenStack[$pos - 3]->position), - 235, 244, 279 => fn() => $this->semValue = new Expression\PropertyFetchNode($this->semStack[$pos - 2], $this->semStack[$pos], false, $this->startTokenStack[$pos - 2]->position), - 236, 245, 280 => fn() => $this->semValue = new Expression\PropertyFetchNode($this->semStack[$pos - 2], $this->semStack[$pos], true, $this->startTokenStack[$pos - 2]->position), - 237, 246, 281 => fn() => $this->semValue = new Expression\PropertyFetchNode(new Expression\BinaryOpNode($this->semStack[$pos - 2], '??', new Scalar\NullNode($this->startTokenStack[$pos - 2]->position), $this->startTokenStack[$pos - 2]->position), $this->semStack[$pos], true, $this->startTokenStack[$pos - 2]->position), - 239 => fn() => $this->semValue = new Expression\VariableNode($this->semStack[$pos - 1], $this->startTokenStack[$pos - 3]->position), - 240 => function () use ($pos) { + 204 => fn() => $this->semValue = Scalar\StringNode::parse($this->semStack[$pos], $this->startTokenStack[$pos]->position), + 205 => fn() => $this->semValue = Scalar\InterpolatedStringNode::parse($this->semStack[$pos - 1], $this->startTokenStack[$pos - 2]->position), + 206 => fn() => $this->semValue = Scalar\IntegerNode::parse($this->semStack[$pos], $this->startTokenStack[$pos]->position), + 207 => fn() => $this->semValue = Scalar\FloatNode::parse($this->semStack[$pos], $this->startTokenStack[$pos]->position), + 209, 290 => fn() => $this->semValue = new Scalar\StringNode($this->semStack[$pos], $this->startTokenStack[$pos]->position), + 210 => fn() => $this->semValue = new Scalar\BooleanNode(true, $this->startTokenStack[$pos]->position), + 211 => fn() => $this->semValue = new Scalar\BooleanNode(false, $this->startTokenStack[$pos]->position), + 212 => fn() => $this->semValue = new Scalar\NullNode($this->startTokenStack[$pos]->position), + 215 => fn() => $this->semValue = $this->parseDocString($this->semStack[$pos - 2], [$this->semStack[$pos - 1]], $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position, $this->startTokenStack[$pos]->position), + 216 => fn() => $this->semValue = $this->parseDocString($this->semStack[$pos - 1], [], $this->semStack[$pos], $this->startTokenStack[$pos - 1]->position, $this->startTokenStack[$pos]->position), + 217 => fn() => $this->semValue = $this->parseDocString($this->semStack[$pos - 2], $this->semStack[$pos - 1], $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position, $this->startTokenStack[$pos]->position), + 226 => fn() => $this->semValue = new Expression\ConstantFetchNode(new Node\NameNode($this->semStack[$pos], Node\NameNode::KindNormal, $this->startTokenStack[$pos]->position), $this->startTokenStack[$pos]->position), + 231, 247, 282 => fn() => $this->semValue = new Expression\ArrayAccessNode($this->semStack[$pos - 3], $this->semStack[$pos - 1], $this->startTokenStack[$pos - 3]->position), + 233 => fn() => $this->semValue = new Expression\MethodCallNode($this->semStack[$pos - 3], $this->semStack[$pos - 1], $this->semStack[$pos], false, $this->startTokenStack[$pos - 3]->position), + 234 => fn() => $this->semValue = new Expression\MethodCallableNode($this->semStack[$pos - 5], $this->semStack[$pos - 3], $this->startTokenStack[$pos - 5]->position), + 235 => fn() => $this->semValue = new Expression\MethodCallNode($this->semStack[$pos - 3], $this->semStack[$pos - 1], $this->semStack[$pos], true, $this->startTokenStack[$pos - 3]->position), + 236 => fn() => $this->semValue = new Expression\MethodCallNode(new Expression\BinaryOpNode($this->semStack[$pos - 3], '??', new Scalar\NullNode($this->startTokenStack[$pos - 3]->position), $this->startTokenStack[$pos - 3]->position), $this->semStack[$pos - 1], $this->semStack[$pos], true, $this->startTokenStack[$pos - 3]->position), + 239, 248, 283 => fn() => $this->semValue = new Expression\PropertyFetchNode($this->semStack[$pos - 2], $this->semStack[$pos], false, $this->startTokenStack[$pos - 2]->position), + 240, 249, 284 => fn() => $this->semValue = new Expression\PropertyFetchNode($this->semStack[$pos - 2], $this->semStack[$pos], true, $this->startTokenStack[$pos - 2]->position), + 241, 250, 285 => fn() => $this->semValue = new Expression\PropertyFetchNode(new Expression\BinaryOpNode($this->semStack[$pos - 2], '??', new Scalar\NullNode($this->startTokenStack[$pos - 2]->position), $this->startTokenStack[$pos - 2]->position), $this->semStack[$pos], true, $this->startTokenStack[$pos - 2]->position), + 243 => fn() => $this->semValue = new Expression\VariableNode($this->semStack[$pos - 1], $this->startTokenStack[$pos - 3]->position), + 244 => function () use ($pos) { $var = $this->semStack[$pos]->name; $this->semValue = \is_string($var) ? new Node\VarLikeIdentifierNode($var, $this->startTokenStack[$pos]->position) : $var; }, - 241, 247, 248 => fn() => $this->semValue = new Expression\StaticPropertyFetchNode($this->semStack[$pos - 2], $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), - 255 => fn() => $this->semValue = $this->convertArrayToList(new Expression\ArrayNode($this->semStack[$pos - 1], $this->startTokenStack[$pos - 3]->position)), - 256 => function () use ($pos) { + 245, 251, 252 => fn() => $this->semValue = new Expression\StaticPropertyFetchNode($this->semStack[$pos - 2], $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), + 259 => fn() => $this->semValue = $this->convertArrayToList(new Expression\ArrayNode($this->semStack[$pos - 1], $this->startTokenStack[$pos - 3]->position)), + 260 => function () use ($pos) { $this->semValue = $this->semStack[$pos]; $end = count($this->semValue) - 1; if ( @@ -588,25 +595,25 @@ protected function reduce(int $rule, int $pos): void array_pop($this->semValue); } }, - 260 => fn() => $this->semValue = new Node\ArrayItemNode(new Expression\TemporaryNode($this->semStack[$pos], $this->startTokenStack[$pos]->position), null, false, false, $this->startTokenStack[$pos]->position), - 261 => fn() => $this->semValue = new Node\ArrayItemNode(new Expression\TemporaryNode($this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), $this->semStack[$pos - 2], false, false, $this->startTokenStack[$pos - 2]->position), - 262 => fn() => $this->semValue = new Node\ArrayItemNode(new Expression\TemporaryNode(null), null, false, false, $this->startTokenStack[$pos]->position), - 263 => fn() => $this->semValue = new Node\ArrayItemNode($this->semStack[$pos], null, false, false, $this->startTokenStack[$pos]->position), - 264 => fn() => $this->semValue = new Node\ArrayItemNode($this->semStack[$pos], null, true, false, $this->startTokenStack[$pos - 1]->position), - 265, 267 => fn() => $this->semValue = new Node\ArrayItemNode($this->semStack[$pos], $this->semStack[$pos - 2], false, false, $this->startTokenStack[$pos - 2]->position), - 266, 268 => fn() => $this->semValue = new Node\ArrayItemNode($this->semStack[$pos], $this->semStack[$pos - 3], true, false, $this->startTokenStack[$pos - 3]->position), - 269, 270 => fn() => $this->semValue = new Node\ArrayItemNode($this->semStack[$pos], null, false, true, $this->startTokenStack[$pos - 1]->position), - 271, 272 => function () use ($pos) { + 264 => fn() => $this->semValue = new Node\ArrayItemNode(new Expression\TemporaryNode($this->semStack[$pos], $this->startTokenStack[$pos]->position), null, false, false, $this->startTokenStack[$pos]->position), + 265 => fn() => $this->semValue = new Node\ArrayItemNode(new Expression\TemporaryNode($this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), $this->semStack[$pos - 2], false, false, $this->startTokenStack[$pos - 2]->position), + 266 => fn() => $this->semValue = new Node\ArrayItemNode(new Expression\TemporaryNode(null), null, false, false, $this->startTokenStack[$pos]->position), + 267 => fn() => $this->semValue = new Node\ArrayItemNode($this->semStack[$pos], null, false, false, $this->startTokenStack[$pos]->position), + 268 => fn() => $this->semValue = new Node\ArrayItemNode($this->semStack[$pos], null, true, false, $this->startTokenStack[$pos - 1]->position), + 269, 271 => fn() => $this->semValue = new Node\ArrayItemNode($this->semStack[$pos], $this->semStack[$pos - 2], false, false, $this->startTokenStack[$pos - 2]->position), + 270, 272 => fn() => $this->semValue = new Node\ArrayItemNode($this->semStack[$pos], $this->semStack[$pos - 3], true, false, $this->startTokenStack[$pos - 3]->position), + 273, 274 => fn() => $this->semValue = new Node\ArrayItemNode($this->semStack[$pos], null, false, true, $this->startTokenStack[$pos - 1]->position), + 275, 276 => function () use ($pos) { $this->semStack[$pos - 1][] = $this->semStack[$pos]; $this->semValue = $this->semStack[$pos - 1]; }, - 274 => fn() => $this->semValue = [$this->semStack[$pos - 1], $this->semStack[$pos]], - 275 => fn() => $this->semValue = new Node\InterpolatedStringPartNode($this->semStack[$pos], $this->startTokenStack[$pos]->position), - 276 => fn() => $this->semValue = new Expression\VariableNode($this->semStack[$pos], $this->startTokenStack[$pos]->position), - 282, 283 => fn() => $this->semValue = new Expression\VariableNode($this->semStack[$pos - 1], $this->startTokenStack[$pos - 2]->position), - 284 => fn() => $this->semValue = new Expression\ArrayAccessNode($this->semStack[$pos - 4], $this->semStack[$pos - 2], $this->startTokenStack[$pos - 5]->position), - 287 => fn() => $this->semValue = TagParser::parseOffset($this->semStack[$pos], $this->startTokenStack[$pos]->position), - 288 => fn() => $this->semValue = TagParser::parseOffset('-' . $this->semStack[$pos], $this->startTokenStack[$pos - 1]->position), + 278 => fn() => $this->semValue = [$this->semStack[$pos - 1], $this->semStack[$pos]], + 279 => fn() => $this->semValue = new Node\InterpolatedStringPartNode($this->semStack[$pos], $this->startTokenStack[$pos]->position), + 280 => fn() => $this->semValue = new Expression\VariableNode($this->semStack[$pos], $this->startTokenStack[$pos]->position), + 286, 287 => fn() => $this->semValue = new Expression\VariableNode($this->semStack[$pos - 1], $this->startTokenStack[$pos - 2]->position), + 288 => fn() => $this->semValue = new Expression\ArrayAccessNode($this->semStack[$pos - 4], $this->semStack[$pos - 2], $this->startTokenStack[$pos - 5]->position), + 291 => fn() => $this->semValue = TagParser::parseOffset($this->semStack[$pos], $this->startTokenStack[$pos]->position), + 292 => fn() => $this->semValue = TagParser::parseOffset('-' . $this->semStack[$pos], $this->startTokenStack[$pos - 1]->position), })(); } } diff --git a/src/Latte/Compiler/Token.php b/src/Latte/Compiler/Token.php index da1562aae..6c5462d04 100644 --- a/src/Latte/Compiler/Token.php +++ b/src/Latte/Compiler/Token.php @@ -118,7 +118,8 @@ final class Token Php_Comment = 334, Php_Null = 335, Php_True = 336, - Php_False = 337; + Php_False = 337, + Php_NullsafePipe = 338; public const Names = [ self::End => '[EOF]', @@ -224,6 +225,7 @@ final class Token self::Php_Null => "'null'", self::Php_True => "'true'", self::Php_False => "'false'", + self::Php_NullsafePipe => "'?|'", ]; diff --git a/tests/common/TagParser.parseArguments().phpt b/tests/common/TagParser.parseArguments().phpt index 28420d5e8..3fcab3935 100644 --- a/tests/common/TagParser.parseArguments().phpt +++ b/tests/common/TagParser.parseArguments().phpt @@ -93,6 +93,12 @@ test('inline modifiers', function () { }); +test('inline nullsafe pipe', function () { + Assert::same('(($ʟ_fv = 0) === null ? null : ($this->filters->mod)($ʟ_fv))', formatArgs('(0?|mod)')); + Assert::same('(($ʟ_fv = 0) === null ? null : (($ʟ_fv = ($this->filters->mod2)(($this->filters->mod1)($ʟ_fv))) === null ? null : ($this->filters->mod3)($ʟ_fv)))', formatArgs('(0?|mod1|mod2?|mod3)')); +}); + + test('in operator', function () { Assert::same("in_array(\$a, ['a', 'b'], true), 1", formatArgs('$a in [a, b], 1')); Assert::same('$a, in_array($b->func(), [1, 2], true)', formatArgs('$a, $b->func() in [1, 2]')); diff --git a/tests/common/TagParser.parseModifier().phpt b/tests/common/TagParser.parseModifier().phpt index 9cb30fded..07f034b96 100644 --- a/tests/common/TagParser.parseModifier().phpt +++ b/tests/common/TagParser.parseModifier().phpt @@ -57,6 +57,10 @@ test('depth', function () { }); +test('nullsafe pipe', function () { + Assert::same('(($ʟ_fv = @) === null ? null : (($ʟ_fv = ($this->filters->mod2)(($this->filters->mod1)($ʟ_fv))) === null ? null : ($this->filters->mod3)($ʟ_fv)))', format('?|mod1|mod2?|mod3')); +}); + test('optionalChainingPass', function () { Assert::same( '($this->filters->mod)(@, $var?->prop?->elem[1]?->call(2)?->item)', diff --git a/tests/phpParser/filters.phpt b/tests/phpParser/filters.phpt index 2b5c724c0..a5d96a2d7 100644 --- a/tests/phpParser/filters.phpt +++ b/tests/phpParser/filters.phpt @@ -37,6 +37,7 @@ Latte\Compiler\Nodes\Php\Expression\ArrayNode | | | | | name: 'upper' | | | | | position: 1:5 (offset 4) | | | | args: array (0) + | | | | nullsafe: false | | | | position: 1:2 (offset 1) | | | position: 1:2 (offset 1) | | key: null @@ -60,6 +61,7 @@ Latte\Compiler\Nodes\Php\Expression\ArrayNode | | | | | | name: 'upper' | | | | | | position: 2:11 (offset 22) | | | | | args: array (0) + | | | | | nullsafe: false | | | | | position: 2:2 (offset 13) | | | | position: 2:2 (offset 13) | | | filter: Latte\Compiler\Nodes\Php\FilterNode @@ -67,6 +69,7 @@ Latte\Compiler\Nodes\Php\Expression\ArrayNode | | | | | name: 'truncate' | | | | | position: 2:17 (offset 28) | | | | args: array (0) + | | | | nullsafe: false | | | | position: 2:2 (offset 13) | | | position: 2:2 (offset 13) | | key: null @@ -102,6 +105,7 @@ Latte\Compiler\Nodes\Php\Expression\ArrayNode | | | | | | | unpack: false | | | | | | | name: null | | | | | | | position: 3:20 (offset 58) + | | | | | nullsafe: false | | | | | position: 3:2 (offset 40) | | | | position: 3:2 (offset 40) | | | filter: Latte\Compiler\Nodes\Php\FilterNode @@ -109,6 +113,7 @@ Latte\Compiler\Nodes\Php\Expression\ArrayNode | | | | | name: 'trim' | | | | | position: 3:23 (offset 61) | | | | args: array (0) + | | | | nullsafe: false | | | | position: 3:2 (offset 40) | | | position: 3:2 (offset 40) | | key: null @@ -146,12 +151,14 @@ Latte\Compiler\Nodes\Php\Expression\ArrayNode | | | | | | | | | | name: 'round' | | | | | | | | | | position: 4:24 (offset 91) | | | | | | | | | args: array (0) + | | | | | | | | | nullsafe: false | | | | | | | | | position: 4:21 (offset 88) | | | | | | | | position: 4:21 (offset 88) | | | | | | | byRef: false | | | | | | | unpack: false | | | | | | | name: null | | | | | | | position: 4:20 (offset 87) + | | | | | nullsafe: false | | | | | position: 4:2 (offset 69) | | | | position: 4:2 (offset 69) | | | filter: Latte\Compiler\Nodes\Php\FilterNode @@ -159,6 +166,7 @@ Latte\Compiler\Nodes\Php\Expression\ArrayNode | | | | | name: 'trim' | | | | | position: 4:31 (offset 98) | | | | args: array (0) + | | | | nullsafe: false | | | | position: 4:2 (offset 69) | | | position: 4:2 (offset 69) | | key: null @@ -196,6 +204,7 @@ Latte\Compiler\Nodes\Php\Expression\ArrayNode | | | | | | | name: 'b' | | | | | | | position: 5:23 (offset 127) | | | | | | position: 5:23 (offset 127) + | | | | nullsafe: false | | | | position: 5:2 (offset 106) | | | position: 5:2 (offset 106) | | key: null @@ -233,6 +242,7 @@ Latte\Compiler\Nodes\Php\Expression\ArrayNode | | | | | | | name: 'b' | | | | | | | position: 6:23 (offset 159) | | | | | | position: 6:23 (offset 159) + | | | | nullsafe: false | | | | position: 6:2 (offset 138) | | | position: 6:2 (offset 138) | | key: null diff --git a/tests/phpParser/filtersNullsafe.phpt b/tests/phpParser/filtersNullsafe.phpt new file mode 100644 index 000000000..6099528eb --- /dev/null +++ b/tests/phpParser/filtersNullsafe.phpt @@ -0,0 +1,252 @@ + Latte\Compiler\Nodes\Php\ArrayItemNode + | | value: Latte\Compiler\Nodes\Php\Expression\FilterCallNode + | | | expr: Latte\Compiler\Nodes\Php\Expression\VariableNode + | | | | name: 'a' + | | | | position: 1:2 (offset 1) + | | | filter: Latte\Compiler\Nodes\Php\FilterNode + | | | | name: Latte\Compiler\Nodes\Php\IdentifierNode + | | | | | name: 'upper' + | | | | | position: 1:6 (offset 5) + | | | | args: array (0) + | | | | nullsafe: true + | | | | position: 1:2 (offset 1) + | | | position: 1:2 (offset 1) + | | key: null + | | byRef: false + | | unpack: false + | | position: 1:1 (offset 0) + | 1 => Latte\Compiler\Nodes\Php\ArrayItemNode + | | value: Latte\Compiler\Nodes\Php\Expression\FilterCallNode + | | | expr: Latte\Compiler\Nodes\Php\Expression\FilterCallNode + | | | | expr: Latte\Compiler\Nodes\Php\Expression\BinaryOpNode + | | | | | left: Latte\Compiler\Nodes\Php\Expression\VariableNode + | | | | | | name: 'a' + | | | | | | position: 2:2 (offset 14) + | | | | | operator: '.' + | | | | | right: Latte\Compiler\Nodes\Php\Expression\VariableNode + | | | | | | name: 'b' + | | | | | | position: 2:7 (offset 19) + | | | | | position: 2:2 (offset 14) + | | | | filter: Latte\Compiler\Nodes\Php\FilterNode + | | | | | name: Latte\Compiler\Nodes\Php\IdentifierNode + | | | | | | name: 'upper' + | | | | | | position: 2:12 (offset 24) + | | | | | args: array (0) + | | | | | nullsafe: true + | | | | | position: 2:2 (offset 14) + | | | | position: 2:2 (offset 14) + | | | filter: Latte\Compiler\Nodes\Php\FilterNode + | | | | name: Latte\Compiler\Nodes\Php\IdentifierNode + | | | | | name: 'truncate' + | | | | | position: 2:19 (offset 31) + | | | | args: array (0) + | | | | nullsafe: true + | | | | position: 2:2 (offset 14) + | | | position: 2:2 (offset 14) + | | key: null + | | byRef: false + | | unpack: false + | | position: 2:1 (offset 13) + | 2 => Latte\Compiler\Nodes\Php\ArrayItemNode + | | value: Latte\Compiler\Nodes\Php\Expression\FilterCallNode + | | | expr: Latte\Compiler\Nodes\Php\Expression\FilterCallNode + | | | | expr: Latte\Compiler\Nodes\Php\Expression\VariableNode + | | | | | name: 'a' + | | | | | position: 3:2 (offset 43) + | | | | filter: Latte\Compiler\Nodes\Php\FilterNode + | | | | | name: Latte\Compiler\Nodes\Php\IdentifierNode + | | | | | | name: 'truncate' + | | | | | | position: 3:7 (offset 48) + | | | | | args: array (2) + | | | | | | 0 => Latte\Compiler\Nodes\Php\ArgumentNode + | | | | | | | value: Latte\Compiler\Nodes\Php\Scalar\IntegerNode + | | | | | | | | value: 10 + | | | | | | | | kind: 10 + | | | | | | | | position: 3:17 (offset 58) + | | | | | | | byRef: false + | | | | | | | unpack: false + | | | | | | | name: null + | | | | | | | position: 3:17 (offset 58) + | | | | | | 1 => Latte\Compiler\Nodes\Php\ArgumentNode + | | | | | | | value: Latte\Compiler\Nodes\Php\Scalar\IntegerNode + | | | | | | | | value: 20 + | | | | | | | | kind: 10 + | | | | | | | | position: 3:21 (offset 62) + | | | | | | | byRef: false + | | | | | | | unpack: false + | | | | | | | name: null + | | | | | | | position: 3:21 (offset 62) + | | | | | nullsafe: true + | | | | | position: 3:2 (offset 43) + | | | | position: 3:2 (offset 43) + | | | filter: Latte\Compiler\Nodes\Php\FilterNode + | | | | name: Latte\Compiler\Nodes\Php\IdentifierNode + | | | | | name: 'trim' + | | | | | position: 3:26 (offset 67) + | | | | args: array (0) + | | | | nullsafe: true + | | | | position: 3:2 (offset 43) + | | | position: 3:2 (offset 43) + | | key: null + | | byRef: false + | | unpack: false + | | position: 3:1 (offset 42) + | 3 => Latte\Compiler\Nodes\Php\ArrayItemNode + | | value: Latte\Compiler\Nodes\Php\Expression\FilterCallNode + | | | expr: Latte\Compiler\Nodes\Php\Expression\FilterCallNode + | | | | expr: Latte\Compiler\Nodes\Php\Expression\VariableNode + | | | | | name: 'a' + | | | | | position: 4:2 (offset 75) + | | | | filter: Latte\Compiler\Nodes\Php\FilterNode + | | | | | name: Latte\Compiler\Nodes\Php\IdentifierNode + | | | | | | name: 'truncate' + | | | | | | position: 4:7 (offset 80) + | | | | | args: array (2) + | | | | | | 0 => Latte\Compiler\Nodes\Php\ArgumentNode + | | | | | | | value: Latte\Compiler\Nodes\Php\Scalar\IntegerNode + | | | | | | | | value: 10 + | | | | | | | | kind: 10 + | | | | | | | | position: 4:17 (offset 90) + | | | | | | | byRef: false + | | | | | | | unpack: false + | | | | | | | name: null + | | | | | | | position: 4:17 (offset 90) + | | | | | | 1 => Latte\Compiler\Nodes\Php\ArgumentNode + | | | | | | | value: Latte\Compiler\Nodes\Php\Expression\FilterCallNode + | | | | | | | | expr: Latte\Compiler\Nodes\Php\Scalar\IntegerNode + | | | | | | | | | value: 20 + | | | | | | | | | kind: 10 + | | | | | | | | | position: 4:22 (offset 95) + | | | | | | | | filter: Latte\Compiler\Nodes\Php\FilterNode + | | | | | | | | | name: Latte\Compiler\Nodes\Php\IdentifierNode + | | | | | | | | | | name: 'round' + | | | | | | | | | | position: 4:25 (offset 98) + | | | | | | | | | args: array (0) + | | | | | | | | | nullsafe: false + | | | | | | | | | position: 4:22 (offset 95) + | | | | | | | | position: 4:22 (offset 95) + | | | | | | | byRef: false + | | | | | | | unpack: false + | | | | | | | name: null + | | | | | | | position: 4:21 (offset 94) + | | | | | nullsafe: true + | | | | | position: 4:2 (offset 75) + | | | | position: 4:2 (offset 75) + | | | filter: Latte\Compiler\Nodes\Php\FilterNode + | | | | name: Latte\Compiler\Nodes\Php\IdentifierNode + | | | | | name: 'trim' + | | | | | position: 4:32 (offset 105) + | | | | args: array (0) + | | | | nullsafe: false + | | | | position: 4:2 (offset 75) + | | | position: 4:2 (offset 75) + | | key: null + | | byRef: false + | | unpack: false + | | position: 4:1 (offset 74) + | 4 => Latte\Compiler\Nodes\Php\ArrayItemNode + | | value: Latte\Compiler\Nodes\Php\Expression\FilterCallNode + | | | expr: Latte\Compiler\Nodes\Php\Expression\VariableNode + | | | | name: 'a' + | | | | position: 5:2 (offset 113) + | | | filter: Latte\Compiler\Nodes\Php\FilterNode + | | | | name: Latte\Compiler\Nodes\Php\IdentifierNode + | | | | | name: 'truncate' + | | | | | position: 5:7 (offset 118) + | | | | args: array (2) + | | | | | 0 => Latte\Compiler\Nodes\Php\ArgumentNode + | | | | | | value: Latte\Compiler\Nodes\Php\Scalar\IntegerNode + | | | | | | | value: 10 + | | | | | | | kind: 10 + | | | | | | | position: 5:20 (offset 131) + | | | | | | byRef: false + | | | | | | unpack: false + | | | | | | name: Latte\Compiler\Nodes\Php\IdentifierNode + | | | | | | | name: 'a' + | | | | | | | position: 5:17 (offset 128) + | | | | | | position: 5:17 (offset 128) + | | | | | 1 => Latte\Compiler\Nodes\Php\ArgumentNode + | | | | | | value: Latte\Compiler\Nodes\Php\Scalar\BooleanNode + | | | | | | | value: true + | | | | | | | position: 5:27 (offset 138) + | | | | | | byRef: false + | | | | | | unpack: false + | | | | | | name: Latte\Compiler\Nodes\Php\IdentifierNode + | | | | | | | name: 'b' + | | | | | | | position: 5:24 (offset 135) + | | | | | | position: 5:24 (offset 135) + | | | | nullsafe: true + | | | | position: 5:2 (offset 113) + | | | position: 5:2 (offset 113) + | | key: null + | | byRef: false + | | unpack: false + | | position: 5:1 (offset 112) + | 5 => Latte\Compiler\Nodes\Php\ArrayItemNode + | | value: Latte\Compiler\Nodes\Php\Expression\FilterCallNode + | | | expr: Latte\Compiler\Nodes\Php\Expression\VariableNode + | | | | name: 'a' + | | | | position: 6:2 (offset 146) + | | | filter: Latte\Compiler\Nodes\Php\FilterNode + | | | | name: Latte\Compiler\Nodes\Php\IdentifierNode + | | | | | name: 'truncate' + | | | | | position: 6:7 (offset 151) + | | | | args: array (2) + | | | | | 0 => Latte\Compiler\Nodes\Php\ArgumentNode + | | | | | | value: Latte\Compiler\Nodes\Php\Scalar\IntegerNode + | | | | | | | value: 10 + | | | | | | | kind: 10 + | | | | | | | position: 6:20 (offset 164) + | | | | | | byRef: false + | | | | | | unpack: false + | | | | | | name: Latte\Compiler\Nodes\Php\IdentifierNode + | | | | | | | name: 'a' + | | | | | | | position: 6:17 (offset 161) + | | | | | | position: 6:17 (offset 161) + | | | | | 1 => Latte\Compiler\Nodes\Php\ArgumentNode + | | | | | | value: Latte\Compiler\Nodes\Php\Scalar\BooleanNode + | | | | | | | value: true + | | | | | | | position: 6:27 (offset 171) + | | | | | | byRef: false + | | | | | | unpack: false + | | | | | | name: Latte\Compiler\Nodes\Php\IdentifierNode + | | | | | | | name: 'b' + | | | | | | | position: 6:24 (offset 168) + | | | | | | position: 6:24 (offset 168) + | | | | nullsafe: true + | | | | position: 6:2 (offset 146) + | | | position: 6:2 (offset 146) + | | key: null + | | byRef: false + | | unpack: false + | | position: 6:1 (offset 145) + position: 1:1 (offset 0) diff --git a/tests/phpParser/modifier.phpt b/tests/phpParser/modifier.phpt index fb087c6f0..aa96e8ba9 100644 --- a/tests/phpParser/modifier.phpt +++ b/tests/phpParser/modifier.phpt @@ -54,18 +54,21 @@ Latte\Compiler\Nodes\Php\ModifierNode | | | | | | | name: 'round' | | | | | | | position: 1:20 (offset 19) | | | | | | args: array (0) + | | | | | | nullsafe: false | | | | | | position: 1:17 (offset 16) | | | | | position: 1:17 (offset 16) | | | | byRef: false | | | | unpack: false | | | | name: null | | | | position: 1:16 (offset 15) + | | nullsafe: false | | position: 1:1 (offset 0) | 1 => Latte\Compiler\Nodes\Php\FilterNode | | name: Latte\Compiler\Nodes\Php\IdentifierNode | | | name: 'trim' | | | position: 1:27 (offset 26) | | args: array (0) + | | nullsafe: false | | position: 1:1 (offset 0) escape: false check: true diff --git a/tests/phpParser/modifierNullsafe.phpt b/tests/phpParser/modifierNullsafe.phpt new file mode 100644 index 000000000..2cd24e935 --- /dev/null +++ b/tests/phpParser/modifierNullsafe.phpt @@ -0,0 +1,75 @@ +tokenize($code); +$parser = new Latte\Compiler\TagParser($tokens); +$node = $parser->parseModifier(); +if (!$parser->isEnd()) { + $parser->stream->throwUnexpectedException(); +} + +Assert::same( + loadContent(__FILE__, __COMPILER_HALT_OFFSET__), + exportNode($node), +); + +__halt_compiler(); +Latte\Compiler\Nodes\Php\ModifierNode + filters: array (2) + | 0 => Latte\Compiler\Nodes\Php\FilterNode + | | name: Latte\Compiler\Nodes\Php\IdentifierNode + | | | name: 'truncate' + | | | position: 1:3 (offset 2) + | | args: array (2) + | | | 0 => Latte\Compiler\Nodes\Php\ArgumentNode + | | | | value: Latte\Compiler\Nodes\Php\Scalar\IntegerNode + | | | | | value: 10 + | | | | | kind: 10 + | | | | | position: 1:13 (offset 12) + | | | | byRef: false + | | | | unpack: false + | | | | name: null + | | | | position: 1:13 (offset 12) + | | | 1 => Latte\Compiler\Nodes\Php\ArgumentNode + | | | | value: Latte\Compiler\Nodes\Php\Expression\FilterCallNode + | | | | | expr: Latte\Compiler\Nodes\Php\Scalar\IntegerNode + | | | | | | value: 20 + | | | | | | kind: 10 + | | | | | | position: 1:18 (offset 17) + | | | | | filter: Latte\Compiler\Nodes\Php\FilterNode + | | | | | | name: Latte\Compiler\Nodes\Php\IdentifierNode + | | | | | | | name: 'round' + | | | | | | | position: 1:22 (offset 21) + | | | | | | args: array (0) + | | | | | | nullsafe: true + | | | | | | position: 1:18 (offset 17) + | | | | | position: 1:18 (offset 17) + | | | | byRef: false + | | | | unpack: false + | | | | name: null + | | | | position: 1:17 (offset 16) + | | nullsafe: true + | | position: 1:1 (offset 0) + | 1 => Latte\Compiler\Nodes\Php\FilterNode + | | name: Latte\Compiler\Nodes\Php\IdentifierNode + | | | name: 'trim' + | | | position: 1:30 (offset 29) + | | args: array (0) + | | nullsafe: true + | | position: 1:1 (offset 0) + escape: false + check: true + position: 1:1 (offset 0) diff --git a/tests/tags/print.phpt b/tests/tags/print.phpt index 38a370a23..18c0be9a4 100644 --- a/tests/tags/print.phpt +++ b/tests/tags/print.phpt @@ -19,7 +19,7 @@ $template = <<<'EOD' Condition: {$hello ? yes} {=$hello ? yes} Array: {$hello ? ([a, b, c])|join} {=[a, b, $hello ? c]|join} - filter: {$hello |lower} + filter: {$hello ?|lower} {$hello |truncate:"10"|lower} {$hello |types , '' , "" , "$hello" } EOD; @@ -54,7 +54,7 @@ Assert::match( echo ' filter: '; - echo LR\Filters::escapeHtmlText(($this->filters->lower)($hello)) /* line 9 */; + echo LR\Filters::escapeHtmlText((($ʟ_fv = $hello) === null ? null : ($this->filters->lower)($ʟ_fv))) /* line 9 */; echo "\n"; echo LR\Filters::escapeHtmlText(($this->filters->lower)(($this->filters->truncate)($hello, '10'))) /* line 10 */; echo "\n";