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/Class.hpp>
  8 [hpp]#include <sngcm/cmparser/ParsingContext.hpp>
  9 [cpp]#include <sngcm/cmparser/Attribute.hpp>
 10 [cpp]#include <sngcm/cmparser/Specifier.hpp>
 11 [cpp]#include <sngcm/cmparser/Identifier.hpp>
 12 [cpp]#include <sngcm/cmparser/TypeExpr.hpp>
 13 [cpp]#include <sngcm/cmparser/Concept.hpp>
 14 [cpp]#include <sngcm/cmparser/Expression.hpp>
 15 [cpp]#include <sngcm/cmparser/Statement.hpp>
 16 [cpp]#include <sngcm/cmparser/Parameter.hpp>
 17 [cpp]#include <sngcm/cmparser/Function.hpp>
 18 [cpp]#include <sngcm/cmparser/Template.hpp>
 19 [cpp]#include <sngcm/cmparser/Typedef.hpp>
 20 [cpp]#include <sngcm/cmparser/Enumeration.hpp>
 21 [cpp]#include <sngcm/cmparser/Constant.hpp>
 22 [cpp]#include <sngcm/cmparser/Delegate.hpp>
 23 [cpp]#include <sngcm/cmlexer/CmajorLexer.hpp>
 24 [cpp]#include <sngcm/cmlexer/CmajorTokens.hpp>
 25 
 26 using namespace sngcm::ast;
 27 using namespace CmajorTokens;
 28 
 29 parser api(SNGCM_PARSER_API) ClassParser
 30 {
 31     uselexer CmajorLexer;
 32 
 33     using AttributeParser.Attributes;
 34     using SpecifierParser.Specifiers;
 35     using IdentifierParser.Identifier;
 36     using IdentifierParser.QualifiedId;
 37     using TypeExprParser.TypeExpr;
 38     using ConceptParser.WhereConstraint;
 39     using ExpressionParser.ArgumentList;
 40     using StatementParser.CompoundStatement;
 41     using ParameterParser.ParameterList;
 42     using FunctionParser.FunctionGroupId;
 43     using TemplateParser.TemplateId;
 44     using TemplateParser.TemplateParameterList;
 45     using TypedefParser.Typedef;
 46     using EnumerationParser.EnumType;
 47     using ConstantParser.Constant;
 48     using DelegateParser.Delegate;
 49     using DelegateParser.ClassDelegate;
 50 
 51     Class(boost::uuids::uuid* moduleId, ParsingContext* ctx, var std::unique_ptr cls, var Span s, var Span specifierSpan, var Span classSpan, var Span beginBraceSpan, var Span endBraceSpan) : ClassNode*
 52         ::= empty{ s = span; } Attributes(moduleId):attrs? (Specifiers:specifiers{ specifierSpan = span; } - NEW) CLASS{ classSpan = span; } Identifier(moduleId):id
 53         {
 54             s.end = span.end;
 55             cls.reset(new ClassNode(s, *moduleId, specifiers, id, attrs));
 56             cls->SetSpecifierSpan(specifierSpan);
 57             cls->SetClassSpan(classSpan);
 58         }
 59         TemplateParameterList(moduleId, ctx, cls.get()):templateParams?
 60         InheritanceAndInterfaces(moduleId, ctx, cls.get()):inheritance?
 61         (WhereConstraint(moduleId, ctx):constraint{ cls->SetConstraint(constraint); })?
 62         LBRACE!{ beginBraceSpan = span; } ClassContent(moduleId, ctx, cls.get()):content RBRACE!
 63         {
 64             endBraceSpan = span;
 65             cls->SetBeginBraceSpan(beginBraceSpan);
 66             cls->SetEndBraceSpan(endBraceSpan);
 67             return cls.release();
 68         }
 69         ;
 70 
 71     InheritanceAndInterfaces(boost::uuids::uuid* moduleId, ParsingContext* ctx, sngcm::ast::ClassNode* classNode)
 72         ::= COLON
 73         (   empty{ ctx->BeginParsingTypeExpr(); }
 74             BaseClassOrInterface(moduleId, ctx):baseOrIntf{ classNode->AddBaseClassOrInterface(baseOrIntf); ctx->EndParsingTypeExpr(); } / { ctx->EndParsingTypeExpr(); }
 75         ) % COMMA
 76         ;
 77 
 78     BaseClassOrInterface(boost::uuids::uuid* moduleId, ParsingContext* ctx) : Node*
 79         ::= TemplateId(moduleId, ctx):templateId{ return templateId; }
 80         |   QualifiedId(moduleId):qid{ return qid; }
 81         ;
 82 
 83     ClassContent(boost::uuids::uuid* moduleId, ParsingContext* ctx, sngcm::ast::ClassNode* classNode)
 84         ::= (ClassMember(moduleId, ctx, classNode):classMember{ classNode->AddMember(classMember); })*
 85         ;
 86 
 87     ClassMember(boost::uuids::uuid* moduleId, ParsingContext* ctx, sngcm::ast::ClassNode* classNode) : Node*
 88         ::= StaticConstructor(moduleId, ctx, classNode):staticConstructor{ return staticConstructor; }
 89         |   Constructor(moduleId, ctx, classNode):constructor{ return constructor; }
 90         |   Destructor(moduleId, ctx, classNode):destructor{ return destructor; }
 91         |   MemberFunction(moduleId, ctx):memberFunction{ return memberFunction; }
 92         |   ConversionFunction(moduleId, ctx):conversionFunction{ return conversionFunction; }
 93         |   MemberVariable(moduleId, ctx):memberVariable{ return memberVariable; }
 94         |   Typedef(moduleId, ctx):typedefinition{ return typedefinition; }
 95         |   Class(moduleId, ctx):cls{ return cls; }
 96         |   EnumType(moduleId, ctx):enumType{ return enumType; }
 97         |   Constant(moduleId, ctx):constant{ return constant; }
 98         |   Delegate(moduleId, ctx):delegate{ return delegate; }
 99         |   ClassDelegate(moduleId, ctx):classDelegate{ return classDelegate; }
100         ;
101 
102     StaticConstructor(boost::uuids::uuid* moduleId, ParsingContext* ctx, sngcm::ast::ClassNode* classNode, var std::unique_ptr staticConstructor, var Span s, var Span specifierSpan,
103         var std::u32string className) : StaticConstructorNode*
104         ::=
105         (   empty{ s = span; } Attributes(moduleId):attrs? Specifiers:specifiers{ specifierSpan = span; } Identifier(moduleId):id{ className = lexer.GetMatch(span); } LPAREN RPAREN
106             {
107                 s.end = span.end;
108                 if (className != classNode->Id()->Str()) pass = false; else if (!StaticConstructorSpecifiers(specifiers)) pass = false; else
109                 {
110                     staticConstructor.reset(new StaticConstructorNode(s, *moduleId, specifiers, attrs));
111                     staticConstructor->SetClassId(id);
112                     staticConstructor->SetSpecifierSpan(specifierSpan);
113                 }
114             }
115             (COLON (Initializer(moduleId, ctx):initializer{ staticConstructor->AddInitializer(initializer); } % COMMA))?
116             (WhereConstraint(moduleId, ctx):constraint{ staticConstructor->SetConstraint(constraint); })?
117             (CompoundStatement(moduleId, ctx):body{ staticConstructor->SetBody(body); } | SEMICOLON)
118         )
119         {
120             return staticConstructor.release();
121         }
122         ;
123 
124     Constructor(boost::uuids::uuid* moduleId, ParsingContext* ctx, sngcm::ast::ClassNode* classNode, var std::unique_ptr ctor, var Span s, var Span specifierSpan) : Node*
125         ::=
126         (   empty{ s = span; } Attributes(moduleId):attrs? Specifiers:specifiers{ specifierSpan = span; } Identifier(moduleId):id
127             {
128                 std::u32string className = lexer.GetMatch(span);
129                 s.end = span.end;
130                 if (className != classNode->Id()->Str()) pass = false; else
131                 {
132                     ctor.reset(new ConstructorNode(s, *moduleId, specifiers, attrs));
133                     ctor->SetClassId(id);
134                     ctor->SetSpecifierSpan(specifierSpan);
135                 }
136             }
137             ParameterList(moduleId, ctx, ctor.get()):paramList
138             (COLON (Initializer(moduleId, ctx):initializer{ ctor->AddInitializer(initializer); } % COMMA))?
139             (WhereConstraint(moduleId, ctx):constraint{ ctor->SetConstraint(constraint); })?
140             (CompoundStatement(moduleId, ctx):body{ ctor->SetBody(body); } | SEMICOLON)
141         )
142         {
143             return ctor.release();
144         }
145         ;
146 
147     Destructor(boost::uuids::uuid* moduleId, ParsingContext* ctx, sngcm::ast::ClassNode* classNode, var std::unique_ptr dtor, var Span s, var Span specifierSpan, var std::u32string className) : Node*
148         ::=
149         (   empty{ s = span; } Attributes(moduleId):attrs? Specifiers:specifiers{ specifierSpan = span; } CPL Identifier(moduleId):id{ className = lexer.GetMatch(span); } LPAREN! RPAREN!
150             {
151                 s.end = span.end;
152                 if (className != classNode->Id()->Str()) pass = false; else
153                 {
154                     dtor.reset(new DestructorNode(s, *moduleId, specifiers, attrs));
155                     dtor->SetClassId(id);
156                     dtor->SetSpecifierSpan(specifierSpan);
157                 }
158             }
159             (WhereConstraint(moduleId, ctx):contraint{ dtor->SetConstraint(contraint); })?
160             (CompoundStatement(moduleId, ctx):body{ dtor->SetBody(body); } | SEMICOLON)
161         )
162         {
163             return dtor.release();
164         }
165         ;
166 
167     Initializer(boost::uuids::uuid* moduleId, ParsingContext* ctx, var std::unique_ptr initializer) : InitializerNode*
168         ::=
169         (   THIS{ initializer.reset(new ThisInitializerNode(span, *moduleId)); } LPAREN! ArgumentList(moduleId, ctx, initializer.get()):thisArgs! RPAREN!
170         |   BASE{ initializer.reset(new BaseInitializerNode(span, *moduleId)); } LPAREN! ArgumentList(moduleId, ctx, initializer.get()):baseArgs! RPAREN!
171         |   Identifier(moduleId):id{ initializer.reset(new MemberInitializerNode(span, *moduleId, id)); } LPAREN! ArgumentList(moduleId, ctx, initializer.get()):memberArgs! RPAREN!
172         )
173         {
174             return initializer.release();
175         }
176         ;
177 
178     MemberFunction(boost::uuids::uuid* moduleId, ParsingContext* ctx, var std::unique_ptr memFun, var Span s, var Span specifierSpan, var Span groupIdSpan) : Node*
179         ::=
180         (   empty{ s = span; } Attributes(moduleId):attrs? Specifiers:specifiers{ specifierSpan = span; } TypeExpr(moduleId, ctx):returnType FunctionGroupId(moduleId, ctx):groupId
181             {
182                 s.end = span.end;
183                 groupIdSpan = span;
184                 memFun.reset(new MemberFunctionNode(s, *moduleId, specifiers, returnType, groupId, attrs));
185                 memFun->SetSpecifierSpan(specifierSpan);
186                 memFun->SetGroupIdSpan(groupIdSpan);
187             }
188             ParameterList(moduleId, ctx, memFun.get()):paramList (CONST{ memFun->SetConst(); })?
189             (WhereConstraint(moduleId, ctx):constraint{ memFun->SetConstraint(constraint); })?
190             (CompoundStatement(moduleId, ctx):body{ memFun->SetBody(body); } | SEMICOLON)
191         )
192         {
193             return memFun.release();
194         }
195         ;
196 
197     ConversionFunction(boost::uuids::uuid* moduleId, ParsingContext* ctx, var std::unique_ptr conversionFun, var Span s, var Span specifierSpan) : Node*
198         ::=
199         (   empty{ s = span; } Attributes(moduleId):attrs? Specifiers:specifiers{ specifierSpan = span; } OPERATOR TypeExpr(moduleId, ctx):type LPAREN! RPAREN!
200             {
201                 s.end = span.end;
202                 conversionFun.reset(new ConversionFunctionNode(s, *moduleId, specifiers, type, attrs));
203                 conversionFun->SetSpecifierSpan(specifierSpan);
204             }
205             (CONST{ conversionFun->SetConst(); })?
206             (WhereConstraint(moduleId, ctx):constraint{ conversionFun->SetConstraint(constraint); })?
207             (CompoundStatement(moduleId, ctx):body{ conversionFun->SetBody(body); } | SEMICOLON)
208         )
209         {
210             return conversionFun.release();
211         }
212         ;
213 
214     MemberVariable(boost::uuids::uuid* moduleId, ParsingContext* ctx, var Span s, var Span specifierSpan) : MemberVariableNode*
215         ::= empty{ s = span; } Attributes(moduleId):attrs? Specifiers:specifiers{ specifierSpan = span; } TypeExpr(moduleId, ctx):type Identifier(moduleId):id SEMICOLON
216         {
217             s.end = span.end;
218             MemberVariableNode* value = new MemberVariableNode(s, *moduleId, specifiers, type, id, attrs);
219             value->SetSpecifierSpan(specifierSpan);
220             return value;
221         }
222         ;
223 }