/* * MathParser.ypp, part of LatAnalyze 3 * * Copyright (C) 2013 - 2014 Antonin Portelli * * LatAnalyze 3 is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * LatAnalyze 3 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with LatAnalyze 3. If not, see . */ %{ #include #include #include #include #include using namespace std; using namespace Latan; %} %pure-parser %name-prefix="_math_" %locations %defines %error-verbose %parse-param { Latan::MathInterpreter::MathParserState *state } %initial-action {yylloc.last_column = 0;} %lex-param { void* scanner } %union { double val_double; char val_char; char val_str[MAXIDLENGTH]; Latan::MathNode *val_node; } %token ERR %token FLOAT %token ID %token RETURN %left '=' %left '+' '-' %left '*' '/' %left '^' %nonassoc UMINUS %type stmt stmt_list expr func_args %{ int _math_lex(YYSTYPE *lvalp, YYLTYPE *llocp, void *scanner); void _math_error(YYLTYPE *locp, MathInterpreter::MathParserState *state, const char *err) { stringstream buf; buf << *(state->streamName) << ":" << locp->first_line << ":"\ << locp->first_column << ": " << err; LATAN_ERROR(Parsing, buf.str()); } #define scanner state->scanner %} %% program: /* empty string */ | stmt_list {*(state->data) = $1;} ; stmt: ';' {$$ = new MathNode(";", MathNode::Type::op, 0);} | expr ';' {$$ = $1;} | ID '=' expr ';' { $$ = new MathNode("=", MathNode::Type::op, 2, \ new MathNode($ID,MathNode::Type::var), $3); } | RETURN expr ';' {$$ = new MathNode("return", MathNode::Type::keyw, 1, $2);} | '{' stmt_list '}' {$$ = $2;} ; stmt_list: stmt {$$ = $1;} | stmt_list stmt {$$ = new MathNode(";", MathNode::Type::op, 2, $1, $2);} ; expr: FLOAT {$$ = new MathNode($FLOAT, MathNode::Type::cst);} | ID {$$ = new MathNode($ID, MathNode::Type::var);} | '-' expr %prec UMINUS {$$ = new MathNode("-", MathNode::Type::op, 1, $2);} | expr '+' expr {$$ = new MathNode("+", MathNode::Type::op, 2, $1, $3);} | expr '-' expr {$$ = new MathNode("-", MathNode::Type::op, 2, $1, $3);} | expr '*' expr {$$ = new MathNode("*", MathNode::Type::op, 2, $1, $3);} | expr '/' expr {$$ = new MathNode("/", MathNode::Type::op, 2, $1, $3);} | expr '^' expr {$$ = new MathNode("^", MathNode::Type::op, 2, $1, $3);} | '(' expr ')' {$$ = $2;} | ID '(' func_args ')' {$$ = $3; $$->setName($ID);} ; func_args: /* empty string */ {$$ = new MathNode("", MathNode::Type::func);} | expr {$$ = new MathNode("", MathNode::Type::func, 1, $1);} | func_args ',' expr {$$ = $1; $$->pushArg($3);} ;