/* pdnmesh - a 2D finite element solver Copyright (c) 2001-2005 Sarod Yatawatta 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 */ /* yacc file */ %{ /* * $Id: parser.y,v 1.17 2005/02/18 22:30:37 sarod Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include "types.h" /* function prototypes */ static exp_nodetype * opr(int oper, int nops, ...); static exp_nodetype * val( int id ); static exp_nodetype * cons(long double value); static void freenode(exp_nodetype *p); void yyerror(char *s); /* to remove compiler warnings */ extern int yylex(void); %} /* nodetype for syntax tree */ %union { MY_DOUBLE val; /* values */ int sym; /* variables */ exp_nodetype * nptr; /* operator nodes */ }; %token CONSTANT %token VARIABLE %token SIN STEP COS LOG FABS /* precedence */ %left '+' '-' %left '*' '/' %left '^' %nonassoc UMINUS /* unary minus */ %left SIN STEP COS LOG FABS %type expr stmt %% function: function stmt { #ifdef DEBUG printf("parser: expression complete!\n"); #endif /* insert expression to boundary */ insert_expression($2, current_boundary_number); return(0); /* return root of parse tree */ } | /* empty */ ; stmt: ';' { #ifdef DEBUG printf("parser: empty ;\n"); #endif $$ = opr(';', 2, NULL, NULL); } | expr ';'{ #ifdef DEBUG printf("parser: expression ;\n"); #endif $$ = $1; } | error ';'{ #ifdef DEBUG printf("parser: error ;\n"); #endif yyerrok; } ; expr: CONSTANT { #ifdef DEBUG printf("parser: expression CONST\n"); #endif $$ = cons($1); } | VARIABLE { #ifdef DEBUG printf("parser: expression VAR\n"); #endif $$ = val($1); } | '-' expr %prec UMINUS { #ifdef DEBUG printf("parser: expression neg\n"); #endif $$ = opr(UMINUS, 1, $2); } | expr '+' expr { #ifdef DEBUG printf("parser: expression +\n"); #endif $$ = opr('+', 2, $1, $3); } | expr '-' expr { #ifdef DEBUG printf("parser: expression -\n"); #endif $$ = opr('-', 2, $1, $3); } | expr '*' expr { #ifdef DEBUG printf("parser: expression *\n"); #endif $$ = opr('*', 2, $1, $3); } | expr '/' expr { #ifdef DEBUG printf("parser: expression /\n"); #endif $$ = opr('/', 2, $1, $3); } | expr '^' expr { #ifdef DEBUG printf("parser: expression ^\n"); #endif $$ = opr('^', 2, $1, $3); } | '(' expr ')' { #ifdef DEBUG printf("parser: expression ()\n"); #endif $$ = $2; } | SIN expr { #ifdef DEBUG printf("parser: expression SIN\n"); #endif $$ = opr(SIN, 1, $2); } | COS expr { #ifdef DEBUG printf("parser: expression COS\n"); #endif $$ = opr(COS, 1, $2); } | LOG expr { #ifdef DEBUG printf("parser: expression LOG\n"); #endif $$ = opr(LOG, 1, $2); } | STEP expr { #ifdef DEBUG printf("parser: expression STEP\n"); #endif $$ = opr(STEP, 1, $2); } | FABS expr { #ifdef DEBUG printf("parser: expression FABS\n"); #endif $$ = opr(FABS, 1, $2); } ; %% /* functions */ /* insert constants */ static exp_nodetype * cons(long double value) { exp_nodetype *p; #ifdef DEBUG printf("\t\tparser: insert constnt node\n"); #endif /* allocate memory */ if ( (p = malloc(sizeof(node_const)) ) == NULL) yyerror("out of memory"); /* copy information */ p->type = CCONST; p->constnt.value = value; return(p); } /* insert variables */ static exp_nodetype * val(int i) { exp_nodetype *p; #ifdef DEBUG printf("\t\tparser: insert variable node\n"); #endif /* allocate memory */ if ( (p = malloc(sizeof(node_var))) == NULL) yyerror("out of memory"); /* copy information */ p->type = VARI; p->var.d = i; return(p); } /* insert operators */ static exp_nodetype * opr(int oper, int nops, ...) { va_list ap; /* variable list of arguments */ exp_nodetype *p; size_t size; int i; #ifdef DEBUG printf("\t\tparser: insert op node\n"); #endif /* for the node and array of nops elements */ size = sizeof(node_opr)+(nops-1)*sizeof(exp_nodetype*); /* allocate memory */ if ( (p = malloc(size) ) == NULL) yyerror("out of memory"); /* copy information */ p->type = OPR; p->opr.operatr = oper; p->opr.nops = nops; /* handle operands */ #ifdef DEBUG printf("parser.op: has %d args\n",nops); #endif va_start(ap, nops); for ( i = 0; i < nops; i++ ) { p->opr.operand[i] = va_arg(ap, exp_nodetype*); } va_end(ap); return(p); } /* free memory */ static void freenode(exp_nodetype *p) { int i; #ifdef DEBUG printf("parser: free node 1\n"); #endif if ( p == NULL ) return; #ifdef DEBUG printf("parser: free node 2\n"); #endif if ( p->type == OPR) { /* free operands */ #ifdef DEBUG printf("parser: free node 3\n"); #endif for ( i = 0; i < p->opr.nops; i++ ) freenode(p->opr.operand[i]); } #ifdef DEBUG printf("parser: free node 4\n"); #endif free(p); } void yyerror( char *s ) { fprintf(stdout, "%s\n",s); } /* function to evaluate parse treee */ /* input are triangle coordinates and root pf parse tree */ MY_DOUBLE ex( exp_nodetype *p, MY_INT p1 ) { #ifdef DEBUG MY_DOUBLE temp; #endif if ( !p ) return(0); switch( p->type ) { case CCONST: #ifdef DEBUG printf("expression eval const\n"); #endif return(p->constnt.value); case VARI: #ifdef DEBUG printf("expression eval var "); #endif /* check whether x, y or p */ if ( p->var.d == 'x'-'a' ) { #ifdef DEBUG printf("x values %d",p1); temp = Mx(p1,M)*g_xscale-g_xoff; /* convert back to global */ printf("x = "MDF"\n",temp); return(temp); #endif return( Mx(p1,M)*g_xscale-g_xoff ); } else if ( p->var.d == 'y'-'a' ) { #ifdef DEBUG printf("y values "MIF"\n",p1); #endif return( My(p1,M)*g_yscale-g_yoff ); } else return(0); case OPR: switch(p->opr.operatr) { case UMINUS: #ifdef DEBUG printf("expression eval min\n"); #endif return(-ex(p->opr.operand[0],p1)); case SIN: #ifdef DEBUG printf("expression eval sin\n"); #endif return(sin(ex(p->opr.operand[0],p1))); case COS: #ifdef DEBUG printf("expression eval cos\n"); #endif return(cos(ex(p->opr.operand[0],p1))); case LOG: #ifdef DEBUG printf("expression eval log\n"); #endif return(log(ex(p->opr.operand[0],p1))); case STEP: #ifdef DEBUG printf("expression eval step\n"); #endif return((ex(p->opr.operand[0],p1)) > 0); case FABS: #ifdef DEBUG printf("expression eval abs\n"); #endif if ( (ex(p->opr.operand[0],p1)) > 0 ) return(ex(p->opr.operand[0],p1)); else return(-ex(p->opr.operand[0],p1)); case '+': #ifdef DEBUG printf("expression eval +\n"); #endif return(ex(p->opr.operand[0],p1) +ex(p->opr.operand[1],p1)); case '-': #ifdef DEBUG printf("expression eval -\n"); #endif return(ex(p->opr.operand[0],p1) -ex(p->opr.operand[1],p1)); case '*': #ifdef DEBUG printf("expression eval *\n"); #endif return(ex(p->opr.operand[0],p1) *ex(p->opr.operand[1],p1)); case '/': #ifdef DEBUG printf("expression eval /\n"); #endif return(ex(p->opr.operand[0],p1) /ex(p->opr.operand[1],p1)); case '^': #ifdef DEBUG printf("expression eval ^\n"); #endif return(pow(ex(p->opr.operand[0],p1) ,ex(p->opr.operand[1],p1))); case ';': #ifdef DEBUG printf("expression eval ;\n"); #endif ex(p->opr.operand[0],p1); return(ex(p->opr.operand[1],p1)); default: printf("ex: error1\n"); } default: printf("ex: error2\n"); } return(0); }