001
23.10.2003, 21:06 Uhr
Pablo
Supertux (Operator)
|
Also ein Parser: (Achtung nicht von mir, aber ich habe das Programm verändert, ist aber zu lang um zu posten, deshalb nur die Basis)
C++: |
#include <iostream> // Ein-/Ausgabe #include <string> // Strings #include <map> // map #include <cctype> // isalpha() usw. #include <sstream>
using namespace std;
enum Token_value { NAME, NUMBER, END, PLUS='+', MINUS='-', MUL='*', DIV='/', PRINT=';', ASSIGN='=', LP='(', RP=')' };
Token_value curr_tok = PRINT;
double term(bool); double prim(bool); double error(const string& s); Token_value get_token(void);
double expr(bool get) // Addieren und Substrahieren { double left = term(get);
for (;;) // "'forver', siehe unten switch (curr_tok) { case PLUS: left += term(true); break; case MINUS: left -= term(true); break; default: return left; } }
double term(bool get) // Multipliziere und dividiere { double left = prim(get);
for (;;) switch (curr_tok) { case MUL: left *= prim(true); break; case DIV: if (double d = prim(true)) { left /= d; break; } return error("Division durch 0."); default: return left; } }
double number_value; string string_value; double expr(bool);
map<string, double> table;
double prim(bool get) // behandelt Primaries { if (get) get_token();
switch (curr_tok) { case NUMBER: // Gleitkommakonstante { double v = number_value; get_token(); return v; } case NAME: { double& v = table[string_value]; if (get_token() == ASSIGN) v = expr(true); return v; } case MINUS: // Einstelliges Minus return -prim(true); case LP: { double e = expr(true); if (curr_tok != RP) return error(") erwartet"); get_token(); // Verschlucke ')' return e; } default: return error("primary erwartet"); } }
Token_value get_token() { char ch; do { // Überspringe Whitespaces außer '\n' if(!cin.get(ch)) return curr_tok = END; } while (ch!='\n' && isspace(ch)); switch (ch) { case 0: case ':': return curr_tok=END; case ';': case '\n': return curr_tok=PRINT; case '*': case '/': case '+': case '-': case '(': case ')': case '=': return curr_tok=Token_value(ch); case ':': return curr_tok=END; //:end oder:exit um das Prog. zu verlassen case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '.': cin.putback(ch); cin >> number_value; return curr_tok=NUMBER; default: // NAME, NAME=, oder Fehler if (isalpha(ch)) { string_value = ch; while (cin.get(ch) && isalnum(ch)) string_value.push_back(ch); cin.putback(ch); return curr_tok=NAME; } error("Falsches Token"); return curr_tok=PRINT; } }
int no_of_errors;
double error(const string& s) { no_of_errors++; cerr << "Fehler: " << s << '\n'; return 1; }
int main() { table["pi"] = 3.1415926535897932385; // Vordefinierte Namen einfügen table["e"] = 2.7182818284590542354;
while (cin) { get_token(); if (curr_tok == END) break; if (curr_tok == PRINT) continue; cout << expr(false) << "\n"; }
return no_of_errors; }
|
Du kannst sogar Variablen definiere, oder 2+4;8+pi; eingeben. -- A! Elbereth Gilthoniel! silivren penna míriel o menel aglar elenath, Gilthoniel, A! Elbereth! Dieser Post wurde am 23.10.2003 um 21:06 Uhr von Pablo Yanez Trujillo editiert. |