Untitled
unknown
plain_text
2 years ago
3.8 kB
8
Indexable
%skeleton "lalr1.cc"
%require "2.5"
%defines
%define api.namespace {calc}
%define api.value.type variant
%define api.parser.class {Parser}
%code requires {
#include <iostream>
#include <memory>
#include "ast.h"
namespace calc {class Lexer;}
}
%parse-param {calc::Lexer& lexer} {std::shared_ptr<Ast>& result} {std::string& message}
%code {
#include "lexer.h"
#define yylex lexer.lex
}
%token END 0 "end of file"
%token ERROR
%token EOL "\n"
%token <int> NUM
%token <std::string> NAME
%token ASSIGN "="
%token PLUS "+"
%token MINUS "-"
%token MUL "*"
%token DIV "/"
%token LPAR "("
%token RPAR ")"
%token FUNC "def"
%token COLON ":"
%token COMMA ","
%token DO "do"
%token DONE "done"
%token IF "if"
%token ELSE "else"
%token WHILE "while"
%token OR "||"
%token AND "&&"
%token NOT "!"
%token EQUAL "=="
%token NOT_EQUAL "!="
%token LESS "<"
%token LESS_OR_EQUAL "<="
%token GREATER ">"
%token GREATER_OR_EQUAL ">="
%type <std::shared_ptr<Ast>> expr stmt
%type <std::vector<std::string>> params
%type <std::vector<std::shared_ptr<Ast>>> arguments
%type <std::vector<std::shared_ptr<Ast>>> block
%left "+" "-"
%left "*" "/"
%left "||"
%left "&&"
%left "==" "!=" "<" "<=" ">" ">="
%nonassoc UMINUS
%nonassoc NOT_EXPR
%right "then" "else"
%%
input: stmt "\n" { result = $1; }
;
params : NAME { $$ = std::vector<std::string>{$1}; }
| params "," NAME { $1.push_back($3); $$ = std::move($1); }
;
arguments : expr { $$ = std::vector<std::shared_ptr<Ast>>{$1}; }
| arguments "," expr { $1.push_back($3); $$ = std::move($1); }
;
block : stmt { $$ = std::vector<std::shared_ptr<Ast>>{$1}; }
| block "\n" stmt { $1.push_back($3); $$ = std::move($1); }
;
stmt: expr { $$ = $1; }
| "def" NAME "(" params ")" ":" stmt { $$ = new_definition($2, $4, std::vector<std::shared_ptr<Ast>>{$7}); }
| "def" NAME "(" params ")" ":" "do" "\n" block "\n" "done" {$$ = new_definition($2, $4, $9); }
| NAME "=" expr { $$ = new_assignment($1, $3); }
| NAME "(" arguments ")" { $$ = new_function($1, $3); }
| "if" expr ":" "do" "\n" block "\n" "done" %prec "then" { $$ = new_condition($2, $6); }
| "if" expr ":" stmt %prec "then" { $$ = new_condition($2, std::vector<std::shared_ptr<Ast>>{$4}); }
| "if" expr ":" stmt "\n" "else" ":" stmt { $$ = new_condition($2, std::vector<std::shared_ptr<Ast>>{$4}, std::vector<std::shared_ptr<Ast>>{$8}); }
| "if" expr ":" "do" "\n" block "\n" "done" "\n" "else" ":" "do" "\n" block "\n" "done" { $$ = new_condition($2, $6, $14); }
| "while" stmt ":" stmt { $$ = new_while($2, std::vector<std::shared_ptr<Ast>>{$4}); }
| "while" stmt ":" "do" "\n" block "\n" "done" { $$ = new_while($2, $6); }
;
expr: NUM { $$ = new_number($1); }
| NAME { $$ = new_variable($1); }
| expr "+" expr { $$ = new_binary(Opcode::plus, $1, $3); }
| expr "-" expr { $$ = new_binary(Opcode::minus, $1, $3); }
| expr "*" expr { $$ = new_binary(Opcode::mul, $1, $3); }
| expr "/" expr { $$ = new_binary(Opcode::div, $1, $3); }
| "(" expr ")" { $$ = $2; }
| "-" %prec UMINUS expr { $$ = new_unary(Opcode::uminus, $2); }
| expr "||" expr { $$ = new_binary(Opcode::or_expr, $1, $3); }
| expr "&&" expr { $$ = new_binary(Opcode::and_expr, $1, $3); }
| "!" %prec NOT_EXPR expr { $$ = new_unary(Opcode::not_expr, $2); }
| expr "==" expr { $$ = new_binary(Opcode::equal, $1, $3); }
| expr "!=" expr { $$ = new_binary(Opcode::not_equal, $1, $3); }
| expr "<" expr { $$ = new_binary(Opcode::less, $1, $3); }
| expr "<=" expr { $$ = new_binary(Opcode::less_or_equal, $1, $3); }
| expr ">" expr { $$ = new_binary(Opcode::greater, $1, $3); }
| expr ">=" expr { $$ = new_binary(Opcode::greater_or_equal, $1, $3); }
;
%%
void calc::Parser::error(const std::string& err)
{
message = err;
}Editor is loading...