/* * Shift in the next symbol from the input stream * * Return SUCCESS or FAIL */ FUNCTION CODE shift ( struct SYNBLK *sb, struct PSTATE *statelist[], /* in: array of pointers to states */ struct VALUE *value, /* out: value of the primitive */ CODE *symbtype, /* out: type of the primitive */ CODE *lookahead /* out: the peeked-at next symbol */ ) { CODE code; *symbtype= getprim(sb, value); /* get a primary symbol and value */ if (*symbtype == PA_ERROR) /* assume GETPRIM prints error */ return(FAIL); if (*symbtype == PA_ERRFLOW) /* underflow or overflow */ return(PA_ERRFLOW); *lookahead = peekpri(sb); /* look at the next symbol in line */ if (*lookahead == PA_ERROR) code = FAIL; else if (*lookahead == PA_ERRFLOW) code = PA_ERRFLOW; else code = gotostate(statelist, *symbtype); /* fix state stack for next state */ if (code == FAIL || code == PA_ERRFLOW) deal_pval(value, *symbtype); /* deallocate any string */ return(code); }
/* * Parse the line starting at the current syntax block pointer until * end-of-string, using state tables provided by the caller. Trigger any * 'action' routines as indicated by the provided state table. * * Returns PA_SUCC or PA_FAIL or PA_EOS (failure on unexpected EOS) */ FUNCTION CODE parser ( struct SYNBLK *sb, /* in: syntax block */ struct PSTATE *statelist[], /* in: list of state pointers */ FUNINT state0, /* in: index of pointer to start state */ /* (W.R.T. the statelist) */ struct ERRMSG *(*errmsg) /* out: ptr to error msg struct */ ) { CODE code, status; CODE newsymb; /* new language symbol reduced to */ CODE symbtype; CODE lookahead; /* next primitive symbol from input */ struct VALUE value; /* value of primitive from input */ *errmsg = NULL; /* init ptr to error msg */ inivstack(MAX_VAL_NEST); /* initialize value stack */ stk_in(st_stack, MAXSTATE, state0); /* init stack, push state0 */ do { code = shift(sb, statelist, &value, &symbtype, &lookahead); /* do a shift operation */ if (code==FAIL) { if (symbtype==EOS) return(PA_EOS); return(PA_FAIL); } else if (code==PA_ERRFLOW) return(PA_ERRFLOW); if (symbtype==PA_NUM || symbtype==PA_NAME || symbtype==PA_QUOTED || symbtype==PA_NULL) { code = pushvstack(&value); /* if not an operator push the value */ if (code == FAIL) return(PA_FAIL); /* assume user over-nested */ } while ( reduce(statelist, lookahead, &value, &newsymb, &status, errmsg)) /* reduce as much as possible */ { if (status == FAIL) return(PA_FAIL); /* error message set up by action */ if (newsymb == PA_ACCEPT || newsymb == PA_ERROR) break; /* we're done */ code = gotostate(statelist, newsymb); /* fix state stack according to */ /* new symbol */ if (code == FAIL) { tmierr(TMI_XSTATE); /* fatal error: new state undeterminable */ return(PA_FAIL); } } } while( newsymb != PA_ACCEPT && newsymb != PA_ERROR); /* continue until we hit the 'accept' sym */ return(PA_SUCC); }
void reduce(int reduction) /* Completes a reduction */ { struct TOKENREC token1, token2; int counter; switch (reduction) { case 1 : token1 = pop(); pop(); token2 = pop(); curtoken.x.value = token1.x.value + token2.x.value; break; case 2 : token1 = pop(); pop(); token2 = pop(); curtoken.x.value = token2.x.value - token1.x.value; break; case 4 : token1 = pop(); pop(); token2 = pop(); curtoken.x.value = token1.x.value * token2.x.value; break; case 5 : token1 = pop(); pop(); token2 = pop(); if (token1.x.value == 0) curtoken.x.value = HUGE_VAL; else curtoken.x.value = token2.x.value / token1.x.value; break; case 7 : token1 = pop(); pop(); token2 = pop(); curtoken.x.value = pow(token2.x.value, token1.x.value); break; case 9 : token1 = pop(); pop(); curtoken.x.value = -token1.x.value; break; case 11 : token1 = pop(); pop(); token2 = pop(); curtoken.x.value = 0; if (token1.x.c.row == token2.x.c.row) { if (token1.x.c.col < token2.x.c.col) error = TRUE; else { for (counter = token2.x.c.col; counter <= token1.x.c.col; counter++) curtoken.x.value += cellvalue(counter, token1.x.c.row); } } else if (token1.x.c.col == token2.x.c.col) { if (token1.x.c.row < token2.x.c.row) error = TRUE; else { for (counter = token2.x.c.row; counter <= token1.x.c.row; counter++) curtoken.x.value += cellvalue(token1.x.c.col, counter); } } else error = TRUE; break; case 13 : curtoken = pop(); curtoken.x.value = cellvalue(curtoken.x.c.col, curtoken.x.c.row); break; case 14 : pop(); curtoken = pop(); pop(); break; case 16 : pop(); curtoken = pop(); pop(); token1 = pop(); if (strcmp(token1.x.funcname, "ABS") == 0) curtoken.x.value = fabs(curtoken.x.value); else if (strcmp(token1.x.funcname, "ACOS") == 0) curtoken.x.value = acos(curtoken.x.value); else if (strcmp(token1.x.funcname, "ASIN") == 0) curtoken.x.value = asin(curtoken.x.value); else if (strcmp(token1.x.funcname, "ATAN") == 0) curtoken.x.value = atan(curtoken.x.value); else if (strcmp(token1.x.funcname, "COSH") == 0) curtoken.x.value = cosh(curtoken.x.value); else if (strcmp(token1.x.funcname, "COS") == 0) curtoken.x.value = cos(curtoken.x.value); else if (strcmp(token1.x.funcname, "EXP") == 0) curtoken.x.value = exp(curtoken.x.value); else if (strcmp(token1.x.funcname, "LOG10") == 0) curtoken.x.value = log10(curtoken.x.value); else if (strcmp(token1.x.funcname, "LOG") == 0) curtoken.x.value = log(curtoken.x.value); else if (strcmp(token1.x.funcname, "ROUND") == 0) curtoken.x.value = (int)(curtoken.x.value + 0.5); else if (strcmp(token1.x.funcname, "POW10") == 0) curtoken.x.value = pow10(curtoken.x.value); else if (strcmp(token1.x.funcname, "SINH") == 0) curtoken.x.value = sinh(curtoken.x.value); else if (strcmp(token1.x.funcname, "SIN") == 0) curtoken.x.value = sin(curtoken.x.value); else if (strcmp(token1.x.funcname, "SQRT") == 0) curtoken.x.value = sqrt(curtoken.x.value); else if (strcmp(token1.x.funcname, "SQR") == 0) curtoken.x.value *= curtoken.x.value; else if (strcmp(token1.x.funcname, "TANH") == 0) curtoken.x.value = tanh(curtoken.x.value); else if (strcmp(token1.x.funcname, "TAN") == 0) curtoken.x.value = tan(curtoken.x.value); else if (strcmp(token1.x.funcname, "TRUNC") == 0) curtoken.x.value = (int)curtoken.x.value; break; case 3 : case 6 : case 8 : case 10 : case 12 : case 15 : curtoken = pop(); break; } /* switch */ curtoken.state = gotostate(reduction); push(&curtoken); } /* reduce */