%require "3.2" %language "c++" %code requires { #include #include #include "elna/source/parser.hpp" #if ! defined(yyFlexLexerOnce) #include #endif namespace elna::syntax { class FooLexer; } } %code provides { namespace elna::syntax { class FooLexer : public yyFlexLexer { public: yy::location location; FooLexer(std::istream& arg_yyin) : yyFlexLexer(&arg_yyin) { } yy::parser::symbol_type lex(); }; } } %define api.token.raw %define api.token.constructor %define api.value.type variant %define parse.assert %parse-param {elna::syntax::FooLexer& lexer} %parse-param {std::unique_ptr& program} %locations %header %code { #define yylex lexer.lex } %start program; %token IDENTIFIER "identifier" %token NUMBER "number" %token BOOLEAN %token IF THEN WHILE DO %token CONST VAR PROCEDURE %token BEGIN_BLOCK END_BLOCK %token TRUE FALSE %token LEFT_PAREN RIGHT_PAREN SEMICOLON DOT COMMA %token GREATER_EQUAL LESS_EQUAL LESS_THAN GREATER_THAN NOT_EQUAL EQUALS %token PLUS MINUS MULTIPLICATION DIVISION %token ASSIGNMENT COLON HAT AT %type > integer_literal; %type > constant_definition; %type >> constant_definition_part constant_definitions; %type > type_expression; %% program: constant_definition_part { elna::source::position position; std::vector> declarations; std::vector> definitions($1.size()); std::vector>::iterator definition = definitions.begin(); for (auto& constant : $1) { *definition++ = std::move(constant); } program = std::make_unique(position, std::move(definitions), std::move(declarations), std::make_unique(position)); } integer_literal: NUMBER { elna::source::position position{ static_cast(@1.begin.line), static_cast(@1.begin.column) }; $$ = std::make_unique(position, $1); }; type_expression: HAT IDENTIFIER { elna::source::position position{ static_cast(@1.begin.line), static_cast(@1.begin.column) }; $$ = std::make_unique(position, $2, true); } | IDENTIFIER { elna::source::position position{ static_cast(@1.begin.line), static_cast(@1.begin.column) }; $$ = std::make_unique(position, $1, false); } variable_declaration: IDENTIFIER COLON type_expression variable_declarations: variable_declaration COMMA variable_declarations | variable_declaration constant_definition: IDENTIFIER EQUALS integer_literal { elna::source::position position{ static_cast(@1.begin.line), static_cast(@1.begin.column) }; $$ = std::make_unique(position, $1, std::move($3)); }; constant_definitions: constant_definition COMMA constant_definitions { std::swap($$, $3); $$.emplace($$.cbegin(), std::move($1)); } | constant_definition { $$.emplace_back(std::move($1)); } constant_definition_part: /* no constant definitions */ {} | CONST constant_definitions SEMICOLON { std::swap($$, $2); }; %% void yy::parser::error(const location_type& loc, const std::string &message) { std::cerr << "Error: " << message << std::endl; }