1 // =================================
  2 // Copyright (c) 2020 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 [hpp]#include <sngcm/cmparser/ParserApi.hpp>
  7 [hpp]#include <sngcm/ast/Statement.hpp>
  8 [hpp]#include <sngcm/cmparser/ParsingContext.hpp>
  9 [cpp]#include <sngcm/cmparser/Expression.hpp>
 10 [cpp]#include <sngcm/cmparser/TypeExpr.hpp>
 11 [cpp]#include <sngcm/cmparser/Identifier.hpp>
 12 [cpp]#include <sngcm/cmlexer/CmajorLexer.hpp>
 13 [cpp]#include <sngcm/cmlexer/CmajorTokens.hpp>
 14 
 15 using namespace sngcm::ast;
 16 using namespace CmajorTokens;
 17 
 18 parser api(SNGCM_PARSER_API) StatementParser
 19 {
 20     uselexer CmajorLexer;
 21 
 22     using ExpressionParser.Expression;
 23     using ExpressionParser.ArgumentList;
 24     using TypeExprParser.TypeExpr;
 25     using IdentifierParser.Identifier;
 26 
 27     Statement(ParsingContext* ctx) : StatementNode*
 28         ::= LabeledStatement(ctx):labeledStatement{ return labeledStatement; }
 29         |   ControlStatement(ctx):controlStatement{ return controlStatement; }
 30         |   ExpressionStatement(ctx):expressionStatement{ return expressionStatement; }
 31         |   AssignmentStatement(ctx):assignmentStatement{ return assignmentStatement; }
 32         |   ConstructionStatement(ctx):constructionStatement{ return constructionStatement; }
 33         |   DeleteStatement(ctx):deleteStatement{ return deleteStatement; }
 34         |   DestroyStatement(ctx):destroyStatement{ return destroyStatement; }
 35         |   EmptyStatement(ctx):emptyStatement{ return emptyStatement; }
 36         |   ThrowStatement(ctx):throwStatement{ return throwStatement; }
 37         |   TryStatement(ctx):tryStatement{ return tryStatement; }
 38         |   AssertStatement(ctx):assertStatement{ return assertStatement; }
 39         |   ConditionalCompilationStatement(ctx):condCompStatement{ return condCompStatement; }
 40         ;
 41 
 42     Label(var Span s, var std::u32string label) : LabelNode*
 43         ::= (ID{ s = span; label = lexer.GetMatch(span); } COLON{ s.end = span.end; }){ return new LabelNode(s, label); }
 44         ;
 45 
 46     LabeledStatement(ParsingContext* ctx, var std::unique_ptr stmt) : StatementNode*
 47         ::= Label:lbl Statement(ctx):s{ stmt.reset(new LabeledStatementNode(span, s)); stmt->SetLabelNode(lbl); return stmt.release(); }
 48         ;
 49 
 50     ControlStatement(ParsingContext* ctx) : StatementNode*
 51         ::= CompoundStatement(ctx):compoundStatement{ return compoundStatement; }
 52         |   ReturnStatement(ctx):returnStatement{ return returnStatement; }
 53         |   IfStatement(ctx):ifStatement{ return ifStatement; }
 54         |   WhileStatement(ctx):whileStatement{ return whileStatement; }
 55         |   DoStatement(ctx):doStatement{ return doStatement; }
 56         |   RangeForStatement(ctx):rangeForStatement{ return rangeForStatement; }
 57         |   ForStatement(ctx):forStatement{ return forStatement; }
 58         |   BreakStatement(ctx):breakStatement{ return breakStatement; }
 59         |   ContinueStatement(ctx):continueStatement{ return continueStatement; }
 60         |   GotoStatement(ctx):gotoStatement{ return gotoStatement; }
 61         |   SwitchStatement(ctx):switchStatement{ return switchStatement; }
 62         |   GotoCaseStatement(ctx):gotoCaseStatement{ return gotoCaseStatement; }
 63         |   GotoDefaultStatement(ctx):gotoDefaultStatement{ return gotoDefaultStatement; }
 64         ;
 65 
 66     CompoundStatement(ParsingContext* ctx, var std::unique_ptr compoundStatement) : CompoundStatementNode*
 67         ::= LBRACE{ compoundStatement.reset(new CompoundStatementNode(span)); compoundStatement->SetBeginBraceSpan(span); }
 68             (Statement(ctx):stmt{ compoundStatement->AddStatement(stmt); })* RBRACE!
 69         {
 70             compoundStatement->SetEndBraceSpan(span);
 71             compoundStatement->SetSpanEnd(span.end);
 72             return compoundStatement.release();
 73         }
 74         ;
 75 
 76     ReturnStatement(ParsingContext* ctx, var Span s) : StatementNode*
 77         ::= RETURN{ s = span; } Expression(ctx):expr? SEMICOLON!{ s.end = span.end; return new ReturnStatementNode(s, expr); }
 78         ;
 79 
 80     IfStatement(ParsingContext* ctx, var Span s, var Span leftParenSpan, var Span rightParenSpan, var Span elseSpan) : IfStatementNode*
 81         ::=
 82         (   IF{ s = span; } LPAREN{ leftParenSpan = span; } Expression(ctx):cond RPAREN{ rightParenSpan = span; } Statement(ctx):thenS{ s.end = span.end; }
 83             (ELSE{ elseSpan = span; } Statement(ctx):elseS{ s.end = span.end; })?
 84         )
 85         {
 86             IfStatementNode* value = new IfStatementNode(s, cond, thenS, elseS);
 87             value->SetLeftParenSpan(leftParenSpan);
 88             value->SetRightParenSpan(rightParenSpan);
 89             value->SetElseSpan(elseSpan);
 90             return value;
 91         }
 92         ;
 93 
 94     WhileStatement(ParsingContext* ctx, var Span s, var Span leftParenSpan, var Span rightParenSpan) : WhileStatementNode*
 95         ::= (WHILE{ s = span; } LPAREN!{ leftParenSpan = span; } Expression(ctx):cond! RPAREN!{ rightParenSpan = span; } Statement(ctx):stmt!{ s.end = span.end; })
 96         {
 97             WhileStatementNode* value = new WhileStatementNode(s, cond, stmt);
 98             value->SetLeftParenSpan(leftParenSpan);
 99             value->SetRightParenSpan(rightParenSpan);
100             return value;
101         }
102         ;
103 
104     DoStatement(ParsingContext* ctx, var Span s, var Span whileSpan, var Span leftParenSpan, var Span rightParenSpan) : DoStatementNode*
105         ::= (DO{ s = span; } Statement(ctx):stmt! WHILE!{ whileSpan = span; } LPAREN!{ leftParenSpan = span; } Expression(ctx):cond! RPAREN!{ rightParenSpan = span; } SEMICOLON!{ s.end = span.end; })
106         {
107             DoStatementNode* value = new DoStatementNode(s, stmt, cond);
108             value->SetWhileSpan(whileSpan);
109             value->SetLeftParenSpan(leftParenSpan);
110             value->SetRightParenSpan(rightParenSpan);
111             return value;
112         }
113         ;
114 
115     ForStatement(ParsingContext* ctx, var Span s, var Span leftParenSpan, var Span rightParenSpan) : ForStatementNode*
116         ::=
117         (
118             FOR{ s = span; } LPAREN{ leftParenSpan = span; } ForInitStatement(ctx):init! Expression(ctx):cond? SEMICOLON! ForLoopStatementExpr(ctx):loop! RPAREN!{ rightParenSpan = span; }
119             Statement(ctx):stmt!{ s.end = span.end; }
120         )
121         {
122             ForStatementNode* value = new ForStatementNode(s, init, cond, loop, stmt);
123             value->SetLeftParenSpan(leftParenSpan);
124             value->SetRightParenSpan(rightParenSpan);
125             return value;
126         }
127         ;
128 
129     ForInitStatement(ParsingContext* ctx) : StatementNode*
130         ::= AssignmentStatement(ctx):assignmentStatement{ return assignmentStatement; }
131         |   ConstructionStatement(ctx):constructionStatement{ return constructionStatement; }
132         |   EmptyStatement(ctx):emptyStatement{ return emptyStatement; }
133         ;
134 
135     ForLoopStatementExpr(ParsingContext* ctx) : StatementNode*
136         ::= AssignmentStatementExpr(ctx):assignmentStatementExpr{ return assignmentStatementExpr; }
137         |   Expression(ctx):expr{ return new ExpressionStatementNode(span, expr); }
138         |   empty{ return new EmptyStatementNode(span); }
139         ;
140 
141     RangeForStatement(ParsingContext* ctx, var Span s, var Span leftParenSpan, var Span rightParenSpan, var Span colonSpan) : RangeForStatementNode*
142         ::=
143         (
144             FOR{ s = span; } LPAREN{ leftParenSpan = span; } TypeExpr(ctx):type Identifier:id COLON{ colonSpan = span; } Expression(ctx):container! RPAREN!{ rightParenSpan = span; }
145             Statement(ctx):action{ s.end = span.end; }
146         )
147         {
148             RangeForStatementNode* value = new RangeForStatementNode(s, type, id, container, action);
149             value->SetLeftParenSpan(leftParenSpan);
150             value->SetRightParenSpan(rightParenSpan);
151             value->SetColonSpan(colonSpan);
152             return value;
153         }
154         ;
155 
156     BreakStatement(ParsingContext* ctx, var Span s) : StatementNode*
157         ::= BREAK{ s = span; } SEMICOLON!{ s.end = span.end; return new BreakStatementNode(s); }
158         ;
159 
160     ContinueStatement(ParsingContext* ctx, var Span s) : StatementNode*
161         ::= CONTINUE{ s = span; } SEMICOLON!{ s.end = span.end; return new ContinueStatementNode(s); }
162         ;
163 
164     GotoStatement(ParsingContext* ctx, var std::u32string label, var Span s) : StatementNode*
165         ::= GOTO{ s = span; } ID{ label = lexer.GetMatch(span); } SEMICOLON!{ s.end = span.end; return new GotoStatementNode(s, label); }
166         ;
167 
168     SwitchStatement(ParsingContext* ctx, var std::unique_ptr switchStatement,
169         var Span leftParenSpan, var Span rightParenSpan, var Span beginBraceSpan, var Span endBraceSpan) : SwitchStatementNode*
170         ::= (SWITCH LPAREN!{ leftParenSpan = span; } Expression(ctx):cond! RPAREN!)
171             {
172                 rightParenSpan = span;
173                 switchStatement.reset(new SwitchStatementNode(span, cond));
174                 switchStatement->SetLeftParenSpan(leftParenSpan);
175                 switchStatement->SetRightParenSpan(rightParenSpan);
176             }
177             LBRACE!{ beginBraceSpan = span; }
178             (   CaseStatement(ctx):caseStatement{ switchStatement->AddCase(caseStatement); }
179             |   DefaultStatement(ctx):defaultStatement{ switchStatement->SetDefault(defaultStatement); }
180             )*
181             RBRACE!{ endBraceSpan = span; switchStatement->SetBeginBraceSpan(beginBraceSpan); switchStatement->SetEndBraceSpan(endBraceSpan); return switchStatement.release(); }
182         ;
183 
184     CaseStatement(ParsingContext* ctx, var std::unique_ptr caseS, var Span s, var Span caseSpan) : CaseStatementNode*
185         ::= empty{ caseS.reset(new CaseStatementNode(span)); s = span; }
186             (((CASE{ caseSpan = span; } Expression(ctx):caseExpr{ caseS->AddCaseSpan(caseSpan); caseS->AddCaseExpr(caseExpr); } COLON!)+){ s.end = span.end; caseS->SetSpan(s); }
187             (Statement(ctx):stmt{ caseS->AddStatement(stmt); })*
188         )
189         {
190             return caseS.release();
191         }
192         ;
193 
194     DefaultStatement(ParsingContext* ctx, var std::unique_ptr defaultS, var Span s) : DefaultStatementNode*
195         ::= (DEFAULT{ s = span; } COLON!{ s.end = span.end; defaultS.reset(new DefaultStatementNode(s)); }
196             (Statement(ctx):stmt{ defaultS->AddStatement(stmt); })*
197         )
198         {
199             return defaultS.release();
200         }
201         ;
202 
203     GotoCaseStatement(ParsingContext* ctx, var Span s) : StatementNode*
204         ::= GOTO{ s = span; } CASE Expression(ctx):caseExpr SEMICOLON!{ s.end = span.end; return new GotoCaseStatementNode(s, caseExpr); }
205         ;
206 
207     GotoDefaultStatement(ParsingContext* ctx, var Span s) : StatementNode*
208         ::= GOTO{ s = span; } DEFAULT SEMICOLON!{ s.end = span.end; return new GotoDefaultStatementNode(s); }
209         ;
210 
211     AssignmentStatementExpr(ParsingContext* ctx, var Span s) : StatementNode*
212         ::= empty{ ctx->PushParsingLvalue(true); s = span; } Expression(ctx):target{ ctx->PopParsingLvalue(); } / { ctx->PopParsingLvalue(); } ASSIGN Expression(ctx):source
213         {
214             s.end = span.end; return new AssignmentStatementNode(s, target, source);
215         }
216         ;
217 
218     AssignmentStatement(ParsingContext* ctx, var std::unique_ptr statement) : StatementNode*
219         ::= AssignmentStatementExpr(ctx):stmt SEMICOLON{ statement.reset(stmt); statement->SetSpanEnd(span.end); return statement.release(); }
220         ;
221 
222     ConstructionStatement(ParsingContext* ctx, var std::unique_ptr constructionStatement) : ConstructionStatementNode*
223         ::= (TypeExpr(ctx):type Identifier:id!){ constructionStatement.reset(new ConstructionStatementNode(span, type, id)); }
224             (   ASSIGN Expression(ctx):value!{ constructionStatement->AddArgument(value); constructionStatement->SetAssignment(); }
225             |   LPAREN ArgumentList(ctx, constructionStatement.get()):argumentList RPAREN!
226             |   empty{ constructionStatement->SetEmpty(); }
227             )
228             SEMICOLON!{ constructionStatement->SetSpanEnd(span.end); return constructionStatement.release(); }
229         ;
230 
231     DeleteStatement(ParsingContext* ctx, var Span s) : StatementNode*
232         ::= DELETE{ s = span; } Expression(ctx):ptr! SEMICOLON!{ s.end = span.end; return new DeleteStatementNode(s, ptr); }
233         ;
234 
235     DestroyStatement(ParsingContext* ctx, var Span s) : StatementNode*
236         ::= DESTROY{ s = span; } Expression(ctx):ptr! SEMICOLON!{ s.end = span.end; return new DestroyStatementNode(s, ptr); }
237         ;
238 
239     ExpressionStatement(ParsingContext* ctx, var Span s) : StatementNode*
240         ::= empty{ ctx->PushParsingExpressionStatement(true); }
241             (Expression(ctx):expr{ s = span; } SEMICOLON{ s.end = span.end; }){ ctx->PopParsingExpressionStatement(); return new ExpressionStatementNode(s, expr); } / { ctx->PopParsingExpressionStatement(); }
242         ;
243 
244     EmptyStatement(ParsingContext* ctx) : StatementNode*
245         ::= SEMICOLON{ return new EmptyStatementNode(span); }
246         ;
247 
248     ThrowStatement(ParsingContext* ctx, var Span s) : StatementNode*
249         ::= THROW{ s = span; } Expression(ctx):exception? SEMICOLON!{ s.end = span.end; return new ThrowStatementNode(s, exception); }
250         ;
251 
252     TryStatement(ParsingContext* ctx, var std::unique_ptr tryStatement) : TryStatementNode*
253         ::=
254         (   (TRY CompoundStatement(ctx):tryBlock){ tryStatement.reset(new TryStatementNode(span, tryBlock)); }
255             (Catch(ctx):ctch{ tryStatement->AddCatch(ctch); })+
256         )
257         {
258             return tryStatement.release();
259         }
260         ;
261 
262     Catch(ParsingContext* ctx, var Span s, var Span leftParenSpan, var Span rightParenSpan) : CatchNode*
263         ::= CATCH{ s = span; } LPAREN!{ leftParenSpan = span; } TypeExpr(ctx):catchType! Identifier:catchId? RPAREN!{ rightParenSpan = span; }
264             CompoundStatement(ctx):catchBlock
265             {
266                 s.end = span.end;
267                 CatchNode* value = new CatchNode(s, catchType, catchId, catchBlock);
268                 value->SetLeftParenSpan(leftParenSpan);
269                 value->SetRightParenSpan(rightParenSpan);
270                 return value;
271             }
272         ;
273 
274     AssertStatement(ParsingContext* ctx, var Span s) : StatementNode*
275         ::= HASH{ s = span; } ASSERT Expression(ctx):expr! SEMICOLON!{ s.end = span.end; return new AssertStatementNode(s, expr); }
276         ;
277 
278     ConditionalCompilationStatement(ParsingContext* ctx, var std::unique_ptr condCompStmt,
279         var Span s, var Span keywordSpan, var Span leftParenSpan, var Span rightParenSpan) : ConditionalCompilationStatementNode*
280         ::= HASH{ s = span; keywordSpan = span; }
281             IF{ keywordSpan.end = span.end; } LPAREN!{ leftParenSpan = span; }
282             ConditionalCompilationExpression:ifExpr{ s.end = span.end; condCompStmt.reset(new ConditionalCompilationStatementNode(s, ifExpr)); condCompStmt->IfPart()->SetKeywordSpan(keywordSpan); }
283             RPAREN!{ rightParenSpan = span; condCompStmt->IfPart()->SetLeftParenSpan(leftParenSpan); condCompStmt->IfPart()->SetRightParenSpan(rightParenSpan); }
284             (Statement(ctx):ifS{ condCompStmt->AddIfStatement(ifS); })*
285             (
286                 HASH{ keywordSpan = span; } ELIF{ keywordSpan.end = span.end; }
287                 LPAREN!{ leftParenSpan = span; } ConditionalCompilationExpression:elifExpr{ condCompStmt->AddElifExpr(span, elifExpr); } RPAREN!
288                 {
289                     rightParenSpan = span;
290                     condCompStmt->SetElifLeftParenSpan(leftParenSpan);
291                     condCompStmt->SetElifRightParenSpan(rightParenSpan);
292                     condCompStmt->SetElifKeywordSpan(keywordSpan); 
293                 }
294                 (Statement(ctx):elifS{ condCompStmt->AddElifStatement(elifS); })*
295             )*
296             (
297                 HASH{ keywordSpan = span; } ELSE (Statement(ctx):elseS{ condCompStmt->AddElseStatement(span, elseS); })* empty{ condCompStmt->ElsePart()->SetKeywordSpan(keywordSpan); }
298             )?
299             HASH{ keywordSpan = span; } ENDIF!{ keywordSpan.end = span.end; condCompStmt->SetEndIfSpan(keywordSpan); return condCompStmt.release(); }
300         ;
301 
302     ConditionalCompilationExpression : ConditionalCompilationExpressionNode*
303         ::= ConditionalCompilationDisjunction:disjunction{ return disjunction; }
304         ;
305 
306     ConditionalCompilationDisjunction(var Span s, var std::unique_ptr condCompExpr) : ConditionalCompilationExpressionNode*
307         ::=
308         (
309             ConditionalCompilationConjunction:left{ s = span; condCompExpr.reset(left); }
310             (DISJUNCTION ConditionalCompilationConjunction:right{ s.end = span.end; condCompExpr.reset(new ConditionalCompilationDisjunctionNode(s, condCompExpr.release(), right)); })*
311         )
312         {
313             return condCompExpr.release(); 
314         }
315         ;
316 
317     ConditionalCompilationConjunction(var Span s, var std::unique_ptr condCompExpr) : ConditionalCompilationExpressionNode*
318         ::=
319         (
320             ConditionalCompilationPrefix:left{ s = span; condCompExpr.reset(left); }
321             (AMPAMP ConditionalCompilationPrefix:right{ s.end = span.end; condCompExpr.reset(new ConditionalCompilationConjunctionNode(s, condCompExpr.release(), right)); })*
322         )
323         {
324             return condCompExpr.release(); 
325         }
326         ;
327 
328     ConditionalCompilationPrefix(var Span s, var std::unique_ptr condCompExpr) : ConditionalCompilationExpressionNode*
329         ::=
330         (   EXCLAMATION{ s = span; } ConditionalCompilationPrefix:prefix{ s.end = span.end; condCompExpr.reset(new ConditionalCompilationNotNode(s, prefix)); } 
331         |   ConditionalCompilationPrimary:primary!{ condCompExpr.reset(primary); }
332         )
333         {
334             return condCompExpr.release(); 
335         }
336         ;
337 
338     ConditionalCompilationPrimary(var std::u32string symbol) : ConditionalCompilationExpressionNode*
339         ::= ID{ symbol = lexer.GetMatch(span); return new ConditionalCompilationPrimaryNode(span, symbol); }
340         |   LPAREN ConditionalCompilationExpression:expr RPAREN!{ return new ParenthesizedConditionalCompilationExpressionNode(span, expr); }
341         ;
342 
343     ruleinfo
344     {
345         (Statement, "statement"), (Label, "label"), (LabeledStatement, "labeled statement"), (ControlStatement, "control statement"), (CompoundStatement, "compound statement"),
346         (ReturnStatement, "return statement"), (IfStatement, "if statement"), (WhileStatement, "while statement"), (DoStatement, "do statement"),
347         (ForStatement, "for statement"), (ForInitStatement, "for initialization statement"), (ForLoopStatementExpr, "for loop expression"),
348         (RangeForStatement, "range for statement"), (BreakStatement, "break statement"), (ContinueStatement, "continue statement"), (GotoStatement, "goto statement"),
349         (SwitchStatement, "switch statement"), (CaseStatement, "case statement"), (DefaultStatement, "default statement"), (GotoCaseStatement, "goto case statement"),
350         (GotoDefaultStatement, "goto default statement"), (AssignmentStatementExpr, "assignment expression"), (AssignmentStatement, "assignment statement"),
351         (ConstructionStatement, "construction statement"), (DeleteStatement, "delete statement"), (DestroyStatement, "destroy statement"), (ExpressionStatement, "expression statement"),
352         (EmptyStatement, "empty statement"), (ThrowStatement, "throw statement"), (TryStatement, "try statement"), (Catch, "catch statement"), (AssertStatement, "assert statement"),
353         (ConditionalCompilationStatement, "conditional compilation statement"), (ConditionalCompilationExpression, "conditional compilation expression"),
354         (ConditionalCompilationDisjunction, "conditional compilation disjunction"), (ConditionalCompilationConjunction, "conditional compilation conjunction"),
355         (ConditionalCompilationPrefix, "conditional compilation prefix expression"), (ConditionalCompilationPrimary, "conditional compilation primary expression")
356     }
357 }