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/parser/ParsingContext.hpp>
 8 [hpp]#include <sngcpp/ast/Enumeration.hpp>
 9 [cpp]#include <sngcpp/parser/Expression.hpp>
10 [cpp]#include <sngcpp/parser/Identifier.hpp>
11 [cpp]#include <sngcpp/parser/TypeExpr.hpp>
12 [cpp]#include <sngcpp/lexer/CppLexer.hpp>
13 [cpp]#include <sngcpp/lexer/CppTokens.hpp>
14 
15 using namespace CppTokens;
16 using namespace soulng::lexer;
17 
18 parser api(SNGCPP_PARSER_API) EnumerationParser
19 {
20     uselexer CppLexer;
21 
22     using IdentifierParser.Identifier;
23     using IdentifierParser.QualifiedIdNode;
24     using TypeExprParser.TypeExpr;
25     using ExpressionParser.ConstantExpression;
26 
27     EnumDeclaration(sngcpp::cppparser::ParsingContext* ctx) : sngcpp::ast::Node*
28         ::= EnumSpecifier(ctx):enumSpecifier SEMICOLON{ return enumSpecifier; }
29         ;
30 
31     EnumSpecifier(sngcpp::cppparser::ParsingContext* ctx, var std::unique_ptr enumTypeNode, var Span openBraceSpan, var Span closeBraceSpan) : sngcpp::ast::Node*
32         ::= (EnumHead(ctx):enumHead{ enumTypeNode.reset(enumHead); } LBRACE{ openBraceSpan = span; } Enumerators(ctx, enumTypeNode.get()):enumerators RBRACE!{ closeBraceSpan = span; })
33         {
34             enumTypeNode->SetOpenBraceSpan(openBraceSpan);
35             enumTypeNode->SetCloseBraceSpan(closeBraceSpan);
36             return enumTypeNode.release();
37         }
38         ;
39 
40     EnumHead(sngcpp::cppparser::ParsingContext* ctx, var Span s) : sngcpp::ast::EnumTypeNode*
41         ::= (EnumKey:enumKey{ s = span; } EnumName(ctx):enumName{ s.end = span.end; } (EnumBase(ctx):enumBase{ s.end = span.end; })?)
42         {
43             return new sngcpp::ast::EnumTypeNode(s, enumKey, enumName, enumBase);
44         }
45         ;
46 
47     OpaqueEnumDeclaration(sngcpp::cppparser::ParsingContext* ctx, var Span s) : sngcpp::ast::Node*
48         ::= EnumKey:enumKey{ s = span; } EnumName(ctx):enumName (EnumBase(ctx):enumBase)? SEMICOLON
49         {
50             s.end = span.end; 
51             return new sngcpp::ast::EnumTypeNode(s, enumKey, enumName, enumBase);
52         }
53         ;
54 
55     EnumKey : sngcpp::ast::EnumKey
56         ::= ENUM CLASS{ return sngcpp::ast::EnumKey::enumClass_; }
57         |   ENUM STRUCT { return sngcpp::ast::EnumKey::enumStruct_; }
58         |   ENUM{ return sngcpp::ast::EnumKey::enum_; }
59         ;
60 
61     EnumName(sngcpp::cppparser::ParsingContext* ctx) : sngcpp::ast::Node*
62         ::= QualifiedIdNode(ctx):enumName{ return enumName; }
63         ;
64 
65     EnumBase(sngcpp::cppparser::ParsingContext* ctx) : sngcpp::ast::Node*
66         ::= COLON TypeExpr(ctx):typeExpr{ return typeExpr; }
67         ;
68 
69     Enumerators(sngcpp::cppparser::ParsingContext* ctx, sngcpp::ast::EnumTypeNode* enumTypeNode, var Span s)
70         ::=
71         (   EnumeratorDefinition(ctx):left{ s = span; enumTypeNode->AddEnumerator(s, left); }
72             (COMMA EnumeratorDefinition(ctx):right{ s.end = span.end; enumTypeNode->AddEnumerator(s, right); })*
73         )?
74         ;
75 
76     EnumeratorDefinition(sngcpp::cppparser::ParsingContext* ctx, var Span s, var Span assignmentSpan, var std::u32string valueStr, var std::unique_ptr value) : sngcpp::ast::EnumeratorNode*
77         ::= (Enumerator:enumerator{ s = span; }
78             (   ASSIGN{ assignmentSpan = span; } ConstantExpression(ctx):expr{ value.reset(expr); value->SetFullSpan(); valueStr = lexer.GetMatch(value->GetSpan()); s.end = value->GetSpan().end; })?)
79         {
80             return new sngcpp::ast::EnumeratorNode(s, enumerator, value.release(), valueStr);
81         }
82         ;
83 
84     Enumerator : std::u32string
85         ::= Identifier:id{ return id; }
86         ;
87 }