fix dot.get + thing

This commit is contained in:
Chris Wanstrath 2025-11-25 16:27:18 -08:00 committed by Chris Wanstrath
parent 2c2b277b29
commit cc604bea49

View File

@ -126,6 +126,10 @@ export class Parser {
if (expr.type.is('ParenExpr') && !this.isExprEnd()) if (expr.type.is('ParenExpr') && !this.isExprEnd())
expr = this.functionCall(expr) 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 // one | echo
if (allowPipe && this.isPipe()) if (allowPipe && this.isPipe())
return this.pipe(expr) return this.pipe(expr)
@ -535,10 +539,32 @@ export class Parser {
return nodes ? node.push(left, nodes!) : node.push(left, ...parts) 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) // dotget in a statement/expression (something.blah) or (something.blah arg1)
dotGetFunctionCall(): SyntaxNode { dotGetFunctionCall(): SyntaxNode {
const dotGet = this.dotGet() 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 // dotget not in scope, regular Word
if (dotGet.type.is('Word')) return dotGet if (dotGet.type.is('Word')) return dotGet