%{ /* This file is part of exprparser, a lex/yacc based expression parser Copyright (C) 2002-6 Toby Thain, toby@telegraphics.com.au This program 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 2 of the License, or (at your option) any later version. This program 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 this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "node.h" void yyerror(char*); int yylex(void); // hack. correct prototype is buried in lex output #define DPARSE struct node *parsetree; char *errstr; %} %token TOK_NUM TOK_EOF TOK_FN1 TOK_FN2 TOK_FN3 TOK_VAR TOK_UNKNOWN TOK_BADCHAR %left ',' %left '?' ':' %left LOGAND LOGOR %left EQ NE %left '<' LE '>' GE %left '-' '+' %left '*' '/' %right '^' %left NEG %% input : expr { parsetree = $1; } ; expr : TOK_NUM | TOK_VAR /* arithmetic operators */ | expr '+' expr { $$ = $2; $$->child[0] = $1 ; $$->child[1] = $3; } | expr '-' expr { $$ = $2; $$->child[0] = $1 ; $$->child[1] = $3; } | expr '*' expr { $$ = $2; $$->child[0] = $1 ; $$->child[1] = $3; } | expr '/' expr { $$ = $2; $$->child[0] = $1 ; $$->child[1] = $3; } /* exponentiation */ | expr '^' expr { $$ = $2; $$->child[0] = $1 ; $$->child[1] = $3; } /* relational operators */ | expr EQ expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; } | expr NE expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; } | expr '<' expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; } | expr LE expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; } | expr '>' expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; } | expr GE expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; } /* logical operators */ | expr LOGAND expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; } | expr LOGOR expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; } | '!' expr %prec NEG { $$ = $1; $$->child[0] = $2; } /* conditional operator */ | expr '?' expr ':' expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; $$->child[2] = $5; } /* sequence operator */ /*| expr ',' expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }*/ /* unary operators */ | '-' expr %prec NEG { $$ = $1; $$->child[0] = 0; $$->child[1] = $2; } | '+' expr %prec NEG { $$ = $2; } /* parentheses (grouping) */ | '(' expr ')' { $$ = $2; } /* functions */ | TOK_FN1 '(' expr ')' { $$ = $1; $$->child[0] = $3; } | TOK_FN2 '(' expr ',' expr ')' { $$ = $1; $$->child[0] = $3; $$->child[1] = $5; } | TOK_FN3 '(' expr ',' expr ',' expr ')' { $$ = $1; $$->child[0] = $3; $$->child[1] = $5; $$->child[2] = $7; } /* error tokens */ | TOK_UNKNOWN { yyerror("unknown identifier"); YYERROR; } | TOK_BADCHAR { yyerror("bad character"); YYERROR; } ; %% struct node *parseformula(char *s){ node_list = NULL; yy_scan_string(s); if(yyparse()){ freeallnodes(); return NULL; }else return parsetree; } void yyerror(char *msg){ errstr = msg; }