1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 [hpp]#include <sngcm/cmparser/ParserApi.hpp>
  7 [hpp]#include <sngcm/ast/Expression.hpp>
  8 [hpp]#include <sngcm/cmparser/ParsingContext.hpp>
  9 [cpp]#include <sngcm/cmparser/BasicType.hpp>
 10 [cpp]#include <sngcm/cmparser/Literal.hpp>
 11 [cpp]#include <sngcm/cmparser/Template.hpp>
 12 [cpp]#include <sngcm/cmparser/Operator.hpp>
 13 [cpp]#include <sngcm/cmparser/TypeExpr.hpp>
 14 [cpp]#include <sngcm/cmparser/Identifier.hpp>
 15 [cpp]#include <sngcm/cmlexer/CmajorLexer.hpp>
 16 [cpp]#include <sngcm/cmlexer/CmajorTokens.hpp>
 17 
 18 using namespace sngcm::ast;
 19 using namespace CmajorTokens;
 20 
 21 parser api(SNGCM_PARSER_API) ExpressionParser
 22 {
 23     uselexer CmajorLexer;
 24 
 25     using LiteralParser.Literal;
 26     using BasicTypeParser.BasicType;
 27     using TemplateParser.TemplateId;
 28     using TypeExprParser.TypeExpr;
 29     using IdentifierParser.Identifier;
 30 
 31     Expression(boost::uuids::uuid* moduleId, ParsingContext* ctx) : Node*
 32         ::= Equivalence(moduleId, ctx):equivalence{ return equivalence; }
 33         ;
 34 
 35     Equivalence(boost::uuids::uuid* moduleId, ParsingContext* ctx, var std::unique_ptr expr, var Span s) : Node*
 36         ::=
 37         (   Implication(moduleId, ctx):left{ s = span; expr.reset(left); }
 38             (   EQUIVALENCE{ if (!ctx->parsingConcept || ctx->parsingTemplateId) pass = false; }
 39                 Implication(moduleId, ctx):right!{ s.end = span.end; expr.reset(new EquivalenceNode(s, *moduleId, expr.release(), right)); }
 40             )*
 41         )
 42         {
 43             return expr.release();
 44         }
 45         ;
 46 
 47     Implication(boost::uuids::uuid* moduleId, ParsingContext* ctx, var std::unique_ptr expr, var Span s) : Node*
 48         ::=
 49         (   Disjunction(moduleId, ctx):left{ s = span; expr.reset(left); }
 50             (   IMPLICATION{ if (!ctx->parsingConcept || ctx->parsingTemplateId) pass = false; }
 51                 Implication(moduleId, ctx):right!{ s.end = span.end; expr.reset(new ImplicationNode(s, *moduleId, expr.release(), right)); }
 52             )?
 53         )
 54         {
 55             return expr.release();
 56         }
 57         ;
 58 
 59     Disjunction(boost::uuids::uuid* moduleId, ParsingContext* ctx, var std::unique_ptr expr, var Span s) : Node*
 60         ::=
 61         (   Conjunction(moduleId, ctx):left{ s = span; expr.reset(left); }
 62             (   DISJUNCTION{ if (ctx->parsingLvalue || ctx->parsingExpressionStatement && !ctx->parsingArguments) pass = false; }
 63                 Conjunction(moduleId, ctx):right!{ s.end = span.end; expr.reset(new DisjunctionNode(s, *moduleId, expr.release(), right)); }
 64             )*
 65         )
 66         {
 67             return expr.release();
 68         }
 69         ;
 70 
 71     Conjunction(boost::uuids::uuid* moduleId, ParsingContext* ctx, var std::unique_ptr expr, var Span s) : Node*
 72         ::=
 73         (   BitOr(moduleId, ctx):left{ s = span; expr.reset(left); }
 74             (   AMPAMP{ if (ctx->parsingLvalue || ctx->parsingExpressionStatement && !ctx->parsingArguments) pass = false; }
 75                 BitOr(moduleId, ctx):right!{ s.end = span.end; expr.reset(new ConjunctionNode(s, *moduleId, expr.release(), right)); }
 76             )*
 77         )
 78         {
 79             return expr.release();
 80         }
 81         ;
 82 
 83     BitOr(boost::uuids::uuid* moduleId, ParsingContext* ctx, var std::unique_ptr expr, var Span s) : Node*
 84         ::=
 85         (   BitXor(moduleId, ctx):left{ s = span; expr.reset(left); }
 86             (   BITOR{ if (ctx->parsingLvalue || ctx->parsingExpressionStatement && !ctx->parsingArguments) pass = false; }
 87                 BitXor(moduleId, ctx):right!{ s.end = span.end; expr.reset(new BitOrNode(s, *moduleId, expr.release(), right)); }
 88             )*
 89         )
 90         {
 91             return expr.release();
 92         }
 93         ;
 94 
 95     BitXor(boost::uuids::uuid* moduleId, ParsingContext* ctx, var std::unique_ptr expr, var Span s) : Node*
 96         ::=
 97         (   BitAnd(moduleId, ctx):left{ s = span; expr.reset(left); }
 98             (   BITXOR{ if (ctx->parsingLvalue || ctx->parsingExpressionStatement && !ctx->parsingArguments) pass = false; }
 99                 BitAnd(moduleId, ctx):right!{ s.end = span.end; expr.reset(new BitXorNode(s, *moduleId, expr.release(), right)); }
100             )*
101         )
102         {
103             return expr.release();
104         }
105         ;
106 
107     BitAnd(boost::uuids::uuid* moduleId, ParsingContext* ctx, var std::unique_ptr expr, var Span s) : Node*
108         ::=
109         (   Equality(moduleId, ctx):left{ s = span; expr.reset(left); }
110             (   AMP{ if (ctx->parsingLvalue || ctx->parsingExpressionStatement && !ctx->parsingArguments) pass = false; }
111                 Equality(moduleId, ctx):right!{ s.end = span.end; expr.reset(new BitAndNode(s, *moduleId, expr.release(), right)); }
112             )*
113         )
114         {
115             return expr.release();
116         }
117         ;
118 
119     Equality(boost::uuids::uuid* moduleId, ParsingContext* ctx, var std::unique_ptr expr, var Span s, var Operator op) : Node*
120         ::=
121         (   Relational(moduleId, ctx):left{ s = span; expr.reset(left); }
122             (
123                 (   EQ{ if (ctx->parsingLvalue || ctx->parsingExpressionStatement && !ctx->parsingArguments) pass = false; else op = Operator::eq; }
124                 |   NEQ{ if (ctx->parsingLvalue || ctx->parsingExpressionStatement && !ctx->parsingArguments) pass = false; else op = Operator::neq; }
125                 )
126                 Relational(moduleId, ctx):right!
127                 {
128                     switch (op)
129                     {
130                         case Operator::eq: s.end = span.end; expr.reset(new EqualNode(s, *moduleId, expr.release(), right)); break;
131                         case Operator::neq: s.end = span.end; expr.reset(new NotEqualNode(s, *moduleId, expr.release(), right)); break; 
132                     }
133                 }
134             )*
135         )
136         {
137             return expr.release();
138         }
139         ;
140 
141     Relational(boost::uuids::uuid* moduleId, ParsingContext* ctx, var std::unique_ptr expr, var Span s, var Operator op) : Node*
142         ::=
143         (   Shift(moduleId, ctx):left{ s = span; expr.reset(left); }
144             (
145                 (   LEQ{ if (ctx->parsingLvalue || ctx->parsingExpressionStatement && !ctx->parsingArguments) pass = false; else { op = Operator::lessOrEq; ctx->PushParsingIsOrAs(false); } }
146                 |   GEQ{ if (ctx->parsingLvalue || ctx->parsingExpressionStatement && !ctx->parsingArguments) pass = false; else { op = Operator::greaterOrEq; ctx->PushParsingIsOrAs(false); } }
147                 |   LANGLE{ if (ctx->parsingLvalue || ctx->parsingExpressionStatement && !ctx->parsingArguments) pass = false; else { op = Operator::less; ctx->PushParsingIsOrAs(false); } }
148                 |   RANGLE{ if (ctx->parsingLvalue || ctx->parsingExpressionStatement && !ctx->parsingArguments) pass = false; else { op = Operator::greater; ctx->PushParsingIsOrAs(false); } }
149                 |   IS{ if (ctx->parsingLvalue || ctx->parsingExpressionStatement && !ctx->parsingArguments) pass = false; else { op = Operator::is; ctx->PushParsingIsOrAs(true); } }
150                     TypeExpr(moduleId, ctx):isType
151                 |   AS{ if (ctx->parsingLvalue || ctx->parsingExpressionStatement && !ctx->parsingArguments) pass = false; else { op = Operator::as; ctx->PushParsingIsOrAs(true); } }
152                     TypeExpr(moduleId, ctx):asType
153                 )
154                 (Shift(moduleId, ctx):right | empty{ if (!ctx->parsingIsOrAs) pass = false; })
155                 {
156                     ctx->PopParsingIsOrAs();
157                     switch (op)
158                     {
159                         case Operator::lessOrEq: s.end = span.end; expr.reset(new LessOrEqualNode(s, *moduleId, expr.release(), right)); break;
160                         case Operator::greaterOrEq: s.end = span.end; expr.reset(new GreaterOrEqualNode(s, *moduleId, expr.release(), right)); break;
161                         case Operator::less: s.end = span.end; expr.reset(new LessNode(s, *moduleId, expr.release(), right)); break;
162                         case Operator::greater: s.end = span.end; expr.reset(new GreaterNode(s, *moduleId, expr.release(), right)); break;
163                         case Operator::is: s.end = span.end; expr.reset(new IsNode(s, *moduleId, expr.release(), isType)); break;
164                         case Operator::as: s.end = span.end; expr.reset(new AsNode(s, *moduleId, expr.release(), asType)); break;
165                     }
166                 }
167             )*
168         )
169         {
170             return expr.release();
171         }
172         ;
173 
174     Shift(boost::uuids::uuid* moduleId, ParsingContext* ctx, var std::unique_ptr expr, var Span s, var Operator op) : Node*
175         ::=
176         (   Additive(moduleId, ctx):left{ s = span; expr.reset(left); }
177             (
178                 (   SHIFTLEFT{ if (ctx->parsingLvalue) pass = false; else op = Operator::shiftLeft; }
179                 |   SHIFTRIGHT{ if (ctx->parsingLvalue) pass = false; else op = Operator::shiftRight; }
180                 )
181                 empty{ ctx->BeginParsingArguments(); } Additive(moduleId, ctx):right!
182                 {
183                     switch (op)
184                     {
185                         case Operator::shiftLeft: s.end = span.end; expr.reset(new ShiftLeftNode(s, *moduleId, expr.release(), right)); break;
186                         case Operator::shiftRight: s.end = span.end; expr.reset(new ShiftRightNode(s, *moduleId, expr.release(), right)); break;
187                     }
188                     ctx->EndParsingArguments();
189                 }
190                 /
191                 {
192                     ctx->EndParsingArguments();
193                 }
194             )*
195         )
196         {
197             return expr.release();
198         }
199         ;
200 
201     Additive(boost::uuids::uuid* moduleId, ParsingContext* ctx, var std::unique_ptr expr, var Span s, var Operator op) : Node*
202         ::=
203         (   Multiplicative(moduleId, ctx):left{ s = span; expr.reset(left); }
204             (
205                 (   PLUS{ if (ctx->parsingLvalue || ctx->parsingExpressionStatement && !ctx->parsingArguments) pass = false; else op = Operator::plus; }
206                 |   MINUS{ if (ctx->parsingLvalue || ctx->parsingExpressionStatement && !ctx->parsingArguments) pass = false; else op = Operator::minus; }
207                 )
208                 Multiplicative(moduleId, ctx):right!
209                 {
210                     switch (op)
211                     {
212                         case Operator::plus: s.end = span.end; expr.reset(new AddNode(s, *moduleId, expr.release(), right)); break;
213                         case Operator::minus: s.end = span.end; expr.reset(new SubNode(s, *moduleId, expr.release(), right)); break;
214                     }
215                 }
216             )*
217         )
218         {
219             return expr.release();
220         }
221         ;
222 
223     Multiplicative(boost::uuids::uuid* moduleId, ParsingContext* ctx, var std::unique_ptr expr, var Span s, var Operator op) : Node*
224         ::=
225         (   Prefix(moduleId, ctx):left{ s = span; expr.reset(left); }
226             (
227                 (   STAR{ if (ctx->parsingLvalue || ctx->parsingExpressionStatement && !ctx->parsingArguments) pass = false; else op = Operator::mul; }
228                 |   DIV{ if (ctx->parsingLvalue || ctx->parsingExpressionStatement && !ctx->parsingArguments) pass = false; else op = Operator::div; }
229                 |   REM{ if (ctx->parsingLvalue || ctx->parsingExpressionStatement && !ctx->parsingArguments) pass = false; else op = Operator::rem; }
230                 )
231                 Prefix(moduleId, ctx):right!
232                 {
233                     switch (op)
234                     {
235                         case Operator::mul: s.end = span.end; expr.reset(new MulNode(s, *moduleId, expr.release(), right)); break;
236                         case Operator::div: s.end = span.end;  expr.reset(new DivNode(s, *moduleId, expr.release(), right)); break;
237                         case Operator::rem: s.end = span.end; expr.reset(new RemNode(s, *moduleId, expr.release(), right)); break;
238                     }
239                 }
240             )*
241         )
242         {
243             return expr.release();
244         }
245         ;
246 
247     Prefix(boost::uuids::uuid* moduleId, ParsingContext* ctx, var std::unique_ptr prefix, var Span s, var Operator op) : Node*
248         ::=
249         (   (   PLUSPLUS{ s = span; op = Operator::plusplus; }
250             |   MINUSMINUS{ s = span; op = Operator::minusminus; }
251             |   PLUS{ if (ctx->parsingExpressionStatement && !ctx->parsingArguments) pass = false; else { s = span; op = Operator::plus; } }
252             |   MINUS{ if (ctx->parsingExpressionStatement && !ctx->parsingArguments) pass = false; else { s = span; op = Operator::minus; } }
253             |   EXCLAMATION{ if (ctx->parsingExpressionStatement && !ctx->parsingArguments) pass = false; else { s = span; op = Operator::not_; } }
254             |   CPL{ if (ctx->parsingExpressionStatement && !ctx->parsingArguments) pass = false; else { s = span; op = Operator::complement; } }
255             |   STAR{ if (ctx->parsingExpressionStatement && !ctx->parsingArguments) pass = false; else { s = span; op = Operator::deref; } }
256             |   AMP{ if (ctx->parsingExpressionStatement && !ctx->parsingArguments) pass = false; else { s = span; op = Operator::addrOf; } }
257             )
258             Prefix(moduleId, ctx):p
259             {
260                 prefix.reset(p);
261                 s.end = span.end;
262                 switch (op)
263                 {
264                     case Operator::plusplus: return new PrefixIncrementNode(s, *moduleId, prefix.release());
265                     case Operator::minusminus: return new PrefixDecrementNode(s, *moduleId, prefix.release());
266                     case Operator::plus: return new UnaryPlusNode(s, *moduleId, prefix.release());
267                     case Operator::minus: return new UnaryMinusNode(s, *moduleId, prefix.release());
268                     case Operator::not_: return new NotNode(s, *moduleId, prefix.release());
269                     case Operator::complement: return new ComplementNode(s, *moduleId, prefix.release());
270                     case Operator::deref: return new DerefNode(s, *moduleId, prefix.release());
271                     case Operator::addrOf: return new AddrOfNode(s, *moduleId, prefix.release());
272                 }
273             }
274         |   Postfix(moduleId, ctx):postfix{ return postfix; }
275         )
276         ;
277 
278     Postfix(boost::uuids::uuid* moduleId, ParsingContext* ctx, var std::unique_ptr expr, var Span s) : Node*
279         ::=
280         (   Primary(moduleId, ctx):primary{ s = span; expr.reset(primary); }
281             (   PLUSPLUS{ s.end = span.end; expr.reset(new PostfixIncrementNode(s, *moduleId, expr.release())); }
282             |   MINUSMINUS{ s.end = span.end; expr.reset(new PostfixDecrementNode(s, *moduleId, expr.release())); }
283             |   DOT Identifier(moduleId):dotMember{ s.end = span.end; expr.reset(new DotNode(s, *moduleId, expr.release(), dotMember)); }
284             |   ARROW Identifier(moduleId):arrowMember{ s.end = span.end; expr.reset(new ArrowNode(s, *moduleId, expr.release(), arrowMember)); }
285             |   LBRACKET{ ctx->PushParsingLvalue(false); ctx->PushParsingExpressionStatement(false); }
286                 Expression(moduleId, ctx):index{ ctx->PopParsingExpressionStatement(); ctx->PopParsingLvalue(); }
287                 RBRACKET!{ s.end = span.end; expr.reset(new IndexingNode(s, *moduleId, expr.release(), index)); }
288             |   LPAREN{ expr.reset(new InvokeNode(s, *moduleId, expr.release())); } ArgumentList(moduleId, ctx, expr.get()):args RPAREN!{ expr->SetSpanEnd(span.end); }
289             )*
290         )
291         {
292             return expr.release();
293         }
294         ;
295 
296     Primary(boost::uuids::uuid* moduleId, ParsingContext* ctx, var Span s) : Node*
297         ::= (LPAREN{ s = span; } Expression(moduleId, ctx):expr RPAREN{ s.end = span.end; }){ return new ParenthesizedExpressionNode(s, *moduleId, expr); }
298         |   Literal(moduleId, ctx):literal{ return literal; }
299         |   BasicType(moduleId):basicType{ return basicType; }
300         |   TemplateId(moduleId, ctx):templateId{ return templateId; }
301         |   Identifier(moduleId):id{ return id; }
302         |   THIS{ return new ThisNode(span, *moduleId); }
303         |   BASE{ return new BaseNode(span, *moduleId); }
304         |   SizeOfExpr(moduleId, ctx):sizeOf{ return sizeOf; }
305         |   TypeNameExpr(moduleId, ctx):typeName{ return typeName; }
306         |   TypeIdExpr(moduleId, ctx):typeId{ return typeId; }
307         |   CastExpr(moduleId, ctx):cast{ return cast; }
308         |   ConstructExpr(moduleId, ctx):construct{ return construct; }
309         |   NewExpr(moduleId, ctx):newExpr{ return newExpr; }
310         ;
311 
312     SizeOfExpr(boost::uuids::uuid* moduleId, ParsingContext* ctx, var Span s) : Node*
313         ::= (SIZEOF{ s = span; } LPAREN! Expression(moduleId, ctx):expr! RPAREN!){ s.end = span.end; return new SizeOfNode(s, *moduleId, expr); }
314         ;
315 
316     TypeNameExpr(boost::uuids::uuid* moduleId, ParsingContext* ctx, var Span s) : Node*
317         ::= (TYPENAME{ s = span; } LPAREN! Expression(moduleId, ctx):expr! RPAREN!){ s.end = span.end; return new TypeNameNode(s, *moduleId, expr); }
318         ;
319 
320     TypeIdExpr(boost::uuids::uuid* moduleId, ParsingContext* ctx, var Span s) : Node*
321         ::= (TYPEID{ s = span; } LPAREN! Expression(moduleId, ctx):expr! RPAREN!){ s.end = span.end; return new TypeIdNode(s, *moduleId, expr); }
322         ;
323 
324     CastExpr(boost::uuids::uuid* moduleId, ParsingContext* ctx, var Span s) : Node*
325         ::= (CAST{ s = span; } LANGLE! TypeExpr(moduleId, ctx):typeExpr! RANGLE! LPAREN! Expression(moduleId, ctx):expr! RPAREN!){ s.end = span.end; return new CastNode(s, *moduleId, typeExpr, expr); }
326         ;
327 
328     ConstructExpr(boost::uuids::uuid* moduleId, ParsingContext* ctx, var std::unique_ptr expr, var Span s) : Node*
329         ::= (CONSTRUCT{ s = span; } LANGLE! TypeExpr(moduleId, ctx):typeExpr! RANGLE!){ expr.reset(new ConstructNode(s, *moduleId, typeExpr)); } LPAREN! ExpressionList(moduleId, ctx, expr.get()):exprList! RPAREN!
330         {
331             expr->SetSpanEnd(span.end);
332             return expr.release();
333         }
334         ;
335 
336     NewExpr(boost::uuids::uuid* moduleId, ParsingContext* ctx, var std::unique_ptr expr, var Span s) : Node*
337         ::= (NEW{ s = span; } TypeExpr(moduleId, ctx):typeExpr!{ s.end = span.end; expr.reset(new NewNode(s, *moduleId, typeExpr)); } (LPAREN ArgumentList(moduleId, ctx, expr.get()):argList RPAREN{ expr->SetSpanEnd(span.end); })?)
338         {
339             return expr.release();
340         }
341         ;
342 
343     ArgumentList(boost::uuids::uuid* moduleId, ParsingContext* ctx, sngcm::ast::Node* node)
344         ::= (ExpressionList(moduleId, ctx, node):exprList?)
345         ;
346 
347     ExpressionList(boost::uuids::uuid* moduleId, ParsingContext* ctx, sngcm::ast::Node* node)
348         ::= empty{ ctx->BeginParsingArguments(); }
349         (   (Expression(moduleId, ctx):arg{ node->AddArgument(arg); }) % COMMA){ ctx->EndParsingArguments(); } / { ctx->EndParsingArguments(); }
350         ;
351 
352     InvokeExpr(boost::uuids::uuid* moduleId, ParsingContext* ctx, var std::unique_ptr expr, var Span s) : Node*
353         ::= ((TemplateId(moduleId, ctx):templateId{ s = span; expr.reset(templateId); } | Identifier(moduleId):id{ s = span; expr.reset(id); })
354         (   DOT Identifier(moduleId):dotMemberId!{ s.end = span.end; expr.reset(new DotNode(s, *moduleId, expr.release(), dotMemberId)); }   )*
355         LPAREN{ expr.reset(new InvokeNode(s, *moduleId, expr.release())); } ArgumentList(moduleId, ctx, expr.get()):argList RPAREN!{ expr->SetSpanEnd(span.end); })
356         { 
357             return expr.release();
358         }
359         ;
360 
361     ruleinfo
362     {
363         (Expression, "expression"), (Equivalence, "equivalence expression"), (Implication, "implication expression"), (Disjunction, "disjunctive expression"),
364         (Conjunction, "conjunctive expression"), (BitOr, "bitwise or expression "),
365         (BitXor, "bitwise exclusive or expression"), (BitAnd, "bitwise and expression"), (Equality, "equality expression"), (Relational, "relational expression"),
366         (Shift, "shift expression"), (Additive, "additive expression"), (Multiplicative, "multiplicative expression"),
367         (Prefix, "prefix expression"), (Postfix, "postfix expression"), (Primary, "primary expression"), (SizeOfExpr, "sizeof expression"), (TypeNameExpr, "typename expression"),
368         (TypeIdExpr, "typeid expression"), (CastExpr, "cast expression"), (ConstructExpr, "construct expression"), (NewExpr, "new expression"),
369         (ArgumentList, "argument list"), (ExpressionList, "expression list"), (InvokeExpr, "invoke expression")
370     }
371 }