1
2
3
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 }