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/Template.hpp>
  9 [cpp]#include <sngcpp/parser/Declaration.hpp>
 10 [cpp]#include <sngcpp/parser/Expression.hpp>
 11 [cpp]#include <sngcpp/parser/Function.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) TemplateParser
 21 {
 22     uselexer CppLexer;
 23 
 24     using IdentifierParser.Identifier;
 25     using DeclarationParser.Declaration;
 26     using ExpressionParser.ConstantExpression;
 27     using ExpressionParser.ConditionalExpression;
 28     using FunctionParser.ParameterDeclaration;
 29     using TypeExprParser.TypeExpr;
 30 
 31     TemplateDeclaration(sngcpp::cppparser::ParsingContext* ctx, var Span s) : sngcpp::ast::Node*
 32         ::= TEMPLATE{ s = span; } LANGLE TemplateParameterList(ctx):templateParameterList RANGLE! Declaration(ctx):declaration!
 33         {
 34             s.end = span.end;
 35             return new sngcpp::ast::TemplateDeclarationNode(s, templateParameterList, declaration);
 36         }
 37         ;
 38 
 39     TemplateParameterList(sngcpp::cppparser::ParsingContext* ctx, var std::unique_ptr node, var Span s) : sngcpp::ast::Node*
 40         ::=
 41         (   TemplateParameter(ctx):left{ s = span; node.reset(left); }
 42             (COMMA TemplateParameter(ctx):right{ s.end = span.end; node.reset(new sngcpp::ast::TemplateParameterSequenceNode(s, node.release(), right)); })*
 43         )
 44         {
 45             return node.release();
 46         }
 47         ;
 48 
 49     TemplateParameter(sngcpp::cppparser::ParsingContext* ctx) : sngcpp::ast::Node*
 50         ::= TypeParameter(ctx):typeParam{ return typeParam; }
 51         |   ParameterDeclaration(ctx):paramDeclaration{ return paramDeclaration; }
 52         ;
 53 
 54     TypeParameter(sngcpp::cppparser::ParsingContext* ctx, var bool typenameUsed, var Span s) : sngcpp::ast::Node*
 55         ::= ((CLASS{ s = span; typenameUsed = false; } | TYPENAME{ s = span; typenameUsed = true; }) Identifier:id{ s.end = span.end; } (ASSIGN TypeExpr(ctx):typeExpr{ s.end = span.end; })?)
 56         {
 57             return new sngcpp::ast::TypeParameterNode(s, id, typeExpr, typenameUsed);
 58         }
 59         ;
 60 
 61     SimpleTemplateId(sngcpp::cppparser::ParsingContext* ctx, var int arity, var Span s) : sngcpp::ast::Node*
 62         ::=
 63         (   TemplateName:templateName{ s = span; }
 64             LANGLE{ ++lexer.langleCount; ctx->BeginParsingTemplateId(); }
 65             TemplateArgumentList(ctx, &arity):args?
 66             RANGLE{ --lexer.langleCount; ctx->EndParsingTemplateId(); } / { --lexer.langleCount; ctx->EndParsingTemplateId(); }
 67         )
 68         {
 69             s.end = span.end;
 70             return new sngcpp::ast::TemplateIdNode(s, templateName, args, arity);
 71         }
 72         ;
 73 
 74     TemplateId(sngcpp::cppparser::ParsingContext* ctx) : sngcpp::ast::Node*
 75         ::= SimpleTemplateId(ctx):simpleTemplateId{ return simpleTemplateId; }
 76         ;
 77 
 78     TemplateName : sngcpp::ast::IdentifierNode*
 79         ::= Identifier:id{ return new sngcpp::ast::IdentifierNode(span, id); }
 80         ;
 81 
 82     TemplateArgumentList(sngcpp::cppparser::ParsingContext* ctx, int* arity, var std::unique_ptr arg) : sngcpp::ast::Node*
 83         ::=
 84         (   TemplateArgument(ctx):left{ arg.reset(new sngcpp::ast::TemplateArgumentNode(span, left)); ++*arity; }
 85             (COMMA TemplateArgument(ctx):right{ arg.reset(new sngcpp::ast::TemplateArgumentSequenceNode(span, arg.release(), new sngcpp::ast::TemplateArgumentNode(span, right))); ++*arity; })*
 86         )
 87         {
 88             return arg.release();
 89         }
 90         ;
 91 
 92     TemplateArgument(sngcpp::cppparser::ParsingContext* ctx) : sngcpp::ast::Node*
 93         ::= TypeExpr(ctx):typeExpr{ return typeExpr; }
 94         |   ConditionalExpression(ctx):condExpr{ return condExpr; }
 95         ;
 96 
 97     ExplicitInstantiation(sngcpp::cppparser::ParsingContext* ctx, var Span s) : sngcpp::ast::Node*
 98         ::= TEMPLATE{ s = span; } Declaration(ctx):declaration{ s.end = span.end; return new sngcpp::ast::ExplicitInstantiationNode(s, declaration); }
 99         ;
100 
101     ExplicitSpecialization(sngcpp::cppparser::ParsingContext* ctx, var Span s) : sngcpp::ast::Node*
102         ::= TEMPLATE{ s = span; } LANGLE RANGLE Declaration(ctx):declaration{ s.end = span.end; return new sngcpp::ast::ExplicitSpecializationNode(s, declaration); }
103         ;
104 }