Department of Computer Science | Institute of Theoretical Computer Science | CADMO

Theory of Combinatorial Algorithms

Prof. Emo Welzl and Prof. Bernd Gärtner

// Programm: calc-simple.C // Parser fuer einfache arithmetische Ausdruecke. // Benutzt folgende kontextfreie Grammatik: // add_expr: number add_expr_aux // add_expr_aux: '+' number add_expr_aux // '-' number add_expr_aux // epsilon // // number: digit digits // // digits: digit digits // epsilon // // digit: '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9' #include #include #include #include // Parse-Functionen fuer die Nichtterminale: // ----------------------------------------- // Zu jedem Nichtterminal N der Grammatik gibt es genau eine Funktion // desselben Namens, die folgende Pre- und Postconditions hat: // // PRE: [b,e) ist ein gueltiger range. // POST: Wenn sich ein Praefix P=[b,f) der durch den range [b,e) // beschriebenen Zeichenfolge aus dem Nichtterminal N ableiten laesst, // so ist b==f und Rueckgabewert ist der numerische Wert des durch P // beschriebenen arithmetischen Ausdrucks. Andernfalls wirft die // Funktion eine exception vom Typ std::invalid_argument. // Zahlentyp fuer alle Berechnungen typedef int NT; // Iteratortyp fuer alle Funktionen typedef std::string::const_iterator SSCI; NT digit(SSCI& b, SSCI e) // PRE: b ist dereferenzierbar. { return *(b++) - '0'; } NT digits(SSCI& b, SSCI e, const NT& left_op) { if (b == e || !std::isdigit(*b)) return left_op; NT val = left_op * 10 + digit(b, e); return digits(b, e, val); } NT number(SSCI& b, SSCI e) { if (b == e || !std::isdigit(*b)) throw std::invalid_argument("digit expected."); NT val = digit(b, e); return digits(b, e, val); } NT add_expr_aux(SSCI& b, SSCI e, const NT& left_op) { if (b == e) return left_op; if (*b == '+') { NT right_op = number(++b, e); return add_expr_aux(b, e, left_op + right_op); } if (*b == '-') { NT right_op = number(++b, e); return add_expr_aux(b, e, left_op - right_op); } return left_op; } NT add_expr(SSCI& b, SSCI e) { NT value = number(b, e); return add_expr_aux(b, e, value); } int main() { std::cout << "Eingabe: "; std::string input; std::cin >> input; SSCI beg = input.begin(); SSCI end = input.end(); SSCI cur = beg; try { std::cout << add_expr(cur, end) << std::endl; if (cur != end) throw std::invalid_argument("Unexpected character."); } catch (std::invalid_argument err) { std::cerr << "Parse error: " << err.what() << "\n" << std::string(beg, cur) << "|-here->" << std::string(cur, end) << std::endl; return 1; } return 0; }