C:/Users/Dennis/src/lang/bertrand/BERTRAND/bertrand/parse.c

Go to the documentation of this file.
00001 /***********************************************************************
00002  *
00003  * Attributed Operator Precedence Parser
00004  *
00005  ***********************************************************************/
00006 
00007 #include "def.h"
00008 
00009 /* types of nodes on parse stack */
00010 #define OPER_TYPE  401          /* a lone operator */
00011 #define EXPR_TYPE  402          /* a complete expression */
00012 
00013 /* which part of rule are we parsing? */
00014 #define HEAD       501          /* head of rule */
00015 #define BODY       502          /* body of rule */
00016 
00017 static SNODE *pstack = NULL;            /* (top of) parse stack */
00018 
00019 static NODE *boe;               /* beginning of expression */
00020 
00021 static int next_token;          /* next token (for lookahead) */
00022 static int token;               /* token identifier returned from scanner.c */
00023 extern double token_val;        /* numeric value of token, from scanner.c */
00024 extern char token_prval[];      /* print value of token, from scanner.c */
00025 extern OP *token_op;            /* oper ptr from scanner.c */
00026 static NAME_NODE *rule_names = NULL;    /* local names for this rule */
00027 
00028 /***********************************************************************
00029  *
00030  * Print a parse stack. (for debugging)
00031  *
00032  ***********************************************************************/
00033 void
00034 ps_print(st)
00035 SNODE *st;
00036 {
00037 void expr_print();              /* from expr.c */
00038 
00039 while(st) {
00040     if (st->info == OPER_TYPE) fprintf(stderr, "\tOP: %s\n", st->node->op->pname);
00041     else {
00042         fprintf(stderr, "\t");
00043         expr_print(st->node);
00044         fprintf(stderr, "\n");
00045         }
00046     st = st->next;
00047     }
00048 }
00049 
00050 /***********************************************************************
00051  *
00052  * Reduce the parse stack by creating a subtree of an operator and its
00053  * operand(s), popping them off the parse tree and replacing them by
00054  * a pointer to the operator (root of subtree).
00055  * An expression is enclosed by BOE and EOE "outfix operators".
00056  * These will cause the entire expression to reduce properly.
00057  *
00058  * entry:       operator node to be reduced
00059  *
00060  * exit:        top of parse stack is updated
00061  *
00062  ***********************************************************************/
00063 void
00064 reduce(rop)
00065 register SNODE *rop;    /* operator (on parse stack) to be reduced */
00066 {
00067 extern OP *undeclared_prim;     /* from primitive.c */
00068 char *arity_name();             /* from ops.c */
00069 void st_free();                 /* from util.c */
00070 extern int label_count;         /* from rules.c */
00071 
00072 SNODE *q;                       /* temp parse stack pointer */
00073 
00074 #ifdef DEBUG
00075 fprintf(stderr, "reducing operator: %s, parse stack:\n", rop->node->op->pname);
00076 ps_print(pstack);
00077 #endif
00078 
00079 /* handle special parser reduce functions */
00080 if (rop->node->op->eval < 0) {
00081 #   ifdef DEBUG
00082     fprintf(stderr, "special reduce function: %d\n", rop->node->op->eval);
00083 #   endif
00084     switch(- rop->node->op->eval) {
00085      case 1:    /* throw away operator, typically for "()" */
00086         if (!(rop->node->op->arity & UNARY)) {  /* only works for unary */
00087             fprintf(stderr, "operator: %s, arity: %s\n",
00088                 rop->node->op->pname, arity_name(rop->node->op->arity));
00089             error("special reduce function 1 requires unary operator");
00090             }
00091         if (rop == pstack || pstack->info != EXPR_TYPE) {
00092             fprintf(stderr, "unary operator: %s\n", rop->node->op->pname);
00093             error("unary operator has no argument");
00094             }
00095         pstack->next = pstack->next->next;      /* delete rop */
00096         st_free(rop);
00097         break;
00098      case 2:    /* label operator, typically for ":" */
00099         if (!(rop->node->op->arity & BINARY)) {
00100             fprintf(stderr, "operator: %s, arity: %s\n",
00101                 rop->node->op->pname, arity_name(rop->node->op->arity));
00102             error("special label operator must be binary operator");
00103             }
00104         if (rop == pstack || pstack->info != EXPR_TYPE) {
00105             fprintf(stderr, "binary operator: %s\n", rop->node->op->pname);
00106             error("binary operator has no right argument");
00107             }
00108         if (!rop->next || rop->next->info != EXPR_TYPE) {
00109             fprintf(stderr, "binary operator: %s\n", rop->node->op->pname);
00110             error("binary operator has no left argument");
00111             }
00112         if (!(rop->next->node->op->arity == OP_NAME)) {
00113             fprintf(stderr, "operator: %s, arity: %s\n",
00114                 rop->next->node->op->pname,
00115                 arity_name(rop->next->node->op->arity));
00116             error("special label operator requires name for left argument");
00117             }
00118         if (rop->next->node->op != undeclared_prim) {
00119             fprintf(stderr, "parameter: %s\n",
00120                 ((NAME_NODE *)rop->next->node)->pval);
00121             error("parameter may not be used as a label name");
00122             }
00123         if (!(pstack->node->op->arity & OP_TERM)) {
00124             fprintf(stderr, "right argument is: %s, of type: %s\n",
00125                 arity_name(pstack->node->op->arity),  pstack->node->op->pname);
00126             error("special label operator requires term for right argument");
00127             }
00128         if (((TERM_NODE *)(pstack->node))->label) {
00129             /* eventually should allow multiple labels */
00130             fprintf(stderr, "new label: %s, old label: %s, operator: %s\n",
00131                 ((NAME_NODE *)(rop->next->node))->pval,
00132                 ((TERM_NODE *)(pstack->node))->label->pval,
00133                 pstack->node->op->pname);
00134             error("multiple labels on single expression");
00135             }
00136         label_count++;          /* number of label names in a rule */
00137         ((TERM_NODE *)(pstack->node))->label = (NAME_NODE *) rop->next->node;
00138         pstack->next = pstack->next->next->next;        /* delete : and name */
00139         st_free(rop->next);
00140         st_free(rop);
00141         break;
00142      case 3:            /* negate a constant */
00143         if (!(rop->node->op->arity & UNARY)) {  /* only works for unary */
00144             fprintf(stderr, "operator: %s, arity: %s\n",
00145                 rop->node->op->pname, arity_name(rop->node->op->arity));
00146             error("special negation operator must be unary operator");
00147             }
00148         if (rop == pstack || pstack->info != EXPR_TYPE) {
00149             fprintf(stderr, "unary operator: %s\n", rop->node->op->pname);
00150             error("unary operator has no argument");
00151             }
00152         if (!(pstack->node->op->arity & OP_NUM)) {
00153             fprintf(stderr, "right argument is: %s, of type: %s\n",
00154                 arity_name(pstack->node->op->arity),  pstack->node->op->pname);
00155             error("special negation operator requires constant for argument");
00156             }
00157         ((NUM_NODE *)(pstack->node))->value *= -1;
00158         pstack->next = pstack->next->next;      /* delete rop */
00159         st_free(rop);
00160         break;
00161      case 4:    /* don't evaluate (typically []) */
00162         break;  /* implemented at run time */
00163      case 5:    /* simplify expression completely */
00164         break;  /* implemented at run time */
00165      default:
00166         fprintf(stderr,"operator: %s, function: %d\n",
00167             rop->node->op->pname, rop->node->op->eval);
00168         error("unknown parser reduce function");
00169         break;
00170         }       /* end switch */
00171 #   ifdef DEBUG
00172     fprintf(stderr, "result expr is: ");
00173     expr_print(pstack->node);
00174     fprintf(stderr, "\n");
00175 #   endif
00176     }   /* end of special parser reduce functions */
00177 
00178 /* After the expression has been reduced, pop all of the terminal nodes on
00179    the stack and replace with a pointer to the top node in the subtree. */
00180 
00181 /* binary infix operator */
00182 else if (rop->node->op->arity & BINARY) {
00183     if (rop == pstack || pstack->info != EXPR_TYPE) {
00184         fprintf(stderr, "binary operator: %s\n", rop->node->op->pname);
00185         error("binary operator has no right argument");
00186         }
00187     if (!rop->next || rop->next->info != EXPR_TYPE) {
00188         fprintf(stderr, "binary operator: %s\n", rop->node->op->pname);
00189         error("binary operator has no left argument");
00190         }
00191     ((TERM_NODE *)(rop->node))->right = pstack->node;
00192     ((TERM_NODE *)(rop->node))->left = rop->next->node;
00193 #   ifdef DEBUG
00194     fprintf(stderr, "reduce BINARY\n");
00195     fprintf(stderr, "right child is: %s\n",
00196         ((TERM_NODE *)(rop->node))->right->op->pname);
00197     fprintf(stderr, "left child is: %s\n",
00198         ((TERM_NODE *)(rop->node))->left->op->pname);
00199 #   endif
00200     rop->info = EXPR_TYPE;
00201     st_free(pstack);    /* free right child parse stack node */
00202     pstack = rop;
00203     q = rop->next;
00204     rop->next = rop->next->next;        /* pop expr nodes, leave oper node */
00205     st_free(q);         /* free left child parse stack node */
00206     }
00207 
00208 /* unary prefix operator */
00209 else if (rop->node->op->arity == PREFIX) {
00210     if (rop == pstack || pstack->info != EXPR_TYPE) {
00211         fprintf(stderr, "prefix operator: %s\n", rop->node->op->pname);
00212         error("prefix operator has no argument");
00213         }
00214     ((TERM_NODE *)(rop->node))->left = NULL;
00215     ((TERM_NODE *)(rop->node))->right = pstack->node;
00216 #   ifdef DEBUG
00217     fprintf(stderr, "reduce PREFIX\n");
00218     fprintf(stderr, "right child is: %s\n",
00219         ((TERM_NODE *)(rop->node))->right->op->pname);
00220 #   endif    
00221     st_free(pstack);    /* free right child parse stack node */
00222     pstack = rop;               /* pop off top node */
00223     rop->info = EXPR_TYPE;
00224     }
00225 
00226 /* unary postfix operator */
00227 else if (rop->node->op->arity == POSTFIX) {
00228     if (!rop->next || rop->next->info != EXPR_TYPE) {
00229         fprintf(stderr, "postfix operator: %s\n", rop->node->op->pname);
00230         error("postfix operator has no left argument");
00231         }
00232     ((TERM_NODE *)(rop->node))->left = rop->next->node;
00233     ((TERM_NODE *)(rop->node))->right = NULL;
00234 #   ifdef DEBUG
00235     fprintf(stderr, "reduce POSTFIX\n");
00236     fprintf(stderr, "left child is: %s\n",
00237         ((TERM_NODE *)(rop->node))->left->op->pname);
00238 #   endif    
00239     rop->info = EXPR_TYPE;
00240     q = rop->next;
00241     rop->next = rop->next->next;        /* remove next-to-top node */
00242     st_free(q);         /* free left child parse stack node */
00243     }
00244 
00245 /* If we have found the outfix1 oper which matches an input outfix2 oper,
00246    do a special reduce. */
00247 
00248 /* unary outfix (matchfix) operator */
00249 else if (rop->node->op->arity == OUTFIX1) {
00250     if (rop == pstack || pstack->info != EXPR_TYPE) {
00251         fprintf(stderr, "outfix operator: %s\n", rop->node->op->pname);
00252         error("outfix operator has no argument");
00253         }
00254     ((TERM_NODE *)(rop->node))->left = NULL;
00255     ((TERM_NODE *)(rop->node))->right = pstack->node;
00256 #   ifdef DEBUG
00257     fprintf(stderr, "OUTFIX1\n");
00258     fprintf(stderr, "right child is: %s\n",
00259         ((TERM_NODE *)(rop->node))->right->op->pname);
00260 #   endif
00261     rop->info = EXPR_TYPE;
00262     st_free(pstack);            /* free right child parse stack node */
00263     pstack = rop;
00264     }
00265 else {  /* unknown type of operator */
00266     fprintf(stderr, "can't reduce %s, arity: %s\n", rop->node->op,
00267         arity_name(rop->node->op->arity));
00268     error("Don't know how to reduce");
00269     }
00270 
00271 #ifdef DEBUG
00272 fprintf(stderr, "leaving reduce with parse stack:\n");
00273 ps_print(pstack);
00274 #endif
00275 
00276 }
00277 
00278 /***********************************************************************
00279  *
00280  * Shift an expression, or an operator onto the parse stack.
00281  *
00282  * entry:       pointer to node
00283  *              type of node
00284  *
00285  ***********************************************************************/
00286 void
00287 shift(p, type)
00288 NODE *p;
00289 int type;
00290 {
00291 void expr_print();      /* from expr.c */
00292 register SNODE *temp;
00293 SNODE *st_get();        /* from util.c */
00294 
00295 #ifdef DEBUG
00296 if (type==OPER_TYPE) fprintf(stderr, "shifting operator %s onto pstack\n",
00297         p->op->pname);
00298 else if (type==EXPR_TYPE) {
00299         fprintf(stderr, "shifting expression onto pstack: ");
00300         expr_print(p);
00301         fprintf(stderr, "\n");
00302         }
00303 else fprintf(stderr, "shifting unknown %s onto pstack\n",
00304         p->op->pname);
00305 #endif
00306 
00307 temp = st_get();
00308 temp->next = pstack;    /* push onto parse stack */
00309 pstack = temp;
00310 pstack->node = p;       /* assign pointer to expression tree node */
00311 pstack->info = type;    /* assign type of node */
00312 }
00313 
00314 /***********************************************************************
00315  *
00316  * Expression parser: called by parser to parse head, body or type of
00317  * rule.  Read from file and call scanner to get tokens; build 
00318  * expression tree.
00319  *
00320  * entry:       flag indicating whether this is the head, body or type
00321  *              first token read 
00322  *
00323  * exit:        return pointer to top of expression tree
00324  *
00325  ***********************************************************************/
00326 NODE *
00327 exp_parse(part)
00328 int part;               /* parsing HEAD or BODY of rule */
00329 {
00330 register NODE *cnode;   /* current expression node */
00331 register SNODE *lop;    /* last operator type node on parse stack */
00332 int done = FALSE;       /* true if complete expression has been parsed */
00333 char prev_prval[MAXTOKEN];      /* saved previous token_prval */
00334 int holdtoken = TRUE;   /* true if next token has been read */
00335 NAME_NODE *cspace;      /* current name space */
00336 
00337 void st_free();         /* from util.c */
00338 char *char_copy();      /* from util.c */
00339 NODE *node_new();       /* from expr.c */
00340 NODE *name_put();       /* from names.c */
00341 extern OP *pnum_prim;   /* positive constants, from primitive.c */
00342 extern OP *znum_prim;   /* the constant zero, from primitive.c */
00343 extern OP *nnum_prim;   /* negative constants, from primitive.c */
00344 extern OP *str_prim;    /* string constants, from primitive.c */
00345 extern OP *undeclared_prim;     /* from primitive.c */
00346 extern OP *untyped_prim;        /* from primitive.c */
00347 extern NAME_NODE *global_names; /* from names.c */
00348 
00349 #ifdef DEBUG
00350 if (part==HEAD) fprintf(stderr, "parsing HEAD\n");
00351 else if (part==BODY) fprintf(stderr, "parsing BODY\n");
00352 else fprintf(stderr, "parsing unknown = %d\n", part);
00353 
00354 if (pstack) fprintf(stderr, "nodes left on parse stack!\n");
00355 #endif
00356 
00357 pstack = NULL;          /* reinitialize */
00358 
00359 /* Push a beginning-of-expression oper onto the parse stack. */
00360 shift(boe, OPER_TYPE);  
00361 
00362 while (!done) {
00363     if (holdtoken) {
00364 #       ifdef DEBUG
00365         fprintf(stderr, "holdtoken is true, using next_token = %s\n", token_prval);
00366 #       endif 
00367         token = next_token;     /* prev token -> current token */
00368         holdtoken = FALSE;      /* reset */
00369         }
00370     else {
00371         token = scan();
00372 #       ifdef DEBUG
00373         fprintf(stderr, "called scanner, token = %s\n", token_prval);
00374         if (token == OPER) fprintf(stderr, "OPER precedence = %ld\n",
00375                 token_op->precedence);
00376 #       endif 
00377         }
00378 
00379     switch(token) {
00380      case EOF: error("EOF encountered before end of expression");
00381         break;
00382      case '{':  /* end of head expression */
00383         if (part == HEAD) done = TRUE;
00384         else error("Opening brace found in body of rule");
00385         break;
00386      case '}':  /* end of body expression */
00387         if (part == BODY) done = TRUE;
00388         else error("Closing brace found, but not in body of rule");
00389         break;
00390      case IDENT:        /* identifier, put in name space */
00391         /* an identifier must follow an operator */
00392         if (pstack->info != OPER_TYPE) {
00393             fprintf(stderr, "for tokens: ");
00394             expr_print(pstack->node);
00395             fprintf(stderr, " and %s\n", token_prval);
00396             error("missing operator");
00397             }
00398         strcpy(prev_prval, token_prval);        /* save token_prval */
00399         next_token = scan();                    /* look ahead */
00400 #       ifdef DEBUG
00401         fprintf(stderr, "lookahead next_token = %s\n", token_prval);
00402 #       endif
00403         if (part == HEAD) {     /* must be a parameter */
00404             if (next_token == '.') {
00405                 fprintf(stderr, "name beginning with: %s\n", prev_prval);
00406                 error("qualified names illegal in head of rule");
00407                 }
00408             if (next_token == TYPE) {
00409                 cnode = name_put(prev_prval, rule_names, token_op);
00410                 }
00411             else {
00412                 cnode = name_put(prev_prval, rule_names, untyped_prim);
00413                 holdtoken = TRUE;
00414                 }
00415             if (((NAME_NODE *) cnode)->refs != 2) {
00416                 fprintf(stderr, "parameter: %s\n", prev_prval);
00417                 error("reuse of parameter name in head of rule");
00418                 }
00419             shift(cnode, EXPR_TYPE);    /* shift as expression */
00420             break;
00421             }
00422 
00423         /* if we get here, then we must be in the body of the rule */
00424         if (next_token == TYPE) {
00425             fprintf(stderr, "ident: %s, type: %s\n", prev_prval, token_prval);
00426             error("types not allowed in body of rule");
00427             }
00428 
00429         /* insert name into local name space */
00430         cspace = rule_names;
00431         while (next_token == '.') {
00432             cspace = (NAME_NODE *) name_put(prev_prval, cspace, undeclared_prim);
00433             next_token = scan();        /* look ahead for ident */
00434             if (next_token != IDENT) {  
00435                 if (next_token == OPER)
00436                     fprintf(stderr, "token: %s is an operator\n", token_prval);
00437                 else fprintf(stderr, "token: %s\n", token_prval);
00438                 error("expected identifier following '.'");
00439                 }
00440             strcpy(prev_prval, token_prval);
00441             next_token = scan();        /* look ahead for '.' */
00442             }   /* end of qualified name */
00443         holdtoken = TRUE;
00444         cnode = name_put(prev_prval, cspace, undeclared_prim);
00445         shift(cnode, EXPR_TYPE);        /* shift as expression */
00446         break;
00447 
00448      case '.':  /* global variable */
00449         if (part == HEAD) {
00450             fprintf(stderr, "token: %s\n", token_prval);
00451             error("global names illegal in head of rule");
00452             }
00453         /* an identifier must follow an operator */
00454         if (pstack->info != OPER_TYPE) {
00455             fprintf(stderr, "for tokens: ");
00456             expr_print(pstack->node);
00457             fprintf(stderr, " and %s\n", token_prval);
00458             error("missing operator");
00459             }
00460         cspace = global_names;
00461         while (next_token == '.') {
00462             cspace = (NAME_NODE *) name_put(prev_prval, cspace, undeclared_prim);
00463             next_token = scan();        /* look ahead for ident */
00464             if (next_token != IDENT) {
00465                 if (next_token == OPER)
00466                     fprintf(stderr, "token: %s is an operator\n", token_prval);
00467                 else fprintf(stderr, "token: %s\n", token_prval);
00468                 error("expected identifier following '.'");
00469                 }
00470             strcpy(prev_prval, token_prval);
00471             next_token = scan();        /* look ahead for '.' */
00472             }   /* end of global name */
00473         holdtoken = TRUE;
00474         cnode = name_put(prev_prval, cspace, undeclared_prim);
00475         shift(cnode, EXPR_TYPE);        /* shift as expression */
00476         break;
00477 
00478      case NUMBER: 
00479 #       ifdef DEBUG
00480         fprintf(stderr, "type is number\n");
00481 #       endif
00482         cnode = node_new();
00483         cnode->op = (token_val > 0.0) ? pnum_prim :
00484             ((token_val < 0.0) ? nnum_prim : znum_prim );
00485         ((NUM_NODE *) cnode)->value = token_val;
00486         if (pstack->info != OPER_TYPE) {
00487             fprintf(stderr, "for tokens: ");
00488             expr_print(pstack->node);
00489             fprintf(stderr, " and %s\n", token_prval);
00490             error("missing operator");
00491             }
00492         shift(cnode, EXPR_TYPE);        /* shift onto parse stack */
00493         break;
00494 
00495      case STRING:       
00496 #       ifdef DEBUG
00497         fprintf(stderr, "type is string\n");
00498 #       endif
00499         cnode = node_new();
00500         cnode->op = str_prim;   /* constant oper for strings */
00501         ((STR_NODE *) cnode)->value = char_copy(token_prval);
00502         if (pstack->info != OPER_TYPE) {
00503             fprintf(stderr, "for tokens: ");
00504             expr_print(pstack->node);
00505             fprintf(stderr, " and %s\n", token_prval);
00506             error("missing operator");
00507             }
00508         shift(cnode, EXPR_TYPE);        /* shift onto parse stack */
00509         break;
00510 
00511      case OPER:
00512 #       ifdef DEBUG
00513         fprintf(stderr, "type of %s is oper\n", token_prval);
00514 #       endif
00515 
00516         cnode = node_new();             /* to hold this operator */
00517         cnode->op = token_op;           /* oper ptr from scanner */
00518         ((TERM_NODE *) cnode)->label = (NAME_NODE *) NULL;
00519         ((TERM_NODE *) cnode)->left = (NODE *) NULL;
00520         ((TERM_NODE *) cnode)->right = (NODE *) NULL;
00521             
00522         if (cnode->op->arity == NULLARY) {      /* is expression */
00523             shift(cnode, EXPR_TYPE);
00524             break;
00525             }
00526 
00527         if (cnode->op->arity == OUTFIX1 || cnode->op->arity == PREFIX) {
00528             shift(cnode, OPER_TYPE);
00529             break;
00530             }
00531 
00532         /* Keep reducing stack if input operator has lower precedence than 
00533            top operator in stack (or if it has equal precedence and is
00534            left associative.  */
00535 
00536         for (;;) {              /* for ever */
00537 
00538             /* the top or next node on the stack must be an operator */
00539             lop = pstack;
00540             if (lop && lop->info != OPER_TYPE) lop = lop->next;
00541             if (!lop || lop->info != OPER_TYPE)
00542                 error("syntax error: missing operator!");
00543         
00544             /* if there is an infix operator on top of the parse stack,
00545                 and the current operator is also infix,
00546                 then one of them must be convertable to unary
00547                 (an infix operator contains a link to a unary
00548                 operator of the same name in the "other" field),
00549                 or else there is an error. */
00550 
00551             if (lop == pstack && (lop->node->op->arity & BINARY) && 
00552                 cnode->op->arity & BINARY) {
00553 
00554                 /* first check if cnode could be prefix */
00555                 if (cnode->op->other && cnode->op->other->arity == PREFIX) {
00556                     /* could lop also be postfix? */
00557                     if (lop->node->op->other &&
00558                         lop->node->op->other->arity == POSTFIX) {
00559                         /* They both can be converted to unary.
00560                            Pick the one with the higher precedence.
00561                            If equal precedence, shift. */
00562 
00563                         if (lop->node->op->precedence > cnode->op->precedence) {
00564                             lop->node->op = lop->node->op->other;
00565 #                           ifdef DEBUG
00566                             fprintf(stderr, "switching last binary node to unary\n");
00567                             fprintf(stderr, "calling reduce\n");
00568 #                           endif
00569                             reduce(lop);
00570                             }
00571                         else {
00572                             cnode->op = cnode->op->other;       /* to unary */
00573 #                           ifdef DEBUG
00574                             fprintf(stderr, "switching current binary node to unary\n");
00575                             fprintf(stderr, "breaking out and shifting\n");
00576 #                           endif
00577                             break;
00578                             }
00579                         }
00580                     else {      /* only cnode can be converted to unary */
00581                         cnode->op = cnode->op->other;   /* to unary */
00582 #                       ifdef DEBUG
00583                         fprintf(stderr, "switching current binary node to unary\n");
00584                         fprintf(stderr, "breaking out and shifting\n");
00585 #                       endif
00586                         break;
00587                         }
00588                     }
00589                 /* cnode could not be unary, can lop? */
00590                 else if (lop->node->op->other &&
00591                     lop->node->op->other->arity == POSTFIX) {
00592 #                   ifdef DEBUG
00593                     fprintf(stderr, "switching last binary node to unary\n");
00594                     fprintf(stderr, "calling reduce\n");
00595 #                   endif
00596                     reduce(lop);
00597                     }
00598                 else {  /* neither can be converted to unary */
00599                     fprintf(stderr, "operator: %s and operator: %s\n",
00600                         lop->node->op->pname, cnode->op->pname);
00601                     error("syntax error: missing operand");
00602                     }
00603                 }       /* end of two infix operators on top of stack */
00604 
00605             /* if the current operator is binary infix, and there is a
00606                 prefix or outfix1 operator on top of the parse stack,
00607                 see if the current operator can be changed to unary */
00608 
00609             if (cnode->op->arity & BINARY && lop == pstack && (lop->node->op->arity
00610                 == PREFIX || lop->node->op->arity == OUTFIX1)) {
00611                 if (cnode->op->other && cnode->op->other->arity == PREFIX) {
00612                     cnode->op = cnode->op->other;       /* to unary */
00613 #                   ifdef DEBUG
00614                     fprintf(stderr, "switching current binary node to unary\n");
00615                     fprintf(stderr, "breaking out and shifting\n");
00616 #                   endif
00617                     break;
00618                     }
00619                 else {
00620                     fprintf(stderr, "infix operator: %s\n", cnode->op->pname);
00621                     error("syntax error: missing left operand");
00622                     }
00623                 }
00624 
00625             /* If node is an outfix2 operator, reduce the stack
00626                to the matching outfix1 operator.  */
00627 
00628             if (cnode->op->arity == OUTFIX2) {
00629                 if (lop->node->op->arity == OUTFIX1) {
00630                     if (cnode->op->other == lop->node->op) {
00631                         reduce(lop);
00632                         break;
00633                         }
00634                     else {
00635                         fprintf(stderr, "outfix operators: %s and %s\n",
00636                             lop->node->op->pname, cnode->op->pname);
00637                         error("outfix operators do not match");
00638                         }
00639                     }   /* if outfix1 */
00640                 else reduce(lop);
00641                 }
00642 
00643             /* Otherwise, check for precedence. */
00644 
00645             else if (cnode->op->precedence < lop->node->op->precedence ||
00646                 (cnode->op->precedence == lop->node->op->precedence &&
00647                 cnode->op->arity == LEFT)) {
00648 #               ifdef DEBUG
00649                 fprintf(stderr, "calling reduce from <= prec\n");
00650 #               endif
00651                 reduce(lop);
00652                 }
00653 
00654             else if (lop->node->op->arity != OUTFIX1 &&
00655                 (cnode->op->precedence==lop->node->op->precedence) &&
00656                 (cnode->op->arity == NONASSOC)) {
00657                 fprintf(stderr, "input = %s\n", cnode->op->pname);
00658                 fprintf(stderr, "pstack node = %s\n", lop->node->op->pname);
00659                 error("2 opers to be reduced are nonassociative");
00660                 }
00661 
00662             else {
00663 #               ifdef DEBUG
00664                 fprintf(stderr, "breaking out because none of the if's apply\n");
00665 #               endif
00666                 break;
00667                 }
00668 
00669             }   /* end of forever */
00670 
00671         /* finally, shift operator onto parse stack */
00672         if (cnode->op->arity != OUTFIX2) shift(cnode, OPER_TYPE);     
00673 
00674         break;
00675 
00676      case TYPE:
00677         fprintf(stderr,"type: %s\n", token_prval);
00678         if (part == BODY) error("types not allowed in body of rule");
00679         else error("type with no parameter");
00680 
00681      default:                           /* reserved character */
00682         fprintf(stderr,"token: %s\n", token_prval);
00683         error("illegal token in rule");
00684 
00685         }               /* end switch */
00686 
00687 #   ifdef DEBUG
00688     fprintf(stderr, "\n");
00689 #   endif
00690     }   /* end of do until done (end of expression) */
00691 
00692 #ifdef DEBUG
00693 ps_print(pstack);
00694 #endif
00695 
00696 /* have encountered end of expression, reduce everything */
00697 for (lop = pstack; lop; lop = lop->next) {
00698     if (lop->info == OPER_TYPE) {
00699         if (lop->node == boe) break;    /* found bottom of parse stack */
00700         else {
00701             reduce(lop);        /* reduce this operator */
00702             lop = pstack;       /* start from the top */
00703             }
00704         }
00705     }
00706 if (!lop) error("empty parse stack!");
00707 if (lop->next) error("nodes left on parse stack!");
00708 st_free(lop);   /* free boe parse stack node */
00709 cnode = pstack->node;   /* save expression */
00710 st_free(pstack);
00711 pstack = (SNODE *) NULL;
00712 return(cnode);
00713 }
00714 
00715 /***********************************************************************
00716  *
00717  * Parse rules into heads, bodies and types and send each to the
00718  * expression parser.  When a rule has been parsed, send its head,
00719  * body and type to a routine to build the rule.
00720  *
00721  * exit:        entire program parsed
00722  *
00723  ***********************************************************************/
00724 void parse()
00725 {
00726 RULE *rule_build();             /* from rules.c */
00727 NODE *node_new();               /* from expr.c */
00728 OP *op_new();                   /* from ops.c */
00729 void st_mem_free();             /* from util.c */
00730 extern int label_count;         /* from rules.c */
00731 extern OP *undeclared_prim;     /* from primitive.c */
00732 
00733 NODE *head;             /* pointer to root of head's expression tree */
00734 NODE *body;             /* pointer to root of body's expression tree */
00735 OP *rule_tag;           /* pointer to root of tag's expression tree */
00736 
00737 pstack = NULL;          /* parse stack is empty */
00738 
00739 /* initialize boe psuedo operator */
00740 boe = node_new();
00741 boe->op = op_new(3);
00742 strcpy(boe->op->pname,"BOE");
00743 boe->op->arity = OUTFIX1;
00744 boe->op->other = (OP *) NULL;   /* no operator matches boe */
00745 ((TERM_NODE *) boe)->label = (NAME_NODE *) NULL;
00746 ((TERM_NODE *) boe)->left = (NODE *) NULL;
00747 ((TERM_NODE *) boe)->right = (NODE *) NULL;
00748 
00749 for (next_token = scan(); EOF != next_token; ) {
00750     /* initialize namespace for local and parameter names */
00751     rule_names = (NAME_NODE *) node_new();
00752     rule_names->op = undeclared_prim;
00753     rule_names->next = (NAME_NODE *) NULL;
00754     rule_names->parent = (NAME_NODE *) NULL;
00755     rule_names->child = (NAME_NODE *) NULL;
00756     rule_names->pval = NULL;
00757     rule_names->refs = 1;
00758     rule_names->interest = 0;
00759     label_count = 0;            /* number of label names in rule */
00760 
00761     head = exp_parse(HEAD);             /* parse HEAD of rule */
00762     next_token = scan();
00763     if (next_token == EOF) error("EOF encountered before end of rule");
00764     body = exp_parse(BODY);             /* parse BODY of rule */
00765 
00766     next_token = scan();
00767     if (next_token == TYPE) {   /* optional tag */
00768         rule_tag = token_op;
00769         next_token = scan();
00770         }
00771     else {
00772         rule_tag = (OP *) NULL;
00773         }
00774     rule_build(head, body, rule_tag, rule_names);
00775     }   /* for all rules in the input */
00776 st_mem_free();          /* free all parse stack memory */
00777 }

Generated on Fri Jan 25 09:58:43 2008 for Bertrand by  doxygen 1.5.4