Parser 2.0 (Major Delezer) #52

Merged
defunkt merged 35 commits from parser2 into main 2025-12-08 16:35:34 +00:00
Showing only changes of commit cc604bea49 - Show all commits

View File

@ -126,6 +126,10 @@ export class Parser {
if (expr.type.is('ParenExpr') && !this.isExprEnd())
expr = this.functionCall(expr)
// if dotget is followed by binary operator, continue parsing as binary expression
if (expr.type.is('DotGet') && this.is($T.Operator) && !this.is($T.Operator, '|'))
expr = this.dotGetBinOp(expr)
// one | echo
if (allowPipe && this.isPipe())
return this.pipe(expr)
@ -535,10 +539,32 @@ export class Parser {
return nodes ? node.push(left, nodes!) : node.push(left, ...parts)
}
// continue parsing dotget/word binary operation
dotGetBinOp(left: SyntaxNode): SyntaxNode {
while (this.is($T.Operator) && !this.is($T.Operator, '|')) {
const op = this.current().value!
const bp = precedence[op]
if (bp === undefined) break
const opNode = this.op()
const right = this.exprWithPrecedence(bp + 1)
const nodeType = conditionals.has(op) ? 'ConditionalOp' : 'BinOp'
const node = new SyntaxNode(nodeType, left.from, right.to)
node.push(left, opNode, right)
left = node
}
return left
}
// dotget in a statement/expression (something.blah) or (something.blah arg1)
dotGetFunctionCall(): SyntaxNode {
const dotGet = this.dotGet()
// if followed by a binary operator (not pipe), return dotGet/Word as-is for expression parser
if (this.is($T.Operator) && !this.is($T.Operator, '|'))
return dotGet
// dotget not in scope, regular Word
if (dotGet.type.is('Word')) return dotGet