%skeleton "lalr1.cc" %require "3.0" %defines %define api.value.type variant %define api.token.raw %define api.parser.class { parser } %define api.namespace { yy } %define api.token.prefix {TOK_} %define parse.trace %code requires { #include #include "ast.hpp" class Scanner; } %code { #include #include "scanner.hpp" #undef yylex #define yylex scanner->lex } %parse-param { Scanner* scanner } %parse-param { std::unique_ptr* result } %token IDENTIFIER STRING %token NUMBER %left KW_OR %left KW_AND %right KW_NOT // unary logical NOT %token KW_DEF KW_IF KW_RETURN KW_FOR KW_IN KW_PASS KW_ELSE KW_ELIF KW_CLASS %token L_PAREN R_PAREN L_BRACKET R_BRACKET L_BRACE R_BRACE %token DOT COLON SEMICOLON COMMA %token INDENT DEDENT NEWLINE EOF %left BIT_OR %left BIT_XOR %left BIT_AND %left LSHIFT RSHIFT %token BIT_NOT %nonassoc EQ NE LT LTE GT GTE %left PLUS MINUS %left MULTIPLY DIVIDE MODULO %right ASSIGN PLUS_ASSIGN MINUS_ASSIGN MULTIPLY_ASSIGN DIVIDE_ASSIGN MODULO_ASSIGN %right BIT_AND_ASSIGN BIT_OR_ASSIGN BIT_XOR_ASSIGN LSHIFT_ASSIGN RSHIFT_ASSIGN %type > expr %type > stmt %type >> args %type >> stmt_list %% input: stmt_list EOF { *result = std::make_unique(std::move($1));} ; stmt_list: /* empty */ { $$ = std::vector>(); } | stmt_list stmt { $1.push_back(std::move($2)); $$ = std::move($1); } ; stmt: expr NEWLINE { $$ = std::make_unique(std::move($1)); } | expr ASSIGN expr NEWLINE { $$ = std::make_unique(std::move($1), std::move($3));} | KW_IF expr COLON NEWLINE INDENT stmt_list DEDENT { $$ = std::make_unique(std::move($2), std::move($6), std::vector>()); } | KW_IF expr COLON NEWLINE INDENT stmt_list DEDENT KW_ELSE COLON NEWLINE INDENT stmt_list DEDENT{ $$ = std::make_unique(std::move($2), std::move($6), std::move($12)); } ; expr: NUMBER { $$ = std::make_unique($1); } | IDENTIFIER { $$ = std::make_unique($1); } | STRING { $$ = std::make_unique($1); } | expr PLUS expr { $$ = std::make_unique( BinaryOperator(BinaryOperator::ADD), std::move($1), std::move($3)); } | expr MULTIPLY expr { $$ = std::make_unique( BinaryOperator(BinaryOperator::MUL), std::move($1), std::move($3)); } | L_PAREN expr R_PAREN {$$ = std::move($2); /* #todo: test for precedence*/} | expr L_PAREN args R_PAREN { $$ = std::make_unique(std::move($1), std::move($3));} | expr DOT IDENTIFIER { $$ = std::make_unique(std::move($1), $3);} ; args: /* empty */ { $$ = std::vector>(); } | expr { $$ = std::vector>(); $$.push_back(std::move($1)); } | args COMMA expr { $1.push_back(std::move($3)); $$ = std::move($1); } ; %% namespace yy { void parser::error(const std::string& msg) { std::cerr << "Error: " << msg << "\n"; } }