// Massingill, Berna L. and Oldham, Jeffrey D. // 2000 Mar 29 // CS1321 // Tautology checker. // Input: // // A boolean expression, read from standard input (terminated by // EOF), in postfix notation. Terms are separated by whitespace, // and each term is either an operator (&&, ||, !, =>, or ==), a // constant (true or false), or a variable name (anything other // than an operator or a constant). // // A boolean expression falls into one of three categories: // A tautology (well-formed, and true for all possible assignments // of true/false values to variables). // Not a tautology (well-formed, but false for at least one // assignment of true/false values to variables). // Not well-formed. // // Output: // // A message to standard output indicating whether the input // expression is a tautology, not a tautology, or not well-formed. #include #include // has assert() #include // has EXIT_SUCCESS, EXIT_FAILURE #include #include #include // ADD CODE HERE? typedef vector expr; typedef pair twobools; // An instance of this class represents a boolean expression in // reverse Polish notation, together with an assignment of values // to variables. class ExpressionSubstitution { public: // typedef vector expr; ExpressionSubstitution(istream& in) { // Read the expression. string next; while (in >> next) e.push_back(next); // Prepare initial variable values. findVariables(); noMoreValues = false; return; } // Reset to first assignment of values to variables. void reset(void) { resetVariables(); noMoreValues = false; return; } // Obtain the "next" expression generated by assigning values to // all variables in the original expression. Repeated calls to // this function cycle through all possible assignments of values // to variables, returning true as long as there are more possible // assignments, false if all have been used. bool getNext(expr & subst) { if (noMoreValues) return false; subst.clear(); for (expr::const_iterator ePos = e.begin(); ePos != e.end(); ++ePos) if (isKeyword(*ePos)) subst.push_back(*ePos); else { assert(a.find(*ePos) != a.end()); subst.push_back((a.find(*ePos))->second ? "true" : "false"); } // Set up for next call. noMoreValues = !nextAssignment(); return true; } // Determine whether token is a keyword (operator or constant). static bool isKeyword(const string & s) { return (s == "&&" || s == "||" || s == "!" || s == "=>" || s == "==" || s == "true" || s == "false"); } private: expr e; // expression with variables typedef map assignment; assignment a; bool noMoreValues; // Create map from variables in e -- variables are keywords, values // are all initially false. void findVariables(void) { for (expr::const_iterator ePos = e.begin(); ePos != e.end(); ++ePos) if (!isKeyword(*ePos)) a[(*ePos)] = false; return; } // Reset map to initial values. void resetVariables(void) { for (assignment::iterator aPos = a.begin(); aPos != a.end(); ++aPos) aPos->second = false; } // Generate next assignment. Treat sequence of values as a binary // number, and add one. Returns true if there is one (no overflow), // false if not. bool nextAssignment(void) { bool carry = true; for (assignment::iterator aPos = a.begin(); aPos != a.end() && carry; ++aPos) if (aPos->second == false) { aPos->second = true; carry = false; } else { aPos->second = false; carry = true; } return carry == false; } }; // ---- Function prototypes. ---- twobools evaluate(const expr & e); // ADD CODE HERE? // ---- Main program. ---- int main(void) { cout << "Enter the expression to evaluate " "(multiple lines okay, control-D to end):\n"; ExpressionSubstitution e(cin); // construct expression from input twobools evalResult = twobools(true,true); // result of evaluating expression -- // first bool is well-formedness, // second is expression's value. expr eWithValues; // Evaluate expression for all possible assignments, stopping // if one returns a false result or a not-well-formed result. // (Member function getNext() cycles through possible assignments, // returning false when there are no more.) while (evalResult.first && evalResult.second && e.getNext(eWithValues)) evalResult = evaluate(eWithValues); if (!evalResult.first) cout << "Input expression is not well-formed.\n"; else if (!evalResult.second) cout << "Input expression is not a tautology.\n"; else cout << "Input expression is a tautology.\n"; return EXIT_SUCCESS; } // ---- Function definitions. ---- // ADD CODE HERE. // At a minimum you will need to provide a function definition // for the evaluate() function whose prototype appears in the // "Function prototypes" section above.