/*- *----------------------------------------------------------------------- * CondF -- * Parse a conjunctive factor (nice name, wot?) * F -> T && F | T * * Results: * True, False or Err * * Side Effects: * Tokens are consumed. *----------------------------------------------------------------------- */ static Token CondF(bool doEval) { Token l, o; l = CondT(doEval); if (l != Err) { o = CondToken(doEval); if (o == And) { /* F -> T && F * * If T is False, the whole thing will be False, but we * have to parse the r.h.s. anyway (to throw it away). If * T is True, the result is the r.h.s., be it an Err or no. * */ if (l == True) l = CondF(doEval); else (void)CondF(false); } else /* F -> T. */ condPushBack = o; } return l; }
/*- *----------------------------------------------------------------------- * CondF -- * Parse a conjunctive factor (nice name, wot?) * F -> T && F | T * * Results: * TOK_TRUE, TOK_FALSE or TOK_ERROR * * Side Effects: * Tokens are consumed. * *----------------------------------------------------------------------- */ static Token CondF(Boolean doEval) { Token l, o; l = CondT(doEval); if (l != TOK_ERROR) { o = CondToken(doEval); if (o == TOK_AND) { /* * F -> T && F * * If T is TOK_FALSE, the whole thing will be TOK_FALSE, but we have to * parse the r.h.s. anyway (to throw it away). * If T is TOK_TRUE, the result is the r.h.s., be it an TOK_ERROR or no. */ if (l == TOK_TRUE) { l = CondF(doEval); } else { (void)CondF(FALSE); } } else { /* * F -> T */ CondPushBack(o); } } return (l); }
/*- *----------------------------------------------------------------------- * CondE -- * Main expression production. * E -> F || E | F * * Results: * True, False or Err. * * Side Effects: * Tokens are, of course, consumed. *----------------------------------------------------------------------- */ static Token CondE(bool doEval) { Token l, o; l = CondF(doEval); if (l != Err) { o = CondToken(doEval); if (o == Or) { /* E -> F || E * * A similar thing occurs for ||, except that here we * make sure the l.h.s. is False before we bother to * evaluate the r.h.s. Once again, if l is False, the * result is the r.h.s. and once again if l is True, we * parse the r.h.s. to throw it away. */ if (l == False) l = CondE(doEval); else (void)CondE(false); } else /* E -> F. */ condPushBack = o; } return l; }
/*- *----------------------------------------------------------------------- * CondE -- * Main expression production. * E -> F || E | F * * Results: * TOK_TRUE, TOK_FALSE or TOK_ERROR. * * Side Effects: * Tokens are, of course, consumed. * *----------------------------------------------------------------------- */ static Token CondE(Boolean doEval) { Token l, o; l = CondF(doEval); if (l != TOK_ERROR) { o = CondToken(doEval); if (o == TOK_OR) { /* * E -> F || E * * A similar thing occurs for ||, except that here we make sure * the l.h.s. is TOK_FALSE before we bother to evaluate the r.h.s. * Once again, if l is TOK_FALSE, the result is the r.h.s. and once * again if l is TOK_TRUE, we parse the r.h.s. to throw it away. */ if (l == TOK_FALSE) { l = CondE(doEval); } else { (void)CondE(FALSE); } } else { /* * E -> F */ CondPushBack(o); } } return (l); }