pax_global_header00006660000000000000000000000064145433274130014520gustar00rootroot0000000000000052 comment=18363e04d1b85393d68e31e69baa918c1fba8e74 php-1.0.2/000077500000000000000000000000001454332741300123075ustar00rootroot00000000000000php-1.0.2/.gitignore000066400000000000000000000000531454332741300142750ustar00rootroot00000000000000/node_modules/ /src/parser.* .tern-* /dist php-1.0.2/.npmignore000066400000000000000000000000161454332741300143030ustar00rootroot00000000000000/node_modules php-1.0.2/CHANGELOG.md000066400000000000000000000014111454332741300141150ustar00rootroot00000000000000## 1.0.2 (2023-12-28) ### Bug fixes Tag comments and strings as isolating for the purpose of bidirectional text. ## 1.0.1 (2023-01-18) ### Bug fixes Fix an issue where the grammar didn't handle less-than characters at the end of the document correctly. Remove use of `require` as an identifier in the build output, which could break CommonJS builds. ## 1.0.0 (2022-06-06) ### New features First stable version. ## 0.16.0 (2022-04-20) ### Breaking changes Move to 0.16 serialized parser format. ### Bug fixes Allow `class` to be an identifier in constructs like `A::class`. Add highlighting information ### New features The parser now includes syntax highlighting information in its node types. ## 0.15.0 (2021-09-03) ### New features First numbered release. php-1.0.2/LICENSE000066400000000000000000000021311454332741300133110ustar00rootroot00000000000000MIT License Copyright (C) 2018 by Marijn Haverbeke and others Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. php-1.0.2/README.md000066400000000000000000000005611454332741300135700ustar00rootroot00000000000000# @lezer/php This is a PHP grammar for the [Lezer](https://lezer.codemirror.net/) parser system. The grammar used is based in part on the corresponding [tree-sitter grammar](https://github.com/tree-sitter/tree-sitter-php) and the [Zend Yacc grammar](https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y). The code is licensed under an MIT license. php-1.0.2/dist/000077500000000000000000000000001454332741300132525ustar00rootroot00000000000000php-1.0.2/dist/index.d.ts000066400000000000000000000001021454332741300151440ustar00rootroot00000000000000import {LRParser} from "@lezer/lr" export const parser: LRParser php-1.0.2/package.json000066400000000000000000000017361454332741300146040ustar00rootroot00000000000000{ "name": "@lezer/php", "version": "1.0.2", "description": "Lezer-based PHP grammar", "main": "dist/index.cjs", "type": "module", "exports": { "import": "./dist/index.es.js", "require": "./dist/index.cjs" }, "module": "dist/index.es.js", "types": "dist/index.d.ts", "author": "Marijn Haverbeke ", "license": "MIT", "devDependencies": { "@lezer/generator": "^1.2.2", "mocha": "^10.2.0", "rollup": "^2.52.2", "@rollup/plugin-node-resolve": "^9.0.0" }, "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.1.0" }, "repository": { "type" : "git", "url" : "https://github.com/lezer-parser/php.git" }, "scripts": { "build": "lezer-generator src/php.grammar -o src/parser && rollup -c", "build-debug": "lezer-generator src/php.grammar --names -o src/parser && rollup -c", "prepare": "npm run build", "test": "mocha test/test-*.js" } } php-1.0.2/rollup.config.js000066400000000000000000000004651454332741300154330ustar00rootroot00000000000000import {nodeResolve} from "@rollup/plugin-node-resolve" export default { input: "./src/parser.js", output: [{ format: "cjs", file: "./dist/index.cjs" }, { format: "es", file: "./dist/index.es.js" }], external(id) { return !/^[\.\/]/.test(id) }, plugins: [ nodeResolve() ] } php-1.0.2/src/000077500000000000000000000000001454332741300130765ustar00rootroot00000000000000php-1.0.2/src/highlight.js000066400000000000000000000041041454332741300154020ustar00rootroot00000000000000import {styleTags, tags as t} from "@lezer/highlight" export const phpHighlighting = styleTags({ "Visibility abstract final static": t.modifier, "for foreach while do if else elseif switch try catch finally return throw break continue default case": t.controlKeyword, "endif endfor endforeach endswitch endwhile declare enddeclare goto match": t.controlKeyword, "and or xor yield unset clone instanceof insteadof": t.operatorKeyword, "function fn class trait implements extends const enum global interface use var": t.definitionKeyword, "include include_once require require_once namespace": t.moduleKeyword, "new from echo print array list as": t.keyword, null: t.null, Boolean: t.bool, VariableName: t.variableName, "NamespaceName/...": t.namespace, "NamedType/...": t.typeName, Name: t.name, "CallExpression/Name": t.function(t.variableName), "LabelStatement/Name": t.labelName, "MemberExpression/Name": t.propertyName, "MemberExpression/VariableName": t.special(t.propertyName), "ScopedExpression/ClassMemberName/Name": t.propertyName, "ScopedExpression/ClassMemberName/VariableName": t.special(t.propertyName), "CallExpression/MemberExpression/Name": t.function(t.propertyName), "CallExpression/ScopedExpression/ClassMemberName/Name": t.function(t.propertyName), "MethodDeclaration/Name": t.function(t.definition(t.variableName)), "FunctionDefinition/Name": t.function(t.definition(t.variableName)), "ClassDeclaration/Name": t.definition(t.className), UpdateOp: t.updateOperator, ArithOp: t.arithmeticOperator, LogicOp: t.logicOperator, BitOp: t.bitwiseOperator, CompareOp: t.compareOperator, ControlOp: t.controlOperator, AssignOp: t.definitionOperator, "$ ConcatOp": t.operator, LineComment: t.lineComment, BlockComment: t.blockComment, Integer: t.integer, Float: t.float, String: t.string, ShellExpression: t.special(t.string), "=> ->": t.punctuation, "( )": t.paren, "#[ [ ]": t.squareBracket, "${ { }": t.brace, "-> ?->": t.derefOperator, ", ; :: : \\": t.separator, "PhpOpen PhpClose": t.processingInstruction, }) php-1.0.2/src/php.grammar000066400000000000000000000340161454332741300152410ustar00rootroot00000000000000@precedence { pair, namespace, member, scope, new, call, cast, else @right, optionalType, unionType @left, incdec @left, instanceof @left, unary @left, exponent @right, mult @left, plus @left, shift @left, concat @left, compare @left, equal @left, binAnd @left, binXor @left, binOr @left, logAnd @left, logOr @left, qq @right, conditional @left, update @right, and @left, xor @left, or @left, yield @right } @skip {} { @top Template { TextInterpolation { Text? PhpOpen } (LineComment | BlockComment | whitespace | TextInterpolation)* topStatements | Text? } } @top Program { statement* } topStatements { statement* eof } statement[@isGroup=Statement] { EmptyStatement { ";" } | Block | LabelStatement { Name ":" } | ExpressionStatement { expression semicolon } | IfStatement { if ParenthesizedExpression ( statement (!else elseif ParenthesizedExpression statement)* (!else else statement)? | ColonBlock (elseif ParenthesizedExpression ColonBlock)* (else ColonBlock)? endif semicolon ) } | SwitchStatement { switch ParenthesizedExpression ( Block { "{" (CaseStatement | DefaultStatement)* "}" } | ColonBlock { ":" (CaseStatement | DefaultStatement)* } endswitch semicolon ) } | WhileStatement { while ParenthesizedExpression (trailingStatement | ColonBlock endwhile semicolon) } | DoStatement { do statement while ParenthesizedExpression semicolon } | ForStatement { for ForSpec { "(" expressions? ";" expressions? ";" expressions? ")" } (trailingStatement | ColonBlock endfor semicolon) } | ForeachStatement { foreach ForSpec { "(" expression as (Pair { expression "=>" expression } | expression) ")" } (trailingStatement | ColonBlock endforeach semicolon) } | GotoStatement { goto Name semicolon } | ContinueStatement { continue expression? semicolon } | BreakStatement { break expression? semicolon } | ReturnStatement { return expression? semicolon } | TryStatement { try Block (catch CatchDeclarator { "(" type VariableName? ")" } Block | finally Block)+ } | DeclareStatement { declare "(" Name "=" literal ")" (trailingStatement | ColonBlock enddeclare semicolon) } | EchoStatement { echo expressions semicolon } | UnsetStatement { unset "(" commaSep1 ")" semicolon } | ConstDeclaration { Attributes* Visibility? const commaSep1 semicolon } | FunctionDefinition { Attributes* functionDefinitionHeader Block } | ClassDeclaration { Attributes* (final | abstract)? class Name BaseClause? ClassInterfaceClause? DeclarationList } | InterfaceDeclaration { interface Name BaseClause? DeclarationList } | TraitDeclaration { trait Name DeclarationList } | EnumDeclaration { Attributes* enum Name (":" type)? ClassInterfaceClause? EnumBody } | NamespaceDefinition { namespace (qualifiedName semicolon | qualifiedName? Block) } | NamespaceUseDeclaration { use (function | const)? (commaSep1 | "\\"? (NamespaceName !namespace "\\")* UseGroup) semicolon } | GlobalDeclaration { global commaSep1 semicolon } | FunctionStaticDeclaration { static commaSep1 semicolon } } qualifiedName { Name | QualifiedName { "\\" (NamespaceName !namespace "\\")* Name | (NamespaceName !namespace "\\")+ Name } } NamespaceName { Name } UseGroup { "{" commaSep1 "}" } BaseClause { extends commaSep1 } EnumBody { "{" (EnumCase | MethodDeclaration | UseDeclaration)* "}" } EnumCase { Attributes* case Name ("=" (String | Integer))? semicolon } DeclarationList { "{" memberDeclaration* "}" } ClassInterfaceClause { implements commaSep1 } memberDeclaration { ConstDeclaration { Attributes* modifier* const commaSep1 semicolon } | PropertyDeclaration { Attributes* modifier* type? commaSep1 semicolon } | MethodDeclaration | UseDeclaration } modifier { var | Visibility | static | final | abstract } VariableDeclarator { VariableName ("=" expression)? } ConstDeclarator[@name=VariableDeclarator] { Name "=" expression } MethodDeclaration { Attributes* modifier* functionDefinitionHeader (Block | semicolon) } UseDeclaration { use commaSep1 (UseList | semicolon) } UseList { "{" ((UseInsteadOfClause | UseAsClause) semicolon)* "}" } UseInsteadOfClause { (ScopedExpression | Name) insteadof Name } UseAsClause { (ScopedExpression | Name) as (Visibility? Name | Visibility Name?) } functionDefinitionHeader { function "&"? Name ParamList (":" type)? } ParamList { "(" commaSep ")" } parameter { Parameter { Attributes* type? "&"? VariableName ("=" expression)? } | VariadicParameter { Attributes* type? "&"? "..." VariableName } | PropertyParameter { Visibility type? VariableName ("=" expression)? } } type[@isGroup=Type] { UnionType { type (!unionType LogicOp<"|"> type)+ } | OptionalType { !optionalType LogicOp<"?"> type } | NamedType { qualifiedName | null | array } } literal { Integer | Float | string | Boolean | null } expressions { expression | SequenceExpression { expression ("," expression)+ } } ColonBlock { ":" statement* } trailingStatement { statement | EmptyStatement { automaticSemicolon } } MatchArm { (default | commaSep1) "=>" expression } CaseStatement { case expression (":" | ";") statement* } DefaultStatement { default (":" | ";") statement* } Block { "{" statement* "}" } expression[@isGroup=Expression] { ConditionalExpression { expression !conditional LogicOp<"?"> expression? ":" expression } | MatchExpression { match ParenthesizedExpression MatchBlock { "{" commaSep1 "}" } } | AssignmentExpression { variable !update "=" "&"? expression } | UpdateExpression { variable !update UpdateOp expression } | YieldExpression { yield (!yield arrayElement | from expression)? } | BinaryExpression | IncludeExpression { (include | include_once) expression } | RequireExpression { (require | require_once) expression } | CloneExpression { clone expression } | UnaryExpression { ControlOp<"@"> expression | (ArithOp<"+" | "-"> | LogicOp<"~" | "!">) !unary expression } | qualifiedName | PrintIntrinsic { print expression } | FunctionExpression { static? function "&"? ParamList (use UseList { "(" commaSep<"&"? VariableName> ")" })? (":" type)? Block } | ArrowFunction { static? fn "&"? ParamList (":" type)? "=>" expression } | NewExpression { new expression (!new ArgList)? | new class ArgList? BaseClause? ClassInterfaceClause? DeclarationList } | IncDecExpression[@name=UpdateExpression] { expression !incdec ArithOp<"++" | "--"> | ArithOp<"++" | "--"> !incdec expression } | ShellExpression | ParenthesizedExpression | ThrowExpression { throw expression } | variable | literal } variable { ArrayExpression { array ValueList { "(" ","? commaSep ")" } | "[" ","? commaSep "]" } | ListExpression { list ValueList { "(" ","? commaSep" expression }> ")" } } | SubscriptExpression { expression (!member "[" expression? "]" | !member "{" expression "}") } | MemberExpression { expression !member ("->" | "?->") memberName } | DynamicVariable | VariableName | CallExpression { expression !call ArgList } | CastExpression { castOpen type ")" !cast expression } | ScopedExpression } DynamicVariable { "$" (VariableName | DynamicVariable) | "${" expression "}" } ParenthesizedExpression { "(" expression ")" } ScopedExpression { expression !scope "::" ClassMemberName } ClassMemberName { Name | VariableName } ArgList { "(" commaSep ")" } argument { NamedArgument { Name ":" expression } | SpreadArgument { "..." expression? } | expression } memberName { Name | VariableName | "{" expression "}" } arrayElement { "&"? expression | VariadicUnpacking { "..." expression } | Pair { expression !pair "=>" "&"? expression } } Attributes { "#[" commaSep1 "]" } Attribute { qualifiedName ArgList? } @skip {} { TextInterpolation { PhpClose Text? (PhpOpen | eof) } Text[isolate] { textElement+ } InterpolatedString[@name=String] { startInterpolatedString ( interpolatedStringContent | EscapeSequence | interpolatedExpression | Interpolation )* endInterpolatedString } // The afterInterpolation token isn't actually real, but used as a // signal (via canShift) to the tokenizer to indicate it shouldn't // consume '[' or '->' tokens. interpolatedExpression { VariableName | MemberExpression { interpolatedExpression afterInterpolation? ("?->" | "->") Name } | SubscriptExpression { interpolatedExpression afterInterpolation? "[" (Integer | UnaryExpression { ArithOp<"-"> Integer } | Name | VariableName) "]" } } } Interpolation { ("{" | "${") expression "}" } string { InterpolatedString | HeredocString | String } BinaryExpression { expression !instanceof instanceof expression | expression !qq LogicOp<"??"> expression | expression !and and expression | expression !or or expression | expression !xor xor expression | expression !logOr LogicOp<"||"> expression | expression !logAnd LogicOp<"&&"> expression | expression !binOr BitOp<"|"> expression | expression !binXor BitOp<"^"> expression | expression !binAnd BitOp { "&" } expression | expression !equal CompareOp<"==" | "===" | "!=" | "!==" | "<>" | "<=>"> expression | expression !compare CompareOp<"<" | ">" | "<=" | ">="> expression | expression !shift BitOp<"<<" | ">>"> expression | expression !plus ArithOp<"+" | "-"> expression | expression !concat ConcatOp<"."> expression | expression !mult ArithOp<"*" | "/" | "%"> expression | expression !exponent ArithOp<"**"> expression } semicolon { automaticSemicolon | ";" } @skip { LineComment | BlockComment | whitespace | TextInterpolation } @external specialize {Name} keywords from "./tokens" { abstract[@name=abstract], and[@name=LogicOp], array[@name=array], as[@name=as], Boolean, break[@name=break], case[@name=case], catch[@name=catch], clone[@name=clone], const[@name=const], continue[@name=continue], default[@name=default], declare[@name=declare], do[@name=do], echo[@name=echo], else[@name=else], elseif[@name=elseif], enddeclare[@name=enddeclare], endfor[@name=endfor], endforeach[@name=endforeach], endif[@name=endif], endswitch[@name=endswitch], endwhile[@name=endwhile], enum[@name=enum], extends[@name=extends], final[@name=final], finally[@name=finally], fn[@name=fn], for[@name=for], foreach[@name=foreach], from[@name=from], function[@name=function], global[@name=global], goto[@name=goto], if[@name=if], implements[@name=implements], include[@name=include], include_once[@name=include_once], instanceof[@name=LogicOp], insteadof[@name=insteadof], interface[@name=interface], list[@name=list], match[@name=match], namespace[@name=namespace], new[@name=new], null[@name=null], or[@name=LogicOp], print[@name=print], require[@name=require], require_once[@name=require_once], return[@name=return], switch[@name=switch], throw[@name=throw], trait[@name=trait], try[@name=try], unset[@name=unset], use[@name=use], var[@name=var], Visibility, while[@name=while], xor[@name=LogicOp], yield[@name=yield] } commaSep { "" | content ("," content?)* } commaSep1 { content ("," content?)* } static[@dynamicPrecedence=1] { @extend[@name=static] } class { @extend[@name=class] } @external tokens expression from "./tokens" { castOpen[@name="("], HeredocString } @external tokens interpolated from "./tokens" { interpolatedStringContent, EscapeSequence, afterInterpolation } @external tokens semicolon from "./tokens" { automaticSemicolon } @tokens { whitespace { $[ \t\n\r⁠​ ]+ } PhpOpen[closedBy=phpClose] { "" } textElement { "\n" | ![\n<] textElement? | "<" ("\n" | @eof | ![\n\?] textElement?) } digit { $[0-9] } hex { $[0-9A-Fa-f] } oct { $[0-7] } separatedDigits { ("_" digit+)* } exponent { $[eE] $[+-]? digit+ separatedDigits } Float { digit+ separatedDigits ("." digit* separatedDigits exponent? | exponent) | "." digit+ separatedDigits exponent? } Integer { digit+ separatedDigits | "0" $[oO] oct+ ("_" oct+)* | "0" $[xX] hex+ ("_" hex+)* | "0" $[bB] $[01]+ ("_" $[01]+)* } @precedence { Float, ConcatOp<".">, Integer } ShellExpression { "`" ("\\" _ | ![`\\])* "`" } UpdateOp { ("**" | "*" | "/" | "%" | "+" | "-" | "." | "<<" | ">>" | "&" | "^" | "|" | "??") "=" } CompareOp { term } ArithOp { term } LogicOp { term } BitOp { term } ControlOp { term } ConcatOp { term } startInterpolatedString { $[bB]? '"' } endInterpolatedString { '"' } @precedence { startInterpolatedString, Name } String[isolate] { $[bB]? "'" (![\\'] | "\\" _)* "'"? } @precedence { String, Name } letter { $[_a-zA-Z\u00A1-\u00ff] } Name { letter (letter | @digit)* } VariableName { "$" Name } @precedence { VariableName, "${", "$" } LineComment[isolate] { ("//" | "#") lineCommentRest? } lineCommentRest { ![\r\n?] lineCommentRest? | "?" lineCommentQuestion } lineCommentQuestion { $[\r\n] | ![>\r\n] lineCommentRest? } @precedence { "#[", LineComment, ArithOp<"*" | "/" | "%"> } BlockComment[isolate] { "/*" blockCommentRest } blockCommentRest { ![*] blockCommentRest | "*" blockCommentAfterStar } blockCommentAfterStar { "/" | "*" blockCommentAfterStar | ![/*] blockCommentRest } "${" "{" "}" "#[" "[" "]" "(" ")" ";" ":" "::" "," "\\" "?->" "->" "=>" "&" "$" "..." "="[@name=AssignOp] } @external tokens eofToken from "./tokens" { eof } @external propSource phpHighlighting from "./highlight" @detectDelim php-1.0.2/src/tokens.js000066400000000000000000000142211454332741300147370ustar00rootroot00000000000000import {ExternalTokenizer} from "@lezer/lr" import { abstract, and, array, as, Boolean, _break, _case, _catch, clone, _const, _continue, declare, _default, _do, echo, _else, elseif, enddeclare, endfor, endforeach, endif, endswitch, endwhile, _enum, _extends, final, _finally, fn, _for, foreach, from, _function, global, goto, _if, _implements, include, include_once, _instanceof, insteadof, _interface, list, match, namespace, _new, _null, or, print, _require, require_once, _return, _switch, _throw, trait, _try, unset, use, _var, Visibility, _while, xor, _yield, castOpen, eof, automaticSemicolon, HeredocString, interpolatedStringContent, EscapeSequence, afterInterpolation } from "./parser.terms.js" const keywordMap = { abstract, and, array, as, true: Boolean, false: Boolean, break: _break, case: _case, catch: _catch, clone, const: _const, continue: _continue, declare, default: _default, do: _do, echo, else: _else, elseif, enddeclare, endfor, endforeach, endif, endswitch, endwhile, enum: _enum, extends: _extends, final, finally: _finally, fn, for: _for, foreach, from, function: _function, global, goto, if: _if, implements: _implements, include, include_once, instanceof: _instanceof, insteadof, interface: _interface, list, match, namespace, new: _new, null: _null, or, print, require: _require, require_once, return: _return, switch: _switch, throw: _throw, trait, try: _try, unset, use, var: _var, public: Visibility, private: Visibility, protected: Visibility, while: _while, xor, yield: _yield, __proto__: null, } export function keywords(name) { let found = keywordMap[name.toLowerCase()] return found == null ? -1 : found } function isSpace(ch) { return ch == 9 || ch == 10 || ch == 13 || ch == 32 } function isASCIILetter(ch) { return ch >= 97 && ch <= 122 || ch >= 65 && ch <= 90 } function isIdentifierStart(ch) { return ch == 95 || ch >= 0x80 || isASCIILetter(ch) } function isHex(ch) { return ch >= 48 && ch <= 55 || ch >= 97 && ch <= 102 || ch >= 65 && ch <= 70 /* 0-9, a-f, A-F */ } const castTypes = { int: true, integer: true, bool: true, boolean: true, float: true, double: true, real: true, string: true, array: true, object: true, unset: true, __proto__: null } export const expression = new ExternalTokenizer(input => { if (input.next == 40 /* '(' */) { input.advance() let peek = 0 while (isSpace(input.peek(peek))) peek++ let name = "", next while (isASCIILetter(next = input.peek(peek))) { name += String.fromCharCode(next) peek++ } while (isSpace(input.peek(peek))) peek++ if (input.peek(peek) == 41 /* ')' */ && castTypes[name.toLowerCase()]) input.acceptToken(castOpen) } else if (input.next == 60 /* '<' */ && input.peek(1) == 60 && input.peek(2) == 60) { for (let i = 0; i < 3; i++) input.advance(); while (input.next == 32 /* ' ' */ || input.next == 9 /* '\t' */) input.advance() let quoted = input.next == 39 /* "'" */ if (quoted) input.advance() if (!isIdentifierStart(input.next)) return let tag = String.fromCharCode(input.next) for (;;) { input.advance() if (!isIdentifierStart(input.next) && !(input.next >= 48 && input.next <= 55) /* 0-9 */) break tag += String.fromCharCode(input.next) } if (quoted) { if (input.next != 39) return input.advance() } if (input.next != 10 /* '\n' */ && input.next != 13 /* '\r' */) return for (;;) { let lineStart = input.next == 10 || input.next == 13 input.advance() if (input.next < 0) return if (lineStart) { while (input.next == 32 /* ' ' */ || input.next == 9 /* '\t' */) input.advance() let match = true for (let i = 0; i < tag.length; i++) { if (input.next != tag.charCodeAt(i)) { match = false; break } input.advance() } if (match) return input.acceptToken(HeredocString) } } } }) export const eofToken = new ExternalTokenizer(input => { if (input.next < 0) input.acceptToken(eof) }) export const semicolon = new ExternalTokenizer((input, stack) => { if (input.next == 63 /* '?' */ && stack.canShift(automaticSemicolon) && input.peek(1) == 62 /* '>' */) input.acceptToken(automaticSemicolon) }) function scanEscape(input) { let after = input.peek(1) if (after == 110 /* 'n' */ || after == 114 /* 'r' */ || after == 116 /* 't' */ || after == 118 /* 'v' */ || after == 101 /* 'e' */ || after == 102 /* 'f' */ || after == 92 /* '\\' */ || after == 36 /* '"' */ || after == 34 /* '$' */ || after == 123 /* '{' */) return 2 if (after >= 48 && after <= 55 /* '0'-'7' */) { let size = 2, next while (size < 5 && (next = input.peek(size)) >= 48 && next <= 55) size++ return size } if (after == 120 /* 'x' */ && isHex(input.peek(2))) { return isHex(input.peek(3)) ? 4 : 3 } if (after == 117 /* 'u' */ && input.peek(2) == 123 /* '{' */) { for (let size = 3;; size++) { let next = input.peek(size) if (next == 125 /* '}' */) return size == 2 ? 0 : size + 1 if (!isHex(next)) break } } return 0 } export const interpolated = new ExternalTokenizer((input, stack) => { let content = false for (;; content = true) { if (input.next == 34 /* '"' */ || input.next < 0 || input.next == 36 /* '$' */ && (isIdentifierStart(input.peek(1)) || input.peek(1) == 123 /* '{' */) || input.next == 123 /* '{' */ && input.peek(1) == 36 /* '$' */) { break } else if (input.next == 92 /* '\\' */) { let escaped = scanEscape(input) if (escaped) { if (content) break else return input.acceptToken(EscapeSequence, escaped) } } else if (!content && ( input.next == 91 /* '[' */ || input.next == 45 /* '-' */ && input.peek(1) == 62 /* '>' */ && isIdentifierStart(input.peek(2)) || input.next == 63 /* '?' */ && input.peek(1) == 45 && input.peek(2) == 62 && isIdentifierStart(input.peek(3)) ) && stack.canShift(afterInterpolation)) { break } input.advance() } if (content) input.acceptToken(interpolatedStringContent) }) php-1.0.2/test/000077500000000000000000000000001454332741300132665ustar00rootroot00000000000000php-1.0.2/test/class.txt000066400000000000000000000140321454332741300151340ustar00rootroot00000000000000# Abstract class Template( TextInterpolation(PhpOpen), ClassDeclaration(abstract, class, Name, DeclarationList( MethodDeclaration(Visibility, function, Name, ParamList, Block ), MethodDeclaration(abstract, Visibility, function, Name, ParamList ) ) ) ) # Anonymous classes Template( TextInterpolation(PhpOpen), ExpressionStatement( NewExpression(new, class, DeclarationList( MethodDeclaration(Visibility, function, Name, ParamList, Block ) ) ) ), ExpressionStatement( NewExpression(new, class, BaseClause(extends, Name), ClassInterfaceClause(implements, Name, Name), DeclarationList ) ), ExpressionStatement( NewExpression(new, class, ArgList, DeclarationList( PropertyDeclaration( Visibility, VariableDeclarator( VariableName ) ) ) ) ), ExpressionStatement( NewExpression(new, class, ArgList(VariableName, VariableName), BaseClause(extends, Name), DeclarationList( UseDeclaration(use, Name ) ) ) ), ClassDeclaration(class, Name, DeclarationList( MethodDeclaration(Visibility, function, Name, ParamList, Block( ReturnStatement(return, NewExpression(new, class, ArgList(VariableName), BaseClause(extends, Name), DeclarationList( ConstDeclaration(const, VariableDeclarator(Name, AssignOp, String) ) ) ) ) ) ) ) ) ) # Conditional class definition Template( TextInterpolation(PhpOpen), IfStatement(if, ParenthesizedExpression(Boolean), Block( ClassDeclaration(class, Name, DeclarationList ) ) ) ) # Class constant modifiers Template( TextInterpolation(PhpOpen), ClassDeclaration(class, Name, DeclarationList( ConstDeclaration(const, VariableDeclarator(Name, AssignOp, Integer) ), ConstDeclaration(Visibility, const, VariableDeclarator(Name, AssignOp, Integer) ), ConstDeclaration(Visibility, const, VariableDeclarator(Name, AssignOp, Integer) ), ConstDeclaration(Visibility, const, VariableDeclarator(Name, AssignOp, Integer) ), ConstDeclaration(final, const, VariableDeclarator(Name, AssignOp, Integer) ) ) ) ) # Final class Template( TextInterpolation(PhpOpen), ClassDeclaration(final, class, Name, DeclarationList ) ) # Implicitly public properties and methods Template( TextInterpolation(PhpOpen), ClassDeclaration(abstract, class, Name, DeclarationList( PropertyDeclaration( var, VariableDeclarator(VariableName) ), PropertyDeclaration( static, VariableDeclarator(VariableName) ), MethodDeclaration(abstract, function, Name, ParamList ), MethodDeclaration(final, function, Name, ParamList, Block ), MethodDeclaration(static, function, Name, ParamList, Block ), MethodDeclaration(final, static, function, Name, ParamList, Block ), MethodDeclaration(function, Name, ParamList, Block ) ) ) ) # Property Types Template( TextInterpolation(PhpOpen), ClassDeclaration(class, Name, DeclarationList( PropertyDeclaration( Visibility, NamedType(Name), VariableDeclarator(VariableName) ), PropertyDeclaration( Visibility, static, NamedType(Name), VariableDeclarator(VariableName) ), PropertyDeclaration( Visibility, OptionalType(LogicOp, NamedType(Name)), VariableDeclarator(VariableName) ), PropertyDeclaration( Visibility, VariableDeclarator(VariableName) ) ) ) ) # Constructor Property Promotion Template( TextInterpolation(PhpOpen), ClassDeclaration(class, Name, DeclarationList( MethodDeclaration(Visibility, function, Name, ParamList( PropertyParameter( Visibility, NamedType(Name), VariableName, AssignOp, Float ), Parameter( NamedType(Name), VariableName, AssignOp, Float ), PropertyParameter( Visibility, NamedType(Name), VariableName, AssignOp, Float ) ), Block ) ) ) ) # Class constant Template( TextInterpolation(PhpOpen), ExpressionStatement( ScopedExpression( Name, ClassMemberName(Name) ), ";" ) )php-1.0.2/test/declarations.txt000066400000000000000000000222251454332741300165020ustar00rootroot00000000000000# Interface declarations foo; } } ==> Template( TextInterpolation(PhpOpen), InterfaceDeclaration(interface, Name, DeclarationList( MethodDeclaration( Visibility, function, Name, ParamList))), ClassDeclaration( class, Name, ClassInterfaceClause(implements, Name), DeclarationList( PropertyDeclaration( Visibility, VariableDeclarator(VariableName, AssignOp, String)), MethodDeclaration( Visibility, function, Name, ParamList, Block( ReturnStatement(return,MemberExpression( VariableName, Name))))))) # Use declarations Template( TextInterpolation(PhpOpen), TraitDeclaration(trait, Name, DeclarationList( UseDeclaration(use,Name), UseDeclaration(use,Name, Name, UseList), UseDeclaration(use,Name, Name))), ClassDeclaration( class, Name, DeclarationList( UseDeclaration(use, Name, UseList( UseAsClause(Name, as, Visibility), UseAsClause(ScopedExpression(Name, ClassMemberName(Name)), as, Name), UseAsClause(ScopedExpression(Name, ClassMemberName(Name)), as, Name)))))) # Namespace names in namespaces Template( TextInterpolation(PhpOpen), NamespaceDefinition(namespace, QualifiedName(NamespaceName(Name), Name), Block( ClassDeclaration(class, Name, DeclarationList), ClassDeclaration(class, Name, DeclarationList)))) # Class declarations Name = $name; $GLOBALS['List']->echoName(); } function echoName() { $GLOBALS['names'][]=$this->Name; } } ==> Template( TextInterpolation(PhpOpen), ClassDeclaration(class, Name, DeclarationList( MethodDeclaration(function, Name, ParamList( Parameter( VariableName)), Block( ExpressionStatement(AssignmentExpression( SubscriptExpression(VariableName, String), AssignOp, VariableName)), ExpressionStatement(AssignmentExpression( MemberExpression( VariableName, Name), AssignOp, VariableName)), ExpressionStatement(CallExpression( MemberExpression(SubscriptExpression(VariableName, String), Name), ArgList)))), MethodDeclaration(function, Name, ParamList, Block( ExpressionStatement(AssignmentExpression( SubscriptExpression(SubscriptExpression(VariableName, String)), AssignOp, MemberExpression(VariableName,Name)))))))) # Class declarations with base classes Template( TextInterpolation(PhpOpen), ClassDeclaration(class, Name, BaseClause(extends, Name), DeclarationList)) # Function parameters Template( TextInterpolation(PhpOpen), FunctionDefinition(function, Name, ParamList( Parameter( NamedType(Name), VariableName), VariadicParameter( NamedType(Name), VariableName)), Block)) # Functions with default parameters Template( TextInterpolation(PhpOpen), FunctionDefinition(function, Name, ParamList( Parameter( VariableName, AssignOp, ScopedExpression(Name, ClassMemberName(Name)))), Block(EchoStatement(echo,VariableName)))) # Static variables in functions Template( TextInterpolation(PhpOpen), FunctionDefinition(function, Name, ParamList, Block( FunctionStaticDeclaration(static, VariableDeclarator(VariableName, AssignOp, Integer), VariableDeclarator(VariableName, AssignOp, Integer))))) # Defining Constants Template( TextInterpolation(PhpOpen), ExpressionStatement( CallExpression( Name, ArgList(String,String) ) ), ConstDeclaration(const, VariableDeclarator( Name, AssignOp, String ) ), ConstDeclaration(const, VariableDeclarator( Name, AssignOp, BinaryExpression( Name, ConcatOp, String ) ) ), ConstDeclaration(const, VariableDeclarator( Name, AssignOp, ArrayExpression(array, ValueList(String,String,String)) ) ), ExpressionStatement( CallExpression( Name, ArgList( String, ArrayExpression(array, ValueList(String,String,String)) ) ) ) ) # Attributes "value"))] #[MyAttribute(100 + 200)] class Thing { } ==> Template( TextInterpolation(PhpOpen), FunctionDefinition( Attributes(Attribute(Name)), function, Name, ParamList( Parameter( Attributes(Attribute(Name)), VariableName ) ), Block(ExpressionStatement(VariableName)) ), ClassDeclaration(class, Name, DeclarationList( ConstDeclaration( Attributes(Attribute(Name)), const, VariableDeclarator(Name, AssignOp, String) ), PropertyDeclaration( Attributes(Attribute(Name)), Visibility, NamedType(Name), VariableDeclarator(VariableName, AssignOp, String) ), MethodDeclaration( Attributes( Attribute( Name, ArgList( String, ArrayExpression(String) ) ) ), Visibility, function, Name, ParamList( Parameter( Attributes(Attribute(Name)), VariableName ) ), Block(BlockComment) ) ) ), ClassDeclaration( Attributes(Attribute(Name)), Attributes(Attribute(QualifiedName(NamespaceName(Name),Name))), Attributes(Attribute(Name,ArgList(Integer))), Attributes(Attribute(Name,ArgList(ScopedExpression(Name,ClassMemberName(Name))))), Attributes(Attribute(Name,ArgList(ArrayExpression(array, ValueList(Pair(String, String)))))), Attributes(Attribute(Name,ArgList(BinaryExpression(Integer, ArithOp, Integer)))), class, Name, DeclarationList ) ) # Enums 'Red', Suit::Clubs, Suit::Spades => 'Black', }; } } ==> Template( TextInterpolation(PhpOpen), EnumDeclaration(enum, Name, EnumBody ), EnumDeclaration(enum, Name, ClassInterfaceClause(implements, Name, Name), EnumBody ), EnumDeclaration(enum, Name, NamedType(Name), ClassInterfaceClause(implements, Name), EnumBody ), EnumDeclaration(enum, Name, NamedType(Name), EnumBody( EnumCase(case, Name, AssignOp, String), EnumCase(case, Name), EnumCase(case, Name, AssignOp, String), EnumCase(case, Name, AssignOp, String), LineComment, MethodDeclaration( Visibility, function, Name, ParamList, NamedType(Name), Block( ReturnStatement(return, MatchExpression(match, ParenthesizedExpression( VariableName ), MatchBlock( MatchArm( ScopedExpression(Name, ClassMemberName(Name)), ScopedExpression(Name, ClassMemberName(Name)), String ), MatchArm( ScopedExpression(Name, ClassMemberName(Name)), ScopedExpression(Name, ClassMemberName(Name)), String ) ) ) ) ) ) ) ) ) php-1.0.2/test/expressions.txt000066400000000000000000000504571454332741300164240ustar00rootroot00000000000000# Dynamic variable names Template( TextInterpolation(PhpOpen), ExpressionStatement(AssignmentExpression( DynamicVariable(VariableName), AssignOp, VariableName))) # Exponentiation Template( TextInterpolation(PhpOpen), ExpressionStatement( AssignmentExpression( VariableName, AssignOp, BinaryExpression(Integer, ArithOp, Integer) ) ), ExpressionStatement( AssignmentExpression( VariableName, AssignOp, Integer)), EchoStatement(echo, BinaryExpression(VariableName, ArithOp, UnaryExpression(ArithOp, VariableName)) ), ExpressionStatement( BinaryExpression( VariableName, ArithOp, UpdateExpression( VariableName, UpdateOp, VariableName ) ) ), ExpressionStatement( BinaryExpression( VariableName, ArithOp, AssignmentExpression( VariableName, AssignOp, VariableName ) ) ) ) # Reserved Identifiers as Names Template( TextInterpolation(PhpOpen), ExpressionStatement(AssignmentExpression( VariableName, AssignOp, NewExpression(new, Name, ArgList)))) # Unary op with assignment expressions Template( TextInterpolation(PhpOpen), IfStatement(if, ParenthesizedExpression(UnaryExpression(LogicOp, AssignmentExpression( VariableName, AssignOp, VariableName))), Block)) # Capitalized logical operators Template( TextInterpolation(PhpOpen), ExpressionStatement( BinaryExpression( CallExpression(Name, ArgList), LogicOp, BinaryExpression( CallExpression(Name, ArgList), LogicOp, CallExpression(Name, ArgList))))) # Reserved words as function calls current()); ==> Template( TextInterpolation(PhpOpen), ExpressionStatement(AssignmentExpression( VariableName, AssignOp, NewExpression(new, Name, ArgList( CallExpression(MemberExpression(VariableName, Name), ArgList)))))) # Scoped self call expressions Template( TextInterpolation(PhpOpen), ExpressionStatement( CallExpression(ScopedExpression(Name, ClassMemberName(Name)), ArgList))) # Symmetric array destructuring Template( TextInterpolation(PhpOpen), ExpressionStatement( AssignmentExpression( VariableName, AssignOp, ArrayExpression( ArrayExpression(Integer, String), ArrayExpression(Integer, String) ) ) ), LineComment, ExpressionStatement( AssignmentExpression( ListExpression(list, ValueList(VariableName,VariableName)), AssignOp, SubscriptExpression( VariableName, Integer ) ) ), LineComment, ExpressionStatement( AssignmentExpression( ListExpression(list,ValueList(VariableName,VariableName)), AssignOp, SubscriptExpression( VariableName, Integer ) ) ), LineComment, ExpressionStatement( AssignmentExpression( ListExpression(list,ValueList(VariableName)), AssignOp, SubscriptExpression( VariableName, Integer ) ) ), LineComment, ExpressionStatement( AssignmentExpression( ArrayExpression(VariableName,VariableName), AssignOp, SubscriptExpression( VariableName, Integer ) ) ), LineComment, ExpressionStatement( AssignmentExpression( ArrayExpression( VariableName, VariableName ), AssignOp, SubscriptExpression( VariableName, Integer ) ) ), LineComment, ExpressionStatement( AssignmentExpression( ArrayExpression(VariableName), AssignOp, SubscriptExpression( VariableName, Integer ) ) ), ExpressionStatement( AssignmentExpression( ArrayExpression( VariableName, VariableName ), AssignOp, CallExpression( ScopedExpression(Name, ClassMemberName(Name)), ArgList(VariableName) ) ) ) ) # Precedence of assignment, `or`, `xor`, and `and` Template( TextInterpolation(PhpOpen), ExpressionStatement( BinaryExpression( AssignmentExpression( VariableName, AssignOp, Boolean), LogicOp, Boolean)), ExpressionStatement( BinaryExpression( AssignmentExpression( VariableName, AssignOp, Boolean), LogicOp, Boolean)), ExpressionStatement( BinaryExpression( AssignmentExpression( VariableName, AssignOp, Boolean), LogicOp, Boolean)), ExpressionStatement( BinaryExpression( BinaryExpression( AssignmentExpression( VariableName, AssignOp, Boolean), LogicOp, Boolean), LogicOp, BinaryExpression( Boolean, LogicOp, BinaryExpression( Boolean, LogicOp, Boolean))))) # Associativity of conditional ==> Template( TextInterpolation(PhpOpen), ExpressionStatement( ConditionalExpression( ConditionalExpression(Boolean, LogicOp, Boolean, Boolean), LogicOp, String, String)), TextInterpolation(PhpClose)) # Associativity of null-coalescence ==> Template( TextInterpolation(PhpOpen), ExpressionStatement( BinaryExpression( null, LogicOp, BinaryExpression( null, LogicOp, Integer))), TextInterpolation(PhpClose)) # Associativity of negation ==> Template( TextInterpolation(PhpOpen), ExpressionStatement( BinaryExpression( UnaryExpression(ArithOp, Integer), ArithOp, UnaryExpression(ArithOp, Integer))), ExpressionStatement( UnaryExpression(LogicOp, BinaryExpression(VariableName, LogicOp, Name))), TextInterpolation(PhpClose)) # Augmented assignment ==> Template( TextInterpolation(PhpOpen), ExpressionStatement( UpdateExpression( VariableName, UpdateOp, AssignmentExpression( VariableName, AssignOp, String))), ExpressionStatement( UpdateExpression( VariableName, UpdateOp, UpdateExpression( VariableName, UpdateOp, Integer))), ExpressionStatement( UpdateExpression( VariableName, UpdateOp, BinaryExpression(String, ConcatOp, String))), ExpressionStatement( BinaryExpression( String, ConcatOp, UpdateExpression( VariableName, UpdateOp, String))), TextInterpolation(PhpClose)) # Nested assignemnts Template( TextInterpolation(PhpOpen), ExpressionStatement( AssignmentExpression( VariableName, AssignOp, AssignmentExpression( SubscriptExpression(VariableName, Integer), AssignOp, AssignmentExpression( SubscriptExpression(VariableName, Integer), AssignOp, VariableName))))) # All binary op precedence levels 12 << 13 + 14 * (int) 15 instanceof foo; (int) 1 instanceof foo / 3 - 4 >> 5 <= 6 <=> 7 & 8 ^ 9 | 10 && 11 || 12 ?? $i += 13 and 14 xor 15 or 16; ==> Template( TextInterpolation(PhpOpen), ExpressionStatement( BinaryExpression( Integer, LogicOp, BinaryExpression( Integer, LogicOp, BinaryExpression( Integer, LogicOp, UpdateExpression( VariableName, UpdateOp, BinaryExpression( Integer, LogicOp, BinaryExpression( Integer, LogicOp, BinaryExpression( Integer, LogicOp, BinaryExpression( Integer, BitOp, BinaryExpression( Integer, BitOp, BinaryExpression( Integer, BitOp, BinaryExpression( Integer, CompareOp, BinaryExpression( Integer, CompareOp, BinaryExpression( Integer, BitOp, BinaryExpression( Integer, ArithOp, BinaryExpression( Integer, ArithOp, BinaryExpression( CastExpression( NamedType(Name), Integer), LogicOp, Name))))))))))))))))), ExpressionStatement( BinaryExpression( BinaryExpression( BinaryExpression( BinaryExpression( BinaryExpression( BinaryExpression( BinaryExpression( BinaryExpression( BinaryExpression( BinaryExpression( BinaryExpression( BinaryExpression( BinaryExpression( BinaryExpression( BinaryExpression( CastExpression( NamedType(Name), Integer), LogicOp, Name), ArithOp, Integer), ArithOp, Integer), BitOp, Integer), CompareOp, Integer), CompareOp, Integer), BitOp, Integer), BitOp, Integer), BitOp, Integer), LogicOp, Integer), LogicOp, Integer), LogicOp, UpdateExpression( VariableName, UpdateOp, Integer)), LogicOp, Integer), LogicOp, Integer), LogicOp, Integer))) # Concatenation precedence Template( TextInterpolation(PhpOpen), ExpressionStatement( BinaryExpression( String, ConcatOp, BinaryExpression( String, ArithOp, Integer ) ) ) ) # Arrays "orange", "bar" => "apple", "baz" => "lemon"]); $a = [...$values]; ?> ==> Template( TextInterpolation(PhpOpen), ExpressionStatement(CallExpression( Name, ArgList(ArrayExpression(Integer, Integer, Integer)))), ExpressionStatement( CallExpression( Name, ArgList( ArrayExpression(Pair(String, String), Pair(String, String), Pair(String, String))))), ExpressionStatement( AssignmentExpression( VariableName, AssignOp, ArrayExpression(VariadicUnpacking(VariableName)) ) ), TextInterpolation(PhpClose)) # Anonymous functions Template( TextInterpolation(PhpOpen), ExpressionStatement( CallExpression( Name, ArgList( FunctionExpression(function, ParamList, Block(EchoStatement(echo, String)))))), ExpressionStatement( CallExpression( Name, ArgList( FunctionExpression(function, ParamList(Parameter(VariableName)), use, UseList(VariableName), Block(ExpressionStatement(UpdateExpression( VariableName, UpdateOp, VariableName)))), Integer))), ExpressionStatement( CallExpression( Name, ArgList( FunctionExpression(function, ParamList(Parameter(VariableName)), use, UseList(VariableName), Block(ExpressionStatement(UpdateExpression( VariableName, UpdateOp, VariableName)))), Integer)))) # Throw expressions createNotFoundException(); throw static::createNotFoundException(); throw $userIsAuthorized ? new ForbiddenException() : new UnauthorizedException(); throw $maybeNullException ?? new Exception(); throw $exception = new Exception(); throw $condition1 && $condition2 ? new Exception1() : new Exception2(); throw $exception ??= new Exception(); ==> Template( TextInterpolation(PhpOpen), ExpressionStatement( ThrowExpression(throw, NewExpression(new, Name, ArgList(Name) ) ) ), ExpressionStatement( AssignmentExpression( VariableName, AssignOp, ConditionalExpression( UnaryExpression(LogicOp, CallExpression(Name, ArgList(VariableName))), LogicOp, CallExpression(Name, ArgList(VariableName)), ThrowExpression(throw, NewExpression(new, Name, ArgList)) ) ) ), ExpressionStatement( BinaryExpression( VariableName, LogicOp, ThrowExpression(throw, NewExpression(new, Name, ArgList) ) ) ), ExpressionStatement( BinaryExpression( VariableName, LogicOp, ThrowExpression(throw, NewExpression(new, Name, ArgList) ) ) ), ExpressionStatement( BinaryExpression( VariableName, LogicOp, ThrowExpression(throw, NewExpression(new, Name, ArgList) ) ) ), ExpressionStatement( BinaryExpression( VariableName, LogicOp, ThrowExpression(throw, NewExpression(new, Name, ArgList) ) ) ), ExpressionStatement( ThrowExpression(throw, CallExpression(MemberExpression(VariableName, Name), ArgList) ) ), ExpressionStatement( ThrowExpression(throw, CallExpression( ScopedExpression(Name, ClassMemberName(Name)), ArgList ) ) ), ExpressionStatement( ThrowExpression(throw, ConditionalExpression( VariableName, LogicOp, NewExpression(new, Name, ArgList), NewExpression(new, Name, ArgList) ) ) ), ExpressionStatement( ThrowExpression(throw, BinaryExpression( VariableName, LogicOp, NewExpression(new, Name, ArgList) ) ) ), ExpressionStatement( ThrowExpression(throw, AssignmentExpression( VariableName, AssignOp, NewExpression(new, Name, ArgList) ) ) ), ExpressionStatement( ThrowExpression(throw, ConditionalExpression( BinaryExpression( VariableName, LogicOp, VariableName ), LogicOp, NewExpression(new, Name, ArgList), NewExpression(new, Name, ArgList) ) ) ), ExpressionStatement( ThrowExpression(throw, UpdateExpression( VariableName, UpdateOp, NewExpression(new, Name, ArgList) ) ) ) ) # Nullsafe operator b; $a?->b($c); new $a?->b; $country = $session?->user?->getAddress()?->country; ==> Template( TextInterpolation(PhpOpen), ExpressionStatement( MemberExpression( VariableName, Name ) ), ExpressionStatement( CallExpression( MemberExpression(VariableName, Name), ArgList(VariableName) ) ), ExpressionStatement( NewExpression(new, MemberExpression(VariableName, Name)) ), ExpressionStatement( AssignmentExpression( VariableName, AssignOp, MemberExpression( CallExpression( MemberExpression(MemberExpression(VariableName, Name), Name), ArgList ), Name ) ) ) ) # Match expressions $b, Lexer::T_UPDATE => updateStatement(), Lexer::T_DELETE => $this->DeleteStatement(), default => $this->syntaxError('SELECT, UPDATE or DELETE'), }; ==> Template( TextInterpolation(PhpOpen), ExpressionStatement( AssignmentExpression( VariableName, AssignOp, MatchExpression(match, ParenthesizedExpression(VariableName), MatchBlock( MatchArm( ScopedExpression(Name, ClassMemberName(Name)), VariableName VariableName ), MatchArm( ScopedExpression(Name, ClassMemberName(Name)), CallExpression(Name, ArgList) ), MatchArm( ScopedExpression(Name, ClassMemberName(Name)) CallExpression(MemberExpression(VariableName, Name), ArgList) ), MatchArm( default, CallExpression(MemberExpression(VariableName, Name), ArgList(String)) ) ) ) ) ) ) # Arrow functions $a; fn($x = 42) => $x; static fn(&$x) => $x; fn&($x) => $x; fn($x, ...$rest) => $rest; fn(): int => $x; $fn1 = fn($x) => $x + $y; ==> Template( TextInterpolation(PhpOpen), ExpressionStatement( ArrowFunction(fn, ParamList( Parameter( NamedType(Name), VariableName ) ), VariableName ) ), ExpressionStatement( ArrowFunction(fn, ParamList( Parameter( VariableName, AssignOp, Integer) ), VariableName ) ), ExpressionStatement( ArrowFunction(static, fn, ParamList(Parameter(VariableName)), VariableName ) ), ExpressionStatement( ArrowFunction(fn, ParamList(Parameter(VariableName)), VariableName ) ), ExpressionStatement( ArrowFunction(fn, ParamList( Parameter(VariableName), VariadicParameter(VariableName)), VariableName)), ExpressionStatement( ArrowFunction(fn, ParamList, NamedType(Name), VariableName ) ), ExpressionStatement( AssignmentExpression( VariableName, AssignOp, ArrowFunction(fn, ParamList( Parameter(VariableName) ), BinaryExpression(VariableName, ArithOp, VariableName) ) ) ) ) # Functions with named arguments Template( TextInterpolation(PhpOpen), ExpressionStatement( CallExpression( Name, ArgList( NamedArgument(Name, Integer), NamedArgument(Name, Integer), NamedArgument(Name, VariableName) ) ) ) ) # Precedence between concatenation and shift Template( TextInterpolation(PhpOpen), ExpressionStatement( BinaryExpression( VariableName, ConcatOp, BinaryExpression(VariableName, BitOp, VariableName)))) php-1.0.2/test/interpolation.txt000066400000000000000000000047061454332741300167250ustar00rootroot00000000000000# no interpolated text Template( TextInterpolation(PhpOpen), EchoStatement(echo,String)) # interpolated text at beginning
Template( TextInterpolation(Text, PhpOpen), EchoStatement(echo,String)) # interpolated text at end
==> Template( TextInterpolation(PhpOpen), EchoStatement(echo,String), TextInterpolation(PhpClose, Text)) # interpolated text in middle
==> Template( TextInterpolation(PhpOpen), EchoStatement(echo,String), TextInterpolation(PhpClose, Text, PhpOpen), EchoStatement(echo,String), TextInterpolation(PhpClose)) # short open tag: On Finished ==> Template( TextInterpolation(PhpOpen), EchoStatement(echo,String(EscapeSequence)), TextInterpolation(PhpClose, Text)) # short open tag: Off
one
two
==> Template( TextInterpolation(Text,PhpOpen), ExpressionStatement(AssignmentExpression(VariableName, AssignOp, String)), TextInterpolation(PhpClose,Text,PhpOpen), ExpressionStatement(VariableName), TextInterpolation(PhpClose,Text,PhpOpen), ExpressionStatement(AssignmentExpression(VariableName, AssignOp, Integer)), TextInterpolation(PhpClose,Text,PhpOpen), EchoStatement(echo,String(Interpolation(VariableName))), TextInterpolation(PhpClose,Text,PhpOpen), ExpressionStatement(String(Interpolation(VariableName))), TextInterpolation(PhpClose)) # Single line php comment
Template( TextInterpolation(Text, PhpOpen), LineComment, TextInterpolation(PhpClose, Text, PhpOpen), LineComment, LineComment, EchoStatement(echo,String)) # Single line comment without any content Template( TextInterpolation(PhpOpen), LineComment, LineComment, IfStatement(if, ParenthesizedExpression( UnaryExpression(LogicOp, CallExpression(Name,ArgList(String))) ), Block(EchoStatement(echo,VariableName)) ) ) # Closing tags before the first PHP tag a ?> b Template( TextInterpolation(Text, PhpOpen), ExpressionStatement(Name)) # Text ends in a less-than char foo< ==> Template(Text) php-1.0.2/test/literals.txt000066400000000000000000000060571454332741300156560ustar00rootroot00000000000000# Booleans ==> Template( TextInterpolation(PhpOpen), ExpressionStatement(Boolean), ExpressionStatement(Boolean), ExpressionStatement(Boolean), ExpressionStatement(Boolean), ExpressionStatement(Boolean), ExpressionStatement(Boolean), TextInterpolation(PhpClose)) # Floats Template( TextInterpolation(PhpOpen), ExpressionStatement(Float), ExpressionStatement(Float), ExpressionStatement(Float), ExpressionStatement(Float), ExpressionStatement(Float), ExpressionStatement(Float), ExpressionStatement(Float) ) # Integers Template( TextInterpolation(PhpOpen), ExpressionStatement(Integer), ExpressionStatement(Integer), ExpressionStatement(Integer), ExpressionStatement(Integer), ExpressionStatement(Integer), ExpressionStatement(Integer), ExpressionStatement(Integer), ExpressionStatement(Integer), ExpressionStatement(Integer) ) # Testing string scanner conformance ==> Template( TextInterpolation(PhpOpen), EchoStatement(echo, BinaryExpression(String(EscapeSequence, EscapeSequence, EscapeSequence), ConcatOp, String)), TextInterpolation(PhpClose)) # Shell command Template( TextInterpolation(PhpOpen), ExpressionStatement(ShellExpression), ExpressionStatement(ShellExpression)) # Heredocs Template( TextInterpolation(PhpOpen), ExpressionStatement(HeredocString), TextInterpolation(PhpClose,Text,PhpOpen), ExpressionStatement(HeredocString), ExpressionStatement(HeredocString), LineComment, ExpressionStatement( CallExpression( Name, ArgList(HeredocString) ) ), ExpressionStatement( CallExpression( Name, ArgList( HeredocString, Boolean ) ) ) ) # Nowdocs ==> Template( TextInterpolation(PhpOpen), ExpressionStatement(HeredocString), TextInterpolation(PhpClose)) # Unicode escape sequences Template( TextInterpolation(PhpOpen), ExpressionStatement(String(EscapeSequence)), LineComment, ExpressionStatement(String(EscapeSequence)), LineComment, ExpressionStatement(String(EscapeSequence)), LineComment, ExpressionStatement(String(EscapeSequence)), LineComment, ExpressionStatement(String(EscapeSequence)), LineComment, ExpressionStatement(String(EscapeSequence)), LineComment) php-1.0.2/test/statements.txt000066400000000000000000000160671454332741300162300ustar00rootroot00000000000000# If statements 0) { echo "Yes"; } if ($a==0) { echo "bad"; } else { echo "good"; } if ($a==0) { echo "bad"; } elseif ($a==3) { echo "bad"; } else { echo "good"; } ==> Template( TextInterpolation(PhpOpen), IfStatement(if, ParenthesizedExpression(BinaryExpression( VariableName, CompareOp, Integer)), Block(EchoStatement(echo,String))), IfStatement(if, ParenthesizedExpression(BinaryExpression( VariableName, CompareOp, Integer)), Block(EchoStatement(echo,String)), else, Block(EchoStatement(echo,String))), IfStatement(if, ParenthesizedExpression(BinaryExpression( VariableName, CompareOp, Integer)), Block(EchoStatement(echo,String)), elseif, ParenthesizedExpression(BinaryExpression(VariableName,CompareOp,Integer)), Block(EchoStatement(echo,String)), else, Block(EchoStatement(echo,String)))) # Alternative if statements Template( TextInterpolation(PhpOpen), IfStatement(if, ParenthesizedExpression(VariableName), EchoStatement(echo,Integer), else, EchoStatement(echo,Integer)), IfStatement(if, ParenthesizedExpression(VariableName), ColonBlock( EchoStatement(echo,Integer), EchoStatement(echo,Integer)), else, ColonBlock(EchoStatement(echo,Integer)), endif)) # While statements Template( TextInterpolation(PhpOpen), WhileStatement(while, ParenthesizedExpression(BinaryExpression(VariableName,CompareOp,Integer)), Block( EchoStatement(echo,VariableName), ExpressionStatement(UpdateExpression(VariableName, ArithOp))))) # Alternative while statements Template( TextInterpolation(PhpOpen), WhileStatement(while, ParenthesizedExpression(BinaryExpression(VariableName, CompareOp, Integer)), EchoStatement(echo,UpdateExpression(VariableName, ArithOp))), WhileStatement(while, ParenthesizedExpression(BinaryExpression(VariableName, CompareOp, Integer)), ColonBlock( EchoStatement(echo,UpdateExpression(ArithOp, VariableName)), EchoStatement(echo,VariableName)), endwhile)) # For statements Template( TextInterpolation(PhpOpen), ForStatement(for, ForSpec( AssignmentExpression(VariableName, AssignOp, Integer), BinaryExpression(VariableName, CompareOp, Integer), UpdateExpression(VariableName, ArithOp)), EchoStatement(echo,VariableName)), ForStatement(for, ForSpec( AssignmentExpression(VariableName, AssignOp, Integer), BinaryExpression(VariableName, CompareOp, Integer), UpdateExpression(VariableName, ArithOp)), ColonBlock(EchoStatement(echo,VariableName)), endfor)) # Switch statements ==> Template( TextInterpolation(PhpOpen), SwitchStatement(switch, ParenthesizedExpression(VariableName), Block( CaseStatement(case, Integer, EchoStatement(echo,String), BreakStatement(break)), CaseStatement(case, Integer, EchoStatement(echo,String), BreakStatement(break)), DefaultStatement(default, EchoStatement(echo,String), BreakStatement(break)))), TextInterpolation(PhpClose)) # Alternative switch statements Template( TextInterpolation(PhpOpen), SwitchStatement(switch, ParenthesizedExpression(VariableName), ColonBlock( CaseStatement(case, Integer, EchoStatement(echo,Integer), BreakStatement(break)), CaseStatement(case, Integer, EchoStatement(echo,Integer), BreakStatement(break)), DefaultStatement(default, EchoStatement(echo,Integer), BreakStatement(break))) endswitch)) # Include statement Template( TextInterpolation(PhpOpen), ExpressionStatement(IncludeExpression(include, String))) # Do-while statements 0); ==> Template( TextInterpolation(PhpOpen), DoStatement(do, Block( EchoStatement(echo,VariableName), ExpressionStatement(UpdateExpression(VariableName, ArithOp))), while, ParenthesizedExpression(BinaryExpression(VariableName, CompareOp, Integer)))) # Try statements getException(); print "\n"; } ==> Template( TextInterpolation(PhpOpen), TryStatement( try, Block, catch, CatchDeclarator(NamedType(Name)), Block, catch, CatchDeclarator(UnionType(NamedType(Name), LogicOp, NamedType(Name)), VariableName), Block, finally, Block), TryStatement( try, Block(ExpressionStatement(CallExpression(Name,ArgList))), catch, CatchDeclarator(NamedType(Name), VariableName), Block( ExpressionStatement(PrintIntrinsic(print, BinaryExpression( String, ConcatOp, CallExpression(MemberExpression(VariableName,Name),ArgList)))), ExpressionStatement(PrintIntrinsic(print, String(EscapeSequence)))))) # Foreach statements $value); foreach($a as $b): echo $a; echo $b; endforeach; ==> Template( TextInterpolation(PhpOpen), ForeachStatement(foreach, ForSpec(VariableName, as, SubscriptExpression(VariableName, Integer)), Block( EchoStatement(echo,BinaryExpression( SubscriptExpression(VariableName, Integer), ConcatOp, String(EscapeSequence))))), ForeachStatement(foreach, ForSpec(VariableName, as, Pair(VariableName, VariableName)), EmptyStatement), ForeachStatement(foreach, ForSpec(VariableName, as, VariableName), ColonBlock( EchoStatement(echo,VariableName), EchoStatement(echo,VariableName)), endforeach)) # Case insensitive keywords Template( TextInterpolation(PhpOpen), ForeachStatement(foreach, ForSpec(VariableName, as, VariableName), Block( DoStatement(do, Block( IfStatement(if, ParenthesizedExpression(VariableName), Block(ExpressionStatement(CallExpression(Name, ArgList))), else, Block(ExpressionStatement(CallExpression(Name, ArgList))))), while, ParenthesizedExpression(VariableName))))) # Accessing Constants Template( TextInterpolation(PhpOpen), EchoStatement(echo, Name ), EchoStatement(echo, SubscriptExpression( Name, Integer ) ) ) php-1.0.2/test/string.txt000066400000000000000000000173271454332741300153470ustar00rootroot00000000000000# Complex: Variable access Template( TextInterpolation(PhpOpen), ExpressionStatement( String(Interpolation(VariableName)) ) ) # Complex: Disallow space between { and $ Template( TextInterpolation(PhpOpen), ExpressionStatement( String(VariableName) ) ) # Complex: PHP documentation tests width}00 centimeters broad."; // Works, quoted keys only work using the curly brace syntax "This works: {$arr['key']}"; "This works: {$arr[4][3]}"; // Works. When using multi-dimensional arrays, always use braces around arrays // when inside of strings "This works: {$arr['foo'][3]}"; "This works: " . $arr['foo'][3]; "This works too: {$obj->values[3]->name}"; "This is the value of the var named $name: {${$name}}"; "This is the value of the var named by the return value of getName(): {${getName()}}"; "This is the value of the var named by the return value of \$object->getName(): {${$object->getName()}}"; // Won't work, outputs: This is the return value of getName(): {getName()} "This is the return value of getName(): {getName()}"; "{$foo->$bar}\n"; "{$foo->{$baz[1]}}\n"; "I'd like an {${beers::softdrink}}\n"; "I'd like an {${beers::$ale}}\n"; ==> Template( TextInterpolation(PhpOpen), ExpressionStatement( String(Interpolation(VariableName)) ), ExpressionStatement( String(Interpolation(MemberExpression(VariableName, Name))) ), LineComment, ExpressionStatement( String(Interpolation(SubscriptExpression(VariableName, String)))), ExpressionStatement( String(Interpolation(SubscriptExpression(SubscriptExpression(VariableName,Integer),Integer))) ), LineComment, LineComment, ExpressionStatement( String(Interpolation(SubscriptExpression(SubscriptExpression(VariableName,String),Integer))) ), ExpressionStatement( BinaryExpression( String, ConcatOp, SubscriptExpression(SubscriptExpression(VariableName,String),Integer)) ), ExpressionStatement( String( Interpolation(MemberExpression( SubscriptExpression( MemberExpression( VariableName, Name ), Integer ), Name )) ) ), ExpressionStatement( String( VariableName, Interpolation(DynamicVariable(VariableName)) ) ), ExpressionStatement( String( Interpolation(DynamicVariable(CallExpression(Name,ArgList))) ) ), ExpressionStatement( String( EscapeSequence, Interpolation(DynamicVariable( CallExpression(MemberExpression(VariableName, Name), ArgList) )) ) ), LineComment, ExpressionStatement(String), ExpressionStatement( String( Interpolation(MemberExpression(VariableName,VariableName)), EscapeSequence ) ), ExpressionStatement( String( Interpolation(MemberExpression( VariableName, SubscriptExpression( VariableName, Integer ) )), EscapeSequence ) ), ExpressionStatement( String( Interpolation(DynamicVariable( ScopedExpression( Name, ClassMemberName(Name) ) )), EscapeSequence ) ), ExpressionStatement( String( Interpolation(DynamicVariable( ScopedExpression( Name, ClassMemberName(VariableName) ) )), EscapeSequence ) ) ) # Simple: Variable access Template( TextInterpolation(PhpOpen), ExpressionStatement( String(VariableName) ), ExpressionStatement( String(Interpolation(Name)) ) ) # Simple: Member and array access john drank some $juices[0] juice.".PHP_EOL; "$people->john then said hello to $people?->jane.".PHP_EOL; "$people->john's wife greeted $people->robert."; "The character at index -2 is $string[-2]."; ==> Template( TextInterpolation(PhpOpen), ExpressionStatement( BinaryExpression( String( MemberExpression(VariableName,Name), SubscriptExpression(VariableName,Integer), ), ConcatOp, Name ) ), ExpressionStatement( BinaryExpression( String( MemberExpression(VariableName,Name), MemberExpression(VariableName,Name), ), ConcatOp, Name ) ), ExpressionStatement( String( MemberExpression(VariableName,Name), MemberExpression(VariableName,Name), ) ), ExpressionStatement( String( SubscriptExpression(VariableName,UnaryExpression(ArithOp,Integer)), ) ) ) # Corner cases tester- Hello"; " # x {$var->prop["key:"."key: {$var->func("arg")}"]}# x"; "hello \0 world"; "hello ${"a"."b"} world"; "$$$$$$$$$$$$$a"; "{$$$$$$$$b}"; "\{$"; "\u{$a}"; ==> Template( TextInterpolation(PhpOpen), ExpressionStatement( String ), ExpressionStatement( String(EscapeSequence) ), ExpressionStatement( String ), ExpressionStatement( String ), ExpressionStatement( String ), ExpressionStatement( String ), ExpressionStatement( String ), ExpressionStatement( String ), ExpressionStatement( String ), ExpressionStatement( String ), ExpressionStatement( String(EscapeSequence) ), ExpressionStatement( String(EscapeSequence) ), ExpressionStatement( String ), ExpressionStatement( String(EscapeSequence) ), ExpressionStatement( String(EscapeSequence,EscapeSequence,EscapeSequence) ), ExpressionStatement( String(EscapeSequence,EscapeSequence,VariableName) ), ExpressionStatement( String(VariableName) ), ExpressionStatement( String(VariableName) ), ExpressionStatement( String(VariableName) ), ExpressionStatement( String( Interpolation(CallExpression(ScopedExpression(VariableName,ClassMemberName(Name)), ArgList)) ) ), ExpressionStatement( String(MemberExpression(VariableName,Name)) ), ExpressionStatement( String( Interpolation(SubscriptExpression( MemberExpression(VariableName,Name), BinaryExpression( String, ConcatOp, String(Interpolation(CallExpression(MemberExpression(VariableName,Name),ArgList(String)))) ) )) ) ), ExpressionStatement( String(EscapeSequence) ), ExpressionStatement( String(Interpolation(BinaryExpression(String,ConcatOp,String))) ), ExpressionStatement( String(VariableName) ), ExpressionStatement( String( Interpolation(DynamicVariable( DynamicVariable( DynamicVariable( DynamicVariable( DynamicVariable( DynamicVariable( DynamicVariable( VariableName ) ) ) ) ) ) )) ) ), ExpressionStatement( String(EscapeSequence) ), ExpressionStatement( String(Interpolation(VariableName)) ) ) # Single quoted Template( TextInterpolation(PhpOpen), ExpressionStatement(String), ExpressionStatement(String), ExpressionStatement(String), ExpressionStatement(String), ExpressionStatement(String), ExpressionStatement(String), ExpressionStatement(String) ) php-1.0.2/test/test-php.js000066400000000000000000000010161454332741300153660ustar00rootroot00000000000000import {parser} from "../dist/index.es.js" import {fileTests} from "@lezer/generator/dist/test" import * as fs from "fs" import * as path from "path" import {fileURLToPath} from "url" let caseDir = path.dirname(fileURLToPath(import.meta.url)) for (let file of fs.readdirSync(caseDir)) { if (!/\.txt$/.test(file)) continue let name = /^[^\.]*/.exec(file)[0] describe(name, () => { for (let {name, run} of fileTests(fs.readFileSync(path.join(caseDir, file), "utf8"), file)) it(name, () => run(parser)) }) } php-1.0.2/test/types.txt000066400000000000000000000037251454332741300152020ustar00rootroot00000000000000# Type names Template( TextInterpolation(PhpOpen), FunctionDefinition(function, Name, ParamList, NamedType(Name), Block), FunctionDefinition(function, Name, ParamList, NamedType(QualifiedName(NamespaceName(Name), Name)), Block)) # Primitive types Template( TextInterpolation(PhpOpen), FunctionDefinition(function, Name, ParamList, NamedType(Name), Block), FunctionDefinition(function, Name, ParamList, NamedType(Name), Block), FunctionDefinition(function, Name, ParamList, NamedType(Name), Block)) # Optional types Template( TextInterpolation(PhpOpen), FunctionDefinition(function, Name, ParamList, OptionalType(LogicOp, NamedType(array)), Block), FunctionDefinition(function, Name, ParamList, OptionalType(LogicOp, NamedType(Name)), Block)) # Union types Template( TextInterpolation(PhpOpen), FunctionDefinition(function, Name, ParamList( Parameter( UnionType(NamedType(Name),LogicOp,NamedType(Name),LogicOp,NamedType(null)), VariableName)), UnionType(OptionalType(LogicOp, NamedType(Name)),LogicOp,NamedType(Name)), Block)) # Mixed type Template( TextInterpolation(PhpOpen), FunctionDefinition(function, Name, ParamList( Parameter( UnionType(NamedType(Name),LogicOp,NamedType(Name)), VariableName ) ), NamedType(Name), Block ) ) # Static type Template( TextInterpolation(PhpOpen), FunctionDefinition(function, Name, ParamList( Parameter(NamedType(Name),VariableName)), NamedType(Name), Block))