1 // =================================
  2 // Copyright (c) 2020 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 [hpp]#include <sngcpp/parser/ParserApi.hpp>
  7 [hpp]#include <sngcpp/ast/Expression.hpp>
  8 [hpp]#include <sngcpp/parser/ParsingContext.hpp>
  9 [cpp]#include <sngcpp/parser/Declarator.hpp>
 10 [cpp]#include <sngcpp/parser/Function.hpp>
 11 [cpp]#include <sngcpp/parser/Identifier.hpp>
 12 [cpp]#include <sngcpp/parser/Literal.hpp>
 13 [cpp]#include <sngcpp/parser/SimpleType.hpp>
 14 [cpp]#include <sngcpp/parser/Statement.hpp>
 15 [cpp]#include <sngcpp/parser/Template.hpp>
 16 [cpp]#include <sngcpp/parser/TypeExpr.hpp>
 17 [cpp]#include <sngcpp/lexer/CppLexer.hpp>
 18 [cpp]#include <sngcpp/lexer/CppTokens.hpp>
 19 
 20 using namespace CppTokens;
 21 using namespace soulng::lexer;
 22 
 23 parser api(SNGCPP_PARSER_API) ExpressionParser
 24 {
 25     uselexer CppLexer;
 26     main;
 27 
 28     using TypeExprParser.TypeExpr;
 29     using DeclaratorParser.InitializerList;
 30     using DeclaratorParser.InitializerClause;
 31     using DeclaratorParser.BracedInitializerList;
 32     using FunctionParser.ParameterList;
 33     using LiteralParser.Literal;
 34     using SimpleTypeParser.SimpleTypeSpecifier;
 35     using IdentifierParser.Identifier;
 36     using IdentifierParser.NestedNameSpecifier;
 37     using StatementParser.CompoundStatement;
 38     using TemplateParser.TemplateId;
 39 
 40     Expression(sngcpp::cppparser::ParsingContext* ctx, var std::unique_ptr expr, var Span s) : sngcpp::ast::Node*
 41         ::=
 42         (   AssignmentExpression(ctx):left{ expr.reset(left); s = span; }
 43             (COMMA AssignmentExpression(ctx):right{ s.end = span.end; expr.reset(new sngcpp::ast::CommaExpressionNode(s, expr.release(), right)); })*
 44         )
 45         {
 46             return expr.release();
 47         }
 48         ;
 49 
 50     ConstantExpression(sngcpp::cppparser::ParsingContext* ctx) : sngcpp::ast::Node*
 51         ::= ConditionalExpression(ctx):expr{ return expr; }
 52         ;
 53 
 54     AssignmentExpression(sngcpp::cppparser::ParsingContext* ctx, var std::unique_ptr expr, var Span s) : sngcpp::ast::Node*
 55         ::= empty{ ctx->BeginParsingLvalue(); }
 56         (   LogicalOrExpression(ctx):logicalOrExpression{ s = span; ctx->EndParsingLvalue(); expr.reset(logicalOrExpression); } / { ctx->EndParsingLvalue(); }
 57             AssignmentOperator:op
 58             InitializerClause(ctx):initializerClause{ s.end = span.end; expr.reset(new sngcpp::ast::AssignmentExpressionNode(s, expr.release(), op, initializerClause)); }
 59         |   ConditionalExpression(ctx):conditionalExpression{ expr.reset(conditionalExpression); }
 60         |   ThrowExpression(ctx):throwExpression{ expr.reset(throwExpression); }
 61         )
 62         {
 63             return expr.release();
 64         }
 65         ;
 66 
 67     AssignmentOperator : sngcpp::ast::Operator
 68         ::= ASSIGN{ return sngcpp::ast::Operator::assign; }
 69         |   MULASSIGN{ return sngcpp::ast::Operator::mulAssign; }
 70         |   DIVASSIGN{ return sngcpp::ast::Operator::divAssign; }
 71         |   REMASSIGN{ return sngcpp::ast::Operator::remAssign; }
 72         |   ADDASSIGN{ return sngcpp::ast::Operator::addAssign; }
 73         |   SUBASSIGN{ return sngcpp::ast::Operator::subAssign; }
 74         |   SHIFTRIGHTASSIGN{ return sngcpp::ast::Operator::shiftRightAssign; }
 75         |   SHIFTLEFTASSIGN{ return sngcpp::ast::Operator::shiftLeftAssign; }
 76         |   ANDASSIGN{ return sngcpp::ast::Operator::andAssign; }
 77         |   XORASSIGN{ return sngcpp::ast::Operator::xorAssign; }
 78         |   ORASSIGN{ return sngcpp::ast::Operator::orAssign; }
 79         ;
 80 
 81     ConditionalExpression(sngcpp::cppparser::ParsingContext* ctx, var std::unique_ptr expr, var Span s) : sngcpp::ast::Node*
 82         ::=
 83         (   LogicalOrExpression(ctx):logicalOrExpression{ expr.reset(logicalOrExpression); s = span; }
 84             (QUEST Expression(ctx):thenExpr COLON AssignmentExpression(ctx):elseExpr{ s.end = span.end; expr.reset(new sngcpp::ast::ConditionalExpressionNode(s, expr.release(), thenExpr, elseExpr)); })?
 85         )
 86         {
 87             return expr.release();
 88         }
 89         ;
 90 
 91     ThrowExpression(sngcpp::cppparser::ParsingContext* ctx, var Span s) : sngcpp::ast::Node*
 92         ::= (THROW{ s = span; } (AssignmentExpression(ctx):exception{ s.end = span.end; })?)
 93         {
 94             return new sngcpp::ast::ThrowExpressionNode(s, exception);
 95         }
 96         ;
 97 
 98     LogicalOrExpression(sngcpp::cppparser::ParsingContext* ctx, var std::unique_ptr expr, var Span s) : sngcpp::ast::Node*
 99         ::=
100         (   LogicalAndExpression(ctx):left{ expr.reset(left); s = span; }
101             (
102                 OROR LogicalAndExpression(ctx):right
103                 {
104                     if (ctx->ParsingTemplateIdOrLvalueAndNotArguments()) pass = false; else
105                     {
106                         s.end = span.end;
107                         expr.reset(new sngcpp::ast::LogicalOrExpressionNode(s, expr.release(), right));
108                     }
109                 }
110             )*
111         )
112         {
113             return expr.release();
114         }
115         ;
116 
117     LogicalAndExpression(sngcpp::cppparser::ParsingContext* ctx, var std::unique_ptr expr, var Span s) : sngcpp::ast::Node*
118         ::=
119         (   InclusiveOrExpression(ctx):left{ expr.reset(left); s = span; }
120             (
121                 AMPAMP InclusiveOrExpression(ctx):right
122                 {
123                     if (ctx->ParsingTemplateIdOrLvalueAndNotArguments()) pass = false; else
124                     {
125                         s.end = span.end;
126                         expr.reset(new sngcpp::ast::LogicalAndExpressionNode(s, expr.release(), right));
127                     }
128                 }
129             )*
130         )
131         {
132             return expr.release();
133         }
134         ;
135 
136     InclusiveOrExpression(sngcpp::cppparser::ParsingContext* ctx, var std::unique_ptr expr, var Span s) : sngcpp::ast::Node*
137         ::=
138         (   ExclusiveOrExpression(ctx):left{ expr.reset(left); s = span; }
139             (
140                 OR ExclusiveOrExpression(ctx):right
141                 {
142                     if (ctx->ParsingLvalueAndNotArguments()) pass = false; else
143                     {
144                         s.end = span.end;
145                         expr.reset(new sngcpp::ast::InclusiveOrExpressionNode(s, expr.release(), right));
146                     }
147                 }
148             )*
149         )
150         {
151             return expr.release();
152         }
153         ;
154 
155     ExclusiveOrExpression(sngcpp::cppparser::ParsingContext* ctx, var std::unique_ptr expr, var Span s) : sngcpp::ast::Node*
156         ::= 
157         (   AndExpression(ctx):left{ expr.reset(left); s = span; }
158             (
159                 XOR AndExpression(ctx):right
160                 {
161                     if (ctx->ParsingLvalueAndNotArguments()) pass = false; else
162                     {
163                         s.end = span.end;
164                         expr.reset(new sngcpp::ast::ExclusiveOrExpressionNode(s, expr.release(), right));
165                     }
166                 }
167             )*
168         )
169         {
170             return expr.release();
171         }
172         ;
173 
174     AndExpression(sngcpp::cppparser::ParsingContext* ctx, var std::unique_ptr expr, var Span s) : sngcpp::ast::Node*
175         ::= 
176         (   EqualityExpression(ctx):left{ expr.reset(left); s = span; }
177             (
178                 AMP EqualityExpression(ctx):right
179                 {
180                     if (ctx->ParsingLvalueAndNotArguments()) pass = false; else
181                     {
182                         s.end = span.end;
183                         expr.reset(new sngcpp::ast::AndExpressionNode(s, expr.release(), right));
184                     }
185                 }
186             )*
187         )
188         {
189             return expr.release();
190         }
191         ;
192 
193     EqualityExpression(sngcpp::cppparser::ParsingContext* ctx, var std::unique_ptr expr, var Span s) : sngcpp::ast::Node*
194         ::=
195         (   RelationalExpression(ctx):left{ expr.reset(left); s = span; }
196             (
197                 EqualityOperator:op RelationalExpression(ctx):right
198                 {
199                     if (ctx->ParsingLvalueAndNotArguments()) pass = false; else
200                     {
201                         s.end = span.end;
202                         expr.reset(new sngcpp::ast::EqualityExpressionNode(s, expr.release(), right, op));
203                     }
204                 }
205             )*
206         )
207         {
208             return expr.release();
209         }
210         ;
211 
212     EqualityOperator : sngcpp::ast::Operator
213         ::= EQ{ return sngcpp::ast::Operator::equal; }
214         |   NEQ{ return sngcpp::ast::Operator::notEqual; }
215         ;
216 
217     RelationalExpression(sngcpp::cppparser::ParsingContext* ctx, var std::unique_ptr expr, var Span s) : sngcpp::ast::Node*
218         ::= 
219         (   ShiftExpression(ctx):left{ expr.reset(left); s = span; }
220             (
221                 RelationalOperator:op ShiftExpression(ctx):right
222                 {
223                     if (ctx->ParsingTemplateIdOrLvalueAndNotArguments()) pass = false; else
224                     {
225                         s.end = span.end;
226                         expr.reset(new sngcpp::ast::RelationalExpressionNode(s, expr.release(), right, op));
227                     }
228                 }
229             )*
230         )
231         {
232             return expr.release();
233         }
234         ;
235 
236     RelationalOperator : sngcpp::ast::Operator
237         ::= LEQ{ return sngcpp::ast::Operator::lessOrEqual; }
238         |   GEQ{ return sngcpp::ast::Operator::greaterOrEqual; }
239         |   LANGLE{ return sngcpp::ast::Operator::less; }
240         |   RANGLE{ return sngcpp::ast::Operator::greater; }
241         ;
242 
243     ShiftExpression(sngcpp::cppparser::ParsingContext* ctx, var std::unique_ptr expr, var Span s) : sngcpp::ast::Node*
244         ::= 
245         (   AdditiveExpression(ctx):left{ expr.reset(left); s = span; }
246             (
247                 ShiftOperator:op AdditiveExpression(ctx):right
248                 {
249                     if (ctx->ParsingTemplateIdOrLvalueAndNotArguments()) pass = false; else
250                     {
251                         s.end = span.end;
252                         expr.reset(new sngcpp::ast::ShiftExpressionNode(s, expr.release(), right, op));
253                     }
254                 }
255             )*
256         )
257         {
258             return expr.release();
259         }
260         ;
261 
262     ShiftOperator : sngcpp::ast::Operator
263         ::= SHIFTLEFT{ return sngcpp::ast::Operator::shiftLeft; }
264         |   SHIFTRIGHT{ return sngcpp::ast::Operator::shiftRight; }
265         ;
266 
267     AdditiveExpression(sngcpp::cppparser::ParsingContext* ctx, var std::unique_ptr expr, var Span s) : sngcpp::ast::Node*
268         ::= 
269         (   MultiplicativeExpression(ctx):left{ expr.reset(left); s = span; }
270             (
271                 AdditiveOperator:op MultiplicativeExpression(ctx):right
272                 {
273                     if (ctx->ParsingLvalueAndNotArguments()) pass = false; else
274                     {
275                         s.end = span.end;
276                         expr.reset(new sngcpp::ast::AdditiveExpressionNode(s, expr.release(), right, op));
277                     }
278                 }
279             )*
280         )
281         {
282             return expr.release();
283         }
284         ;
285 
286     AdditiveOperator : sngcpp::ast::Operator
287         ::= PLUS{ return sngcpp::ast::Operator::add; }
288         |   MINUS{ return sngcpp::ast::Operator::sub; }
289         ;
290 
291     MultiplicativeExpression(sngcpp::cppparser::ParsingContext* ctx, var std::unique_ptr expr, var Span s) : sngcpp::ast::Node*
292         ::= 
293         (   PMExpression(ctx):left{ expr.reset(left); s = span; }
294             (
295                 MultiplicativeOperator:op PMExpression(ctx):right
296                 {
297                     if (ctx->ParsingLvalueAndNotArguments()) pass = false; else
298                     {
299                         s.end = span.end;
300                         expr.reset(new sngcpp::ast::MultiplicativeExpressionNode(s, expr.release(), right, op));
301                     }
302                 }
303             )*
304         )
305         {
306             return expr.release();
307         }
308         ;
309 
310     MultiplicativeOperator : sngcpp::ast::Operator
311         ::= STAR{ return sngcpp::ast::Operator::mul; }
312         |   DIV{ return sngcpp::ast::Operator::div; }
313         |   MOD{ return sngcpp::ast::Operator::rem; }
314         ;
315 
316     PMExpression(sngcpp::cppparser::ParsingContext* ctx, var std::unique_ptr expr, var Span s) : sngcpp::ast::Node*
317         ::=
318         (   CastExpression(ctx):left{ expr.reset(left); s = span; }
319             (
320                 PMOperator:op CastExpression(ctx):right
321                 {
322                     s.end = span.end;
323                     expr.reset(new sngcpp::ast::PMExpressionNode(s, expr.release(), right, op));
324                 }
325             )*
326         )
327         {
328             return expr.release();
329         }
330         ;
331 
332     PMOperator : sngcpp::ast::Operator
333         ::= DOTSTAR{ return sngcpp::ast::Operator::dotStar; }
334         |   ARROWSTAR{ return sngcpp::ast::Operator::arrowStar; }
335         ;
336 
337     CastExpression(sngcpp::cppparser::ParsingContext* ctx, var Span s) : sngcpp::ast::Node*
338         ::= LPAREN{ s = span; } TypeExpr(ctx):typeExpr RPAREN CastExpression(ctx):castExpr{ s.end = span.end; return new sngcpp::ast::CastExpressionNode(s, typeExpr, castExpr); }
339         |   UnaryExpression(ctx):unaryExpression{ return unaryExpression; }
340         ;
341 
342     UnaryExpression(sngcpp::cppparser::ParsingContext* ctx, var Span s) : sngcpp::ast::Node*
343         ::= PLUSPLUS{ s = span; } CastExpression(ctx):c1{ s.end = span.end; return new sngcpp::ast::UnaryExpressionNode(s, sngcpp::ast::Operator::inc, c1); }
344         |   MINUSMINUS{ s = span; } CastExpression(ctx):c2{ s.end = span.end; return new sngcpp::ast::UnaryExpressionNode(s, sngcpp::ast::Operator::dec, c2); }
345         |   UnaryOperator:op{ s = span; } CastExpression(ctx):c3{ s.end = span.end; return new sngcpp::ast::UnaryExpressionNode(s, op, c3); }
346         |   SIZEOF{ s = span; } UnaryExpression(ctx):u4{ s.end = span.end; return new sngcpp::ast::UnaryExpressionNode(s, sngcpp::ast::Operator::sizeOf, u4); }
347         |   ALIGNOF{ s = span; } LPAREN TypeExpr(ctx):t5 RPAREN{ s.end = span.end; return new sngcpp::ast::UnaryExpressionNode(s, sngcpp::ast::Operator::alignOf, t5); }
348         |   NewExpression(ctx):newExpr{ return newExpr; }
349         |   DeleteExpression(ctx):deleteExpr{ return deleteExpr; }
350         |   PostfixExpression(ctx):postfixExpr{ return postfixExpr; }
351         ;
352 
353     UnaryOperator : sngcpp::ast::Operator
354         ::= STAR{ return sngcpp::ast::Operator::deref; }
355         |   AMP{ return sngcpp::ast::Operator::addrOf; }
356         |   PLUS{ return sngcpp::ast::Operator::unaryPlus; }
357         |   MINUS{ return sngcpp::ast::Operator::unaryMinus; }
358         |   EXCLAMATION{ return sngcpp::ast::Operator::not_; }
359         |   TILDE{ return sngcpp::ast::Operator::complement; }
360         ;
361 
362     NewExpression(sngcpp::cppparser::ParsingContext* ctx, var Span s) : sngcpp::ast::Node*
363         ::= (NEW{ s = span; } NewPlacement(ctx):placement? TypeExpr(ctx):typeExpr{ s.end = span.end; } (NewInitializer(ctx):initializer{ s.end = span.end; })?)
364         {
365             return new sngcpp::ast::NewExpressionNode(s, placement, typeExpr, initializer);
366         }
367         ;
368 
369     NewPlacement(sngcpp::cppparser::ParsingContext* ctx) : sngcpp::ast::Node*
370         ::= LPAREN ExpressionList(ctx):exprList RPAREN{ return exprList; }
371         ;
372 
373     NewInitializer(sngcpp::cppparser::ParsingContext* ctx) : sngcpp::ast::Node*
374         ::= LPAREN ArgumentList(ctx):args RPAREN{ return args; }
375         ;
376 
377     ExpressionList(sngcpp::cppparser::ParsingContext* ctx) : sngcpp::ast::Node*
378         ::= InitializerList(ctx):initializerList{ return initializerList; }
379         ;
380 
381     ArgumentList(sngcpp::cppparser::ParsingContext* ctx) : sngcpp::ast::Node*
382         ::= ExpressionList(ctx):exprList{ return exprList; }
383         |   empty{ return nullptr; }
384         ;
385 
386     DeleteExpression(sngcpp::cppparser::ParsingContext* ctx, var bool array, var Span s) : sngcpp::ast::Node*
387         ::= DELETE{ s = span; } (LBRACKET RBRACKET{ array = true; })? CastExpression(ctx):castExpr{ s.end = span.end; return new sngcpp::ast::DeleteExpressionNode(s, array, castExpr); }
388         ;
389 
390     PostfixExpression(sngcpp::cppparser::ParsingContext* ctx, var std::unique_ptr expr, var Span s) : sngcpp::ast::Node*
391         ::=
392         (   PrimaryExpression(ctx):primaryExpr{ expr.reset(primaryExpr); s = span; }
393             (   LBRACKET{ ctx->BeginParsingArguments(); }
394                 (Expression(ctx):index
395                 RBRACKET){ s.end = span.end; ctx->EndParsingArguments(); expr.reset(new sngcpp::ast::SubscriptExpressionNode(s, expr.release(), index)); } / { ctx->EndParsingArguments(); }
396             |   LPAREN{ ctx->BeginParsingArguments(); }
397                 (ArgumentList(ctx):args
398                 RPAREN){ s.end = span.end; ctx->EndParsingArguments(); expr.reset(new sngcpp::ast::InvokeExpressionNode(s, expr.release(), args)); } / { ctx->EndParsingArguments(); }
399             |   DOT IdExpression(ctx):id1{ s.end = span.end; expr.reset(new sngcpp::ast::DotNode(s, expr.release(), id1)); }
400             |   ARROW IdExpression(ctx):id2{ s.end = span.end; expr.reset(new sngcpp::ast::ArrowNode(s, expr.release(), id2)); }
401             |   PLUSPLUS{ s.end = span.end; expr.reset(new sngcpp::ast::PostfixIncNode(s, expr.release())); }
402             |   MINUSMINUS{ s.end = span.end; expr.reset(new sngcpp::ast::PostfixDecNode(s, expr.release())); }
403             )*
404         )
405         {
406             return expr.release();
407         }
408         ;
409 
410     PrimaryExpression(sngcpp::cppparser::ParsingContext* ctx, var std::unique_ptr expr, var Span s) : sngcpp::ast::Node*
411         ::=
412         (   Literal:literal{ expr.reset(literal); }
413         |   THIS{ expr.reset(new sngcpp::ast::ThisNode(span)); }
414         |   LPAREN{ s = span; } Expression(ctx):e RPAREN{ s.end = span.end; expr.reset(new sngcpp::ast::ParenthesizedExprNode(s, e)); }
415         |   CppCastExpression(ctx):cppCastExpr{ expr.reset(cppCastExpr); }
416         |   TypeIdExpression(ctx):typeIdExpr{ expr.reset(typeIdExpr); }
417         |   SimpleTypeSpecifier:s1{ s = span; } LPAREN ArgumentList(ctx):args1 RPAREN
418             {
419                 s.end = span.end;
420                 expr.reset(new sngcpp::ast::InvokeExpressionNode(s, new sngcpp::ast::SimpleTypeNode(s, std::vector(1, s1)), args1));
421             }
422         |   SimpleTypeSpecifier:s2{ s = span; } BracedInitializerList(ctx):bracedInitializerList1
423             {
424                 s.end = span.end;
425                 expr.reset(new sngcpp::ast::InvokeExpressionNode(s, new sngcpp::ast::SimpleTypeNode(s, std::vector(1, s2)), bracedInitializerList1));
426             }
427         |   TypeExpr(ctx):t1{ s = span; } LPAREN ArgumentList(ctx):args2 RPAREN
428             {
429                 s.end = span.end;
430                 expr.reset(new sngcpp::ast::InvokeExpressionNode(s, t1, args2));
431             }
432         |   TypeExpr(ctx):t2{ s = span; } BracedInitializerList(ctx):bracedInitializerList2
433             {
434                 s.end = span.end;
435                 expr.reset(new sngcpp::ast::InvokeExpressionNode(s, t2, bracedInitializerList2));
436             }
437         |   IdExpression(ctx):idExpr{ expr.reset(idExpr); }
438         |   LambdaExpression(ctx):lambdaExpr{ return lambdaExpr; }
439         )
440         {
441             return expr.release();
442         }
443         ;
444 
445     CppCastExpression(sngcpp::cppparser::ParsingContext* ctx, var sngcpp::ast::Operator op, var Span s) : sngcpp::ast::Node*
446         ::=
447         (   (   DYNAMIC_CAST{ s = span; op = sngcpp::ast::Operator::dynamicCast; }
448             |   STATIC_CAST{ s = span; op = sngcpp::ast::Operator::staticCast; }
449             |   REINTERPRET_CAST{ s = span; op = sngcpp::ast::Operator::reinterpretCast; }
450             |   CONST_CAST{ s = span; op = sngcpp::ast::Operator::constCast; }
451             )
452             LANGLE TypeExpr(ctx):typeExpr RANGLE LPAREN ExpressionList(ctx):exprList RPAREN{ s.end = span.end; }
453         )
454         {
455             return new sngcpp::ast::CppCastExpressionNode(s, typeExpr, exprList, op);
456         }
457         ;
458 
459     TypeIdExpression(sngcpp::cppparser::ParsingContext* ctx, var Span s) : sngcpp::ast::Node*
460         ::= TYPEID{ s = span; } LPAREN TypeExpr(ctx):typeExpr RPAREN{ s.end = span.end; return new sngcpp::ast::TypeIdExpressionNode(s, typeExpr); }
461         |   TYPEID{ s = span; } LPAREN Expression(ctx):expr RPAREN{ s.end = span.end; return new sngcpp::ast::TypeIdExpressionNode(s, expr); }
462         ;
463 
464     IdExpression(sngcpp::cppparser::ParsingContext* ctx) : sngcpp::ast::Node*
465         ::= QualifiedId(ctx):qualifiedId{ return qualifiedId; }
466         |   UnqualifiedId(ctx):unqualifiedId{ return unqualifiedId; }
467         ;
468 
469     UnqualifiedId(sngcpp::cppparser::ParsingContext* ctx, var Span s) : sngcpp::ast::Node*
470         ::= TemplateId(ctx):templateId{ return templateId; }
471         |   Identifier:id1{ return new sngcpp::ast::IdentifierNode(span, id1); }
472         |   OperatorFunctionId:operatorFunctionId{ return operatorFunctionId; }
473         |   ConversionFunctionId(ctx):conversionFunctionId{ return conversionFunctionId; }
474         |   TILDE{ s = span; } Identifier:id2{ s.end = span.end; return new sngcpp::ast::DtorIdNode(s, id2); }
475         ;
476 
477     QualifiedId(sngcpp::cppparser::ParsingContext* ctx, var Span s) : sngcpp::ast::Node*
478         ::= COLONCOLON{ s = span; } TemplateId(ctx):templateId{ s.end = span.end; return new sngcpp::ast::NestedIdNode(s, nullptr, templateId); }
479         |   COLONCOLON{ s = span; } NestedNameSpecifier(ctx):ns1 UnqualifiedId(ctx):uid1{ s.end = span.end; return new sngcpp::ast::NestedIdNode(s, new sngcpp::ast::NestedIdNode(s, nullptr, ns1), uid1); }
480         |   COLONCOLON{ s = span; } Identifier:id1{ s.end = span.end; return new sngcpp::ast::NestedIdNode(s, nullptr, new sngcpp::ast::IdentifierNode(s, id1)); }
481         |   COLONCOLON{ s = span; } OperatorFunctionId:operatorFunctionId{ s.end = span.end; return new sngcpp::ast::NestedIdNode(s, nullptr, operatorFunctionId); }
482         |   NestedNameSpecifier(ctx):ns2{ s = span; } UnqualifiedId(ctx):uid2{ s.end = span.end; return new sngcpp::ast::NestedIdNode(s, ns2, uid2); }
483         ;
484 
485     OperatorFunctionId(var Span s) : sngcpp::ast::Node*
486         ::= OPERATOR{ s = span; } Operator:op{ s.end = span.end; return new sngcpp::ast::OperatorFunctionIdNode(s, op); }
487         ;
488 
489     Operator : sngcpp::ast::Operator
490         ::= NEW LBRACKET RBRACKET{ return sngcpp::ast::Operator::newArray; }
491         |   DELETE LBRACKET RBRACKET{ return sngcpp::ast::Operator::deleteArray; }
492         |   NEW{ return sngcpp::ast::Operator::new_; }
493         |   DELETE{ return sngcpp::ast::Operator::delete_; }
494         |   AssignmentOperator:assignmentOp{ return assignmentOp; }
495         |   PLUSPLUS{ return sngcpp::ast::Operator::inc; }
496         |   MINUSMINUS{ return sngcpp::ast::Operator::dec; }
497         |   SHIFTLEFT{ return sngcpp::ast::Operator::shiftLeft; }
498         |   SHIFTRIGHT{ return sngcpp::ast::Operator::shiftRight; }
499         |   AMPAMP{ return sngcpp::ast::Operator::logicalAnd; }
500         |   OROR{ return sngcpp::ast::Operator::logicalOr; }
501         |   EQ{ return sngcpp::ast::Operator::equal; }
502         |   NEQ{ return sngcpp::ast::Operator::notEqual; }
503         |   LEQ{ return sngcpp::ast::Operator::lessOrEqual; }
504         |   GEQ{ return sngcpp::ast::Operator::greaterOrEqual; }
505         |   LANGLE{ return sngcpp::ast::Operator::less; }
506         |   RANGLE{ return sngcpp::ast::Operator::greater; }
507         |   DOTSTAR{ return sngcpp::ast::Operator::dotStar; }
508         |   ARROWSTAR{ return sngcpp::ast::Operator::arrowStar; }
509         |   ARROW{ return sngcpp::ast::Operator::arrow; }
510         |   LPAREN RPAREN{ return sngcpp::ast::Operator::apply; }
511         |   LBRACKET RBRACKET{ return sngcpp::ast::Operator::subscript; }
512         |   PLUS{ return sngcpp::ast::Operator::add; }
513         |   MINUS{ return sngcpp::ast::Operator::sub; }
514         |   STAR{ return sngcpp::ast::Operator::mul; }
515         |   DIV{ return sngcpp::ast::Operator::div; }
516         |   MOD{ return sngcpp::ast::Operator::rem; }
517         |   XOR{ return sngcpp::ast::Operator::xor_; }
518         |   AMP{ return sngcpp::ast::Operator::and_; }
519         |   OR{ return sngcpp::ast::Operator::or_; }
520         |   TILDE{ return sngcpp::ast::Operator::complement; }
521         |   EXCLAMATION{ return sngcpp::ast::Operator::not_; }
522         |   COMMA{ return sngcpp::ast::Operator::comma; }
523         ;
524 
525     ConversionFunctionId(sngcpp::cppparser::ParsingContext* ctx, var Span s) : sngcpp::ast::Node*
526         ::= OPERATOR{ s = span; } TypeExpr(ctx):typeExpr{ s.end = span.end; return new sngcpp::ast::ConversionFunctionIdNode(s, typeExpr); }
527         ;
528 
529     LambdaExpression(sngcpp::cppparser::ParsingContext* ctx, var std::unique_ptr node) : sngcpp::ast::Node*
530         ::= LBRACKET{ node.reset(new sngcpp::ast::LambdaExpressionNode(span)); } LambdaCaptures(node.get()):captures RBRACKET! (ParameterList(ctx):params{ node->SetParameters(params); })?
531             CompoundStatement(ctx):body!{ node->SetBody(body); return node.release(); }
532         ;
533 
534     LambdaCaptures(sngcpp::ast::LambdaExpressionNode* lambdaExpression)
535         ::= (CaptureDefault:captureDefault{ lambdaExpression->AddCapture(captureDefault); })? Captures(lambdaExpression):captures?
536         ;
537 
538     CaptureDefault : sngcpp::ast::Node*
539         ::= ASSIGN{ return new sngcpp::ast::AssignCaptureNode(span); }
540         |   AMP{ return new sngcpp::ast::RefCaptureNode(span); }
541         ;
542 
543     Captures(sngcpp::ast::LambdaExpressionNode* lambdaExpression)
544         ::= Capture:left{ lambdaExpression->AddCapture(left); } (COMMA Capture:right{ lambdaExpression->AddCapture(right); })*
545         ;
546 
547     Capture : sngcpp::ast::Node*
548         ::= Identifier:id{ return new sngcpp::ast::IdentifierCaptureNode(span, new sngcpp::ast::IdentifierNode(span, id)); }
549         |   THIS{ return new sngcpp::ast::ThisCaptureNode(span); }
550         ;
551 }