%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 KW_WHILE KW_BREAK KW_CONTINUE %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 %left POWER %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 > opt_expr %type > slice %type > stmt %type >> args %type >> tuple %type >> stmt_list %type > params %type >> elif_chain %% 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 elif_chain{ $$ = std::make_unique(std::move($2), std::move($6), std::move($8)); } | KW_FOR IDENTIFIER KW_IN expr COLON NEWLINE INDENT stmt_list DEDENT { $$ = std::make_unique ($2, std::move($4), std::move($8)); } | KW_DEF IDENTIFIER L_PAREN params R_PAREN COLON NEWLINE INDENT stmt_list DEDENT { $$ = std::make_unique($2, std::move($4), std::move($9)); } | KW_RETURN expr NEWLINE { $$ = std::make_unique(std::move($2)); } | KW_RETURN NEWLINE { $$ = std::make_unique(nullptr); } | KW_PASS NEWLINE { $$ = std::make_unique(); } | KW_BREAK NEWLINE { $$ = std::make_unique(); } | KW_CONTINUE NEWLINE { $$ = std::make_unique(); } | KW_WHILE expr COLON NEWLINE INDENT stmt_list DEDENT { $$ = std::make_unique(std::move($2), std::move($6)); } | KW_CLASS IDENTIFIER COLON NEWLINE INDENT stmt_list DEDENT { $$ = std::make_unique(std::move($2), std::move($6)); } ; 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)); } | expr MINUS expr { $$ = std::make_unique( BinaryOperator(BinaryOperator::SUB), std::move($1), std::move($3)); } | expr LT expr { $$ = std::make_unique( BinaryOperator(BinaryOperator::LT) , std::move($1), std::move($3)); } | expr KW_AND expr { $$ = std::make_unique( BinaryOperator(BinaryOperator::AND) , std::move($1), std::move($3)); } | expr KW_OR expr { $$ = std::make_unique( BinaryOperator(BinaryOperator::OR) , std::move($1), std::move($3)); } | expr LTE expr { $$ = std::make_unique( BinaryOperator(BinaryOperator::LTE) , std::move($1), std::move($3)); } | expr POWER expr { $$ = std::make_unique( BinaryOperator(BinaryOperator::POWER) , std::move($1), std::move($3)); } | expr MODULO expr { $$ = std::make_unique( BinaryOperator(BinaryOperator::MOD) , std::move($1), std::move($3)); } | expr EQ expr { $$ = std::make_unique( BinaryOperator(BinaryOperator::EQ) , std::move($1), std::move($3)); } | expr DIVIDE expr { $$ = std::make_unique( BinaryOperator(BinaryOperator::DIV) , std::move($1), std::move($3)); } | KW_NOT expr { $$ = std::make_unique( UnaryOperator(UnaryOperator::NOT) , std::move($2)); } | expr L_BRACKET expr R_BRACKET { $$ = std::make_unique(std::move($1), std::move($3));} | expr L_BRACKET slice R_BRACKET{ $$ = std::make_unique(std::move($1), std::move($3)); } | L_PAREN expr R_PAREN {$$ = std::move($2); } | 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);} | L_BRACKET args R_BRACKET { $$ = std::make_unique(std::move($2));} | L_PAREN tuple R_PAREN { $$ = std::make_unique(std::move($2));} | MINUS expr { $$ = std::make_unique(UnaryOperator(UnaryOperator::NEG), std::move($2));} ; slice: opt_expr COLON opt_expr { $$ = std::make_unique(std::move($1), std::move($3), nullptr); } | opt_expr COLON opt_expr COLON opt_expr { $$ = std::make_unique(std::move($1), std::move($3), std::move($5)); } ; opt_expr: { $$ = nullptr;} | expr { $$ = std::move($1);} args: /* empty */ { $$ = std::vector>(); } | expr { $$ = std::vector>(); $$.push_back(std::move($1)); } | args COMMA expr { $1.push_back(std::move($3)); $$ = std::move($1); } ; tuple: expr { $$ = std::vector>(); $$.push_back(std::move($1)); } | tuple COMMA expr { $1.push_back(std::move($3)); $$ = std::move($1); } params: { $$ = std::vector();} | IDENTIFIER { $$ = std::vector(); $$.push_back($1); } | params COMMA IDENTIFIER {$1.push_back($3); $$ = std::move($1);} elif_chain: /* empty */ { $$ = std::vector>(); } | KW_ELIF expr COLON NEWLINE INDENT stmt_list DEDENT elif_chain { std::vector> output; output.push_back(std::make_unique(std::move($2), std::move($6), std::move($8))); $$ = std::move(output); } | KW_ELSE COLON NEWLINE INDENT stmt_list DEDENT { $$ = std::move($5); } ; %% namespace yy { void parser::error(const std::string& msg) { std::cerr << "Error: " << msg << "\n"; } }