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/Enumeration.hpp>
 8 [hpp]#include <sngcm/cmparser/ParsingContext.hpp>
 9 [cpp]#include <sngcm/cmparser/Specifier.hpp>
10 [cpp]#include <sngcm/cmparser/Identifier.hpp>
11 [cpp]#include <sngcm/cmparser/TypeExpr.hpp>
12 [cpp]#include <sngcm/cmparser/Expression.hpp>
13 [cpp]#include <sngcm/cmlexer/CmajorLexer.hpp>
14 [cpp]#include <sngcm/cmlexer/CmajorTokens.hpp>
15 
16 using namespace sngcm::ast;
17 using namespace CmajorTokens;
18 
19 parser api(SNGCM_PARSER_API) EnumerationParser
20 {
21     uselexer CmajorLexer;
22 
23     using SpecifierParser.Specifiers;
24     using IdentifierParser.Identifier;
25     using TypeExprParser.TypeExpr;
26     using ExpressionParser.Expression;
27 
28     EnumType(boost::uuids::uuid* moduleId, ParsingContext* ctx, var std::unique_ptr enumTypeNode, var Span s, var Span beginBraceSpan, var Span endBraceSpan) : EnumTypeNode*
29         ::= Specifiers:specifiers{ s = span; } ENUM Identifier(moduleId):enumTypeId!{ s.end = span.end; enumTypeNode.reset(new EnumTypeNode(s, *moduleId, specifiers, enumTypeId)); }
30             (UnderlyingType(moduleId, ctx):underlyingType{ enumTypeNode->SetUnderlyingType(underlyingType); })?
31             LBRACE!{ beginBraceSpan = span; } EnumConstants(moduleId, ctx, enumTypeNode.get()):enumConstants RBRACE!
32             {
33                 endBraceSpan = span;
34                 enumTypeNode->SetBeginBraceSpan(beginBraceSpan);
35                 enumTypeNode->SetEndBraceSpan(endBraceSpan);
36                 return enumTypeNode.release();
37             }
38         ;
39 
40     UnderlyingType(boost::uuids::uuid* moduleId, ParsingContext* ctx) : Node*
41         ::= COLON TypeExpr(moduleId, ctx):type{ return type; }
42         ;
43 
44     EnumConstants(boost::uuids::uuid* moduleId, ParsingContext* ctx, sngcm::ast::EnumTypeNode* enumType)
45         ::= EnumConstant(moduleId, ctx, enumType):enumConstant!{ enumType->AddConstant(enumConstant); } % COMMA
46         ;
47 
48     EnumConstant(boost::uuids::uuid* moduleId, ParsingContext* ctx, sngcm::ast::EnumTypeNode* enumType, var Span s, var std::unique_ptr expr) : EnumConstantNode*
49         ::= Identifier(moduleId):constantId!{ s = span; }
50         (   ASSIGN Expression(moduleId, ctx):constantValue
51             {
52                 expr.reset(constantValue);
53                 expr->SetFullSpan();
54                 Span v = expr->GetSpan();
55                 s.end = expr->GetSpan().end;
56                 EnumConstantNode* value = new EnumConstantNode(s, *moduleId, constantId, expr.release());
57                 value->SetHasValue();
58                 value->SetStrValue(lexer.GetMatch(v));
59                 return value;
60             }
61         |   empty{ return new EnumConstantNode(s, *moduleId, constantId, MakeNextEnumConstantValue(s, *moduleId, enumType)); }
62         )
63         ;
64 
65     ruleinfo
66     {
67         (EnumType, "enumerated type"), (UnderlyingType, "underlying type"), (EnumConstants, "enumeration constants"), (EnumConstant, "enumeration constant")
68     }
69 }