%{ #include #include #include #include "parser.hpp" %} %token TEOF %token INDENT %token DEDENT %token NEWLINE %token AND %token BREAK %token DEF %token ELIF %token ELSE %token FOR %token IF %token NOT %token OR %token RETURN %token WHILE %token BOOLEAN %token FLOAT %token INTEGER %token IDENTIFIER %token ASSIGN %token PLUS %token MINUS %token TIMES %token DIVIDEDBY %token EQ %token NEQ %token GT %token GTE %token LT %token LTE %token LPAREN %token RPAREN %token COMMA %token COLON %define api.value.type { std::string* } %define api.pure full %define api.push-pull push %start program %{ template ::value, T>::type* = nullptr> void concat(std::string* s, T vs) { s->append(vs); } template ::value, T>::type* = nullptr> void concat(std::string* s, T vs) { s->append(*vs); delete vs; } template void concat(std::string* s, T v, Ts ... vs) { concat(s, v); concat(s, vs...); } template std::string* concatenate(Ts ... vs) { std::string* temp = new std::string(); concat(temp, vs...); return temp; } void yyerror(const char* s) { std::cout << s << std::endl; } std::set varset; void print_standard(std::string* str) { std::cout << "#include " << std::endl; std::cout << "int main() {" << std::endl; for(auto& name : varset) { std::cout << "double " << name << ";" << std::endl; } std::cout << " " << *str << std::endl; for(auto& name : varset) { std::cout << " std::cout << \"" << name << ": \" << " << name << "<< std::endl;" << std::endl; } std::cout << "}"; delete str; } %} %% program : stmts { print_standard($1); } TEOF ; stmts : stmts stmt { $$ = concatenate($1, $2); } | stmt { $$ = $1; } ; stmt : expr NEWLINE { $$ = concatenate($1, ";"); } | if { $$ = $1; } | while { $$ = $1; } | BREAK NEWLINE { $$ = new std::string("break;"); } ; expr : assign { $$ = $1; } | eq { $$ = $1; } ; while : WHILE expr COLON NEWLINE block { $$ = concatenate("while(", $2, ")", $5); } ; if : IF expr COLON NEWLINE block elses { $$ = concatenate("if(", $2, ")", $5, $6); } ; elses : %empty { $$ = new std::string(""); } | elif elses { $$ = concatenate($1, $2); } | else { $$ = $1; } ; elif : ELIF expr COLON NEWLINE block { $$ = concatenate("else if(", $2, ")", $5); } ; else : ELSE COLON NEWLINE block { $$ = concatenate("else", $4); } ; block : INDENT stmts DEDENT { $$ = concatenate("{", $2, "}"); } ; assign : IDENTIFIER ASSIGN expr { varset.insert(*$1); $$ = concatenate($1, "=", $3); } ; eq : eq EQ rel { $$ = concatenate($1, "==", $3); } | eq NEQ rel { $$ = concatenate($1, "!=", $3); } | rel { $$ = $1; } ; rel : rel LT sum { $$ = concatenate($1, "<", $3); } | rel LTE sum { $$ = concatenate($1, "<=", $3); } | rel GT sum { $$ = concatenate($1, ">", $3); } | rel GTE sum { $$ = concatenate($1, ">=", $3); } | sum { $$ = $1; } ; sum : sum PLUS factor { $$ = concatenate($1, "+", $3); } | sum MINUS factor { $$ = concatenate($1, "-", $3); } | factor { $$ = $1; } ; factor : factor TIMES term { $$ = concatenate($1, "*", $3); } | factor DIVIDEDBY term { $$ = concatenate($1, "/", $3); } | term { $$ = $1; } ; term : IDENTIFIER { $$ = $1; } | FLOAT { $$ = $1; } | INTEGER { $$ = $1; } | BOOLEAN { $$ = $1; } | LPAREN expr RPAREN { $$ = $2; } ; %%