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/Statement.hpp>
  8 [hpp]#include <sngcpp/parser/ParsingContext.hpp>
  9 [cpp]#include <sngcpp/parser/Declaration.hpp>
 10 [cpp]#include <sngcpp/parser/Declarator.hpp>
 11 [cpp]#include <sngcpp/parser/Expression.hpp>
 12 [cpp]#include <sngcpp/parser/Identifier.hpp>
 13 [cpp]#include <sngcpp/parser/TypeExpr.hpp>
 14 [cpp]#include <sngcpp/lexer/CppLexer.hpp>
 15 [cpp]#include <sngcpp/lexer/CppTokens.hpp>
 16 
 17 using namespace CppTokens;
 18 using namespace soulng::lexer;
 19 
 20 parser api(SNGCPP_PARSER_API) StatementParser
 21 {
 22     uselexer CppLexer;
 23 
 24     using ExpressionParser.ConstantExpression;
 25     using ExpressionParser.Expression;
 26     using DeclarationParser.BlockDeclaration;
 27     using DeclarationParser.SimpleDeclaration;
 28     using DeclaratorParser.BracedInitializerList;
 29     using DeclaratorParser.Declarator;
 30     using DeclaratorParser.InitializerClause;
 31     using IdentifierParser.Identifier;
 32     using TypeExprParser.TypeExpr;
 33 
 34     Statement(sngcpp::cppparser::ParsingContext* ctx) : sngcpp::ast::Node*
 35         ::= LabeledStatement(ctx):labeledStatement{ return labeledStatement; }
 36         |   ExpressionStatement(ctx):expressionStatement{ return expressionStatement; }
 37         |   CompoundStatement(ctx):compoundStatement{ return compoundStatement; }
 38         |   SelectionStatement(ctx):selectionStatement{ return selectionStatement; }
 39         |   IterationStatement(ctx):iterationStatement{ return iterationStatement; }
 40         |   JumpStatement(ctx):jumpStatement{ return jumpStatement; }
 41         |   DeclarationStatement(ctx):declarationStatement{ return declarationStatement; }
 42         |   TryStatement(ctx):tryStatement{ return tryStatement; }
 43         ;
 44 
 45     LabeledStatement(sngcpp::cppparser::ParsingContext* ctx, var Span s) : sngcpp::ast::Node*
 46         ::= Identifier:id{ s = span; } COLON Statement(ctx):ls{ s.end = span.end; return new sngcpp::ast::LabeledStatementNode(s, id, ls); }
 47         |   CASE{ s = span; } ConstantExpression(ctx):caseExpr! COLON! Statement(ctx):cs!{ s.end = span.end; return new sngcpp::ast::CaseStatementNode(s, caseExpr, cs); }
 48         |   DEFAULT{ s = span; } COLON! Statement(ctx):ds!{ s.end = span.end; return new sngcpp::ast::DefaultStatementNode(s, ds); }
 49         ;
 50 
 51     ExpressionStatement(sngcpp::cppparser::ParsingContext* ctx, var Span s) : sngcpp::ast::Node*
 52         ::= empty{ s = span; } Expression(ctx):expr? SEMICOLON{ s.end = span.end; return new sngcpp::ast::ExpressionStatementNode(s, expr); }
 53         ;
 54 
 55     CompoundStatement(sngcpp::cppparser::ParsingContext* ctx, var std::unique_ptr node) : sngcpp::ast::CompoundStatementNode*
 56         ::= LBRACE{ node.reset(new sngcpp::ast::CompoundStatementNode(span)); } (Statement(ctx):stmt{ node->AddStatement(span, stmt); })* RBRACE!{ node->SetEndBraceSpan(span); return node.release(); }
 57         ;
 58 
 59     SelectionStatement(sngcpp::cppparser::ParsingContext* ctx, var Span s, var Span elseSpan) : sngcpp::ast::Node*
 60         ::= (IF{ s = span; } LPAREN! Condition(ctx):cond1! RPAREN! Statement(ctx):thenS!{ s.end = span.end; } (ELSE{ elseSpan = span; } Statement(ctx):elseS!{ s.end = span.end; })?)
 61         {
 62             return new sngcpp::ast::IfStatementNode(s, cond1, thenS, elseS, elseSpan);
 63         }
 64         |   (SWITCH{ s = span; } LPAREN! Condition(ctx):cond2! RPAREN! Statement(ctx):stmt!{ s.end = span.end; })
 65         {
 66             return new sngcpp::ast::SwitchStatementNode(s, cond2, stmt);
 67         }
 68         ;
 69 
 70     IterationStatement(sngcpp::cppparser::ParsingContext* ctx, var Span s, var Span whileSpan) : sngcpp::ast::Node*
 71         ::= WHILE{ s = span; } LPAREN! Condition(ctx):cond1! RPAREN! Statement(ctx):stmt1!
 72         {
 73             s.end = span.end;
 74             return new sngcpp::ast::WhileStatementNode(s, cond1, stmt1);
 75         }
 76         |   DO{ s = span; } Statement(ctx):stmt2 WHILE!{ whileSpan = span; } LPAREN! Expression(ctx):cond2! RPAREN! SEMICOLON!
 77         {
 78             s.end = span.end;
 79             return new sngcpp::ast::DoStatementNode(s, stmt2, cond2, whileSpan);
 80         }
 81         |   FOR{ s = span; } LPAREN ForRangeDeclaration(ctx):forRange COLON ForRangeInitializer(ctx):forRangeInit! RPAREN! Statement(ctx):stmt3!
 82         {
 83             s.end = span.end;
 84             return new sngcpp::ast::RangeForStatementNode(s, forRange, forRangeInit, stmt3);
 85         }
 86         |   FOR{ s = span; } LPAREN ForInitStatement(ctx):forInit Condition(ctx):cond4? SEMICOLON Expression(ctx):loopExpr? RPAREN! Statement(ctx):stmt4!
 87         {
 88             s.end = span.end;
 89             return new sngcpp::ast::ForStatementNode(s, forInit, cond4, loopExpr, stmt4);
 90         }
 91         ;
 92 
 93     JumpStatement(sngcpp::cppparser::ParsingContext* ctx, var Span s) : sngcpp::ast::Node*
 94         ::= BREAK{ s = span; } SEMICOLON!{ s.end = span.end; return new sngcpp::ast::BreakStatementNode(s); }
 95         |   CONTINUE{ s = span; } SEMICOLON!{ s.end = span.end; return new sngcpp::ast::ContinueStatementNode(s); }
 96         |   RETURN{ s = span; } Expression(ctx):expr? SEMICOLON!{ s.end = span.end; return new sngcpp::ast::ReturnStatementNode(s, expr); }
 97         |   RETURN{ s = span; } BracedInitializerList(ctx):bi SEMICOLON!{ s.end = span.end; return new sngcpp::ast::ReturnStatementNode(s, bi); }
 98         |   GOTO{ s = span; } Identifier:target! SEMICOLON!{ s.end = span.end; return new sngcpp::ast::GotoStatementNode(s, target); }
 99         ;
100 
101     DeclarationStatement(sngcpp::cppparser::ParsingContext* ctx) : sngcpp::ast::Node*
102         ::= BlockDeclaration(ctx):declaration{ return new sngcpp::ast::DeclarationStatementNode(span, declaration); }
103         ;
104 
105     TryStatement(sngcpp::cppparser::ParsingContext* ctx, var std::unique_ptr node, var Span s) : sngcpp::ast::Node*
106         ::= TRY{ s = span; } CompoundStatement(ctx):tryBlock!{ s.end = span.end; node.reset(new sngcpp::ast::TryStatementNode(s, tryBlock)); } HandlerSequence(ctx, node.get()):handlerSequence!
107         {
108             return node.release();
109         }
110         ;
111 
112     HandlerSequence(sngcpp::cppparser::ParsingContext* ctx, sngcpp::ast::TryStatementNode* tryStatementNode)
113         ::= (Handler(ctx):handler{ tryStatementNode->AddHandler(span, handler); })+
114         ;
115 
116     Handler(sngcpp::cppparser::ParsingContext* ctx, var Span s) : sngcpp::ast::Node*
117         ::= CATCH{ s = span; } LPAREN! ExceptionDeclaration(ctx):exceptionDeclaration! RPAREN! CompoundStatement(ctx):catchBlock!
118         {
119             s.end = span.end;
120             return new sngcpp::ast::HandlerNode(s, exceptionDeclaration, catchBlock);
121         }
122         ;
123 
124     Condition(sngcpp::cppparser::ParsingContext* ctx, var Span s) : sngcpp::ast::Node*
125         ::= TypeExpr(ctx):typeExpr{ s = span; } Declarator(ctx):declarator
126         (   ASSIGN InitializerClause(ctx):ic
127             {
128                 s.end = span.end;
129                 return new sngcpp::ast::SimpleDeclarationNode(s, sngcpp::ast::Specifier::none, typeExpr, new sngcpp::ast::InitDeclaratorNode(s, declarator, new sngcpp::ast::AssignmentInitializerNode(s, ic)));
130             }
131         |   BracedInitializerList(ctx):bi
132             {
133                 s.end = span.end;
134                 return new sngcpp::ast::SimpleDeclarationNode(s, sngcpp::ast::Specifier::none, typeExpr, new sngcpp::ast::InitDeclaratorNode(s, declarator, bi));
135             }
136         )
137         |   Expression(ctx):expr{ return expr; }
138         ;
139 
140     ForRangeDeclaration(sngcpp::cppparser::ParsingContext* ctx, var Span s) : sngcpp::ast::Node*
141         ::= TypeExpr(ctx):typeExpr{ s = span; } Declarator(ctx):declarator{ s.end = span.end; return new sngcpp::ast::SimpleDeclarationNode(s, sngcpp::ast::Specifier::none, typeExpr, declarator); }
142         ;
143 
144     ForRangeInitializer(sngcpp::cppparser::ParsingContext* ctx) : sngcpp::ast::Node*
145         ::= Expression(ctx):expr{ return expr;}
146         |   BracedInitializerList(ctx):bi{ return bi; }
147         ;
148 
149     ForInitStatement(sngcpp::cppparser::ParsingContext* ctx) : sngcpp::ast::Node*
150         ::= ExpressionStatement(ctx):expressionStatement{ return expressionStatement; }
151         |   SimpleDeclaration(ctx):simpleDeclaration{ return simpleDeclaration; }
152         ;
153 
154     ExceptionDeclaration(sngcpp::cppparser::ParsingContext* ctx, var Span s) : sngcpp::ast::Node*
155         ::= (TypeExpr(ctx):typeExpr{ s = span; } (Declarator(ctx):declarator{ s.end = span.end; })?){ return new sngcpp::ast::SimpleDeclarationNode(s, sngcpp::ast::Specifier::none, typeExpr, declarator); }
156         |   ELLIPSES{ return new sngcpp::ast::CatchAllNode(span); }
157         ;
158 }