lezer-parser/lezer

Incorrect node nesting

unconed opened this issue · 1 comments

While writing a grammar for WGSL, I'm finding that lezer is producing incorrectly nested nodes on a valid parse. This is happening in the latest published versions:

  • @lezer/common 0.15.11
  • @lezer/generator 0.15.4
  • @lezer/lr 0.15.7

Given the following (reduced) grammar:

@top StructBodyDeclaration { '{' StructMember* '}' }
@skip { space }

StructMember { AttributeList MemberDeclaration ";" }
AttributeList { "@"* }
MemberDeclaration { Identifier ":" Identifier }

@tokens {
  space { std.whitespace+ }
  Identifier { $[a-zA-Z_] $[0-9a-zA-Z] $[0-9a-zA-Z_]* | $[a-zA-Z] $[0-9a-zA-Z_]* }
}

When I parse:

{ intensity: type; }
{ @ intensity: type; }

I get the following ASTs:

(StructBodyDeclaration (AttributeList) (StructMember (MemberDeclaration (Identifier) (Identifier))))
(StructBodyDeclaration (StructMember (AttributeList) (MemberDeclaration (Identifier) (Identifier))))

If empty, AttributeList appears outside the associated StructMember. Otherwise it correctly goes inside StructMember. This seems like a bug?

Thanks for finding that! Mutable state was being manipulated in the wrong order in the edge case of a reduction with no depth, causing an incorrect parse stack. Attached patch (released as @lezer/lr 0.15.8) should help.