@@ -61,6 +61,10 @@ impl Parser<'_> {
6161 SyntaxKind :: Dot => self . parse_anchor ( ) ,
6262 SyntaxKind :: Negation => self . parse_negated_field ( ) ,
6363 SyntaxKind :: UpperIdent | SyntaxKind :: LowerIdent => self . parse_node_or_field ( ) ,
64+ SyntaxKind :: KwError | SyntaxKind :: KwMissing => {
65+ // Bare ERROR/MISSING outside parens - treat as error
66+ self . error_and_bump ( "ERROR and MISSING must be inside parentheses: (ERROR) or (MISSING ...)" ) ;
67+ }
6468 _ => {
6569 self . error_and_bump ( "unexpected token; expected a pattern" ) ;
6670 }
@@ -71,28 +75,63 @@ impl Parser<'_> {
7175 self . exit_recursion ( ) ;
7276 }
7377
74- /// Named node: `(type child1 child2 ...)` or `(_ child1 ...)` for any node.
78+ /// Named node pattern: `(type ...)`, `(_ ...)`, `(ERROR)`, `(MISSING ...)`.
79+ /// Also handles supertype/subtype: `(expression/binary_expression)`.
7580 fn parse_named_node ( & mut self ) {
7681 self . start_node ( SyntaxKind :: NamedNode ) ;
7782 self . expect ( SyntaxKind :: ParenOpen ) ;
7883
79- if self . peek ( ) == SyntaxKind :: ParenClose {
80- self . error ( "empty node pattern - expected node type or children" ) ;
81- self . expect ( SyntaxKind :: ParenClose ) ;
82- self . finish_node ( ) ;
83- return ;
84- }
85-
86- // Optional type constraint: `(identifier ...)` or `(_ ...)` for wildcard
87- if matches ! (
88- self . peek( ) ,
89- SyntaxKind :: LowerIdent | SyntaxKind :: UpperIdent | SyntaxKind :: Underscore
90- ) {
91- self . bump ( ) ;
84+ match self . peek ( ) {
85+ SyntaxKind :: ParenClose => {
86+ self . error ( "empty node pattern - expected node type or children" ) ;
87+ }
88+ SyntaxKind :: Underscore => {
89+ self . bump ( ) ;
90+ }
91+ SyntaxKind :: LowerIdent | SyntaxKind :: UpperIdent => {
92+ self . bump ( ) ;
93+ // Optional subtype: `expression/binary_expression` or `expr/"()"`
94+ if self . peek ( ) == SyntaxKind :: Slash {
95+ self . bump ( ) ;
96+ match self . peek ( ) {
97+ SyntaxKind :: LowerIdent | SyntaxKind :: StringLit => {
98+ self . bump ( ) ;
99+ }
100+ _ => {
101+ self . error ( "expected subtype after '/' (e.g., expression/binary_expression)" ) ;
102+ }
103+ }
104+ }
105+ }
106+ SyntaxKind :: KwError => {
107+ self . bump ( ) ;
108+ if self . peek ( ) != SyntaxKind :: ParenClose {
109+ self . error ( "(ERROR) takes no arguments" ) ;
110+ self . parse_node_children ( SyntaxKind :: ParenClose , NAMED_NODE_RECOVERY ) ;
111+ }
112+ self . expect ( SyntaxKind :: ParenClose ) ;
113+ self . finish_node ( ) ;
114+ return ;
115+ }
116+ SyntaxKind :: KwMissing => {
117+ self . bump ( ) ;
118+ match self . peek ( ) {
119+ SyntaxKind :: LowerIdent | SyntaxKind :: StringLit => {
120+ self . bump ( ) ;
121+ }
122+ SyntaxKind :: ParenClose => { }
123+ _ => {
124+ self . parse_node_children ( SyntaxKind :: ParenClose , NAMED_NODE_RECOVERY ) ;
125+ }
126+ }
127+ self . expect ( SyntaxKind :: ParenClose ) ;
128+ self . finish_node ( ) ;
129+ return ;
130+ }
131+ _ => { }
92132 }
93133
94134 self . parse_node_children ( SyntaxKind :: ParenClose , NAMED_NODE_RECOVERY ) ;
95-
96135 self . expect ( SyntaxKind :: ParenClose ) ;
97136 self . finish_node ( ) ;
98137 }
@@ -104,11 +143,17 @@ impl Parser<'_> {
104143 until : SyntaxKind ,
105144 recovery : crate :: ql:: syntax_kind:: TokenSet ,
106145 ) {
107- while ! self . eof ( ) {
146+ loop {
108147 let kind = self . peek ( ) ;
109148 if kind == until {
110149 break ;
111150 }
151+ if self . eof ( ) {
152+ self . error (
153+ "unexpected end of input inside node; expected a child pattern or closing delimiter" ,
154+ ) ;
155+ break ;
156+ }
112157 if PATTERN_FIRST . contains ( kind) {
113158 self . parse_pattern ( ) ;
114159 } else if recovery. contains ( kind) {
@@ -218,7 +263,7 @@ impl Parser<'_> {
218263 if self . peek_nth ( 1 ) == SyntaxKind :: Colon {
219264 self . parse_field ( ) ;
220265 } else {
221- self . start_node ( SyntaxKind :: Pattern ) ;
266+ self . start_node ( SyntaxKind :: NamedNode ) ;
222267 self . bump ( ) ;
223268 self . finish_node ( ) ;
224269 }
@@ -249,4 +294,4 @@ impl Parser<'_> {
249294 self . finish_node ( ) ;
250295 }
251296 }
252- }
297+ }
0 commit comments