online compiler and debugger for c/c++

code. compile. run. debug. share.
Source Code   
Language
// g++ --std=c++11 expParser.cpp #include <iostream> #include <string> #include <vector> #include <memory> using namespace std; // Utility stuff // Haskell's Maybe template<typename T> class Optional { bool b; T val; public: Optional() : b(false) {} Optional(T v) : val(v), b(true) {} bool isJust() { return b; } bool isNothing() { return !b; } T fromJust() { return val; } }; template<typename T> Optional<T> nothing() { return Optional<T>(); } template<typename T> Optional<T> just(T v) { return Optional<T>(v); } typedef enum { EOS, // End of string ZERO, ONE, TWO, OPEN, CLOSE, PLUS, MULT } Token_t; string showTok(Token_t t) { switch(t) { case EOS: return "EOS"; case ZERO: return "ZERO"; case ONE: return "ONE"; case TWO: return "TWO"; case OPEN: return "OPEN"; case CLOSE: return "CLOSE"; case PLUS: return "PLUS"; case MULT: return "MULT"; } // NOTE: The (clang) compiler is able to figure out that // along all control-flow paths, a return statement will be reached. } class Tokenize { string s; int pos; public: Tokenize(string s) { this->s = s; pos = 0; } // Scan throuh string, letter (symbol) by letter. Token_t next() { if(s.length() <= pos) return EOS; while(1) { if(s.length() <= pos) return EOS; switch(s[pos]) { case '0': pos++; return ZERO; case '1': pos++; return ONE; case '2': pos++; return TWO; case '(': pos++; return OPEN; case ')': pos++; return CLOSE; case '+': pos++; return PLUS; case '*': pos++; return MULT; default: // we simply skip all other symbols ! pos++; break; } } } // next vector<Token_t> scan() { vector<Token_t> v; Token_t t; do { t = next(); v.push_back(t); } while(t != EOS); return v; } // scan string show() { vector<Token_t> v = this->scan(); string s; for(int i=0; i < v.size(); i++) { s += showTok(v[i]); if(i+1 < v.size()) s += ";" ; // Add delimiter } return s; } // show }; // Wrapper class, provide the (current) token. class Tokenizer : Tokenize { public: Token_t token; Tokenizer(string s) : Tokenize(s) { token = next(); } void nextToken() { token = next(); } }; void testTokenize() { // Tokenize t1("1 + (3 * 4)"); { Tokenize t1(" 1 + (0 * 1)"); cout << t1.show() << endl; } { Tokenize t1(""); cout << t1.show() << endl; } } // Exp AST class Exp { public: virtual int eval() = 0; virtual string pretty() = 0; }; class IntExp : public Exp { int val; public: IntExp(int _val) { val = _val; } int eval() { return val;} string pretty() { return to_string(val); } }; class PlusExp : public Exp { std::shared_ptr<Exp> e1; std::shared_ptr<Exp> e2; public: PlusExp(std::shared_ptr<Exp> _e1, std::shared_ptr<Exp> _e2) { e1 = _e1; e2 = _e2; } int eval() { return e1->eval() + e2->eval(); } string pretty() { string s("("); s.append(e1->pretty()); s.append("+"); s.append(e2->pretty()); s.append(")"); return s; } }; class MultExp : public Exp { std::shared_ptr<Exp> e1; std::shared_ptr<Exp> e2; public: MultExp(std::shared_ptr <Exp> _e1, std::shared_ptr<Exp> _e2) { e1 = _e1; e2 = _e2; } int eval() { return e1->eval() * e2->eval(); } string pretty() { string s("("); s.append(e1->pretty()); s.append("*"); s.append(e2->pretty()); s.append(")"); return s; } }; // Short-hands typedef std::shared_ptr<Exp> EXP; EXP newInt(int i) { return std::make_shared<IntExp>(i); } EXP newPlus(EXP l, EXP r) { return std::make_shared<PlusExp>(l,r); } EXP newMult(EXP l, EXP r) { return std::make_shared<MultExp>(l,r); } // Now comes the parser (OO-style) class Parser { Tokenizer t; // E ::= T E' Optional<EXP> parseE() { Optional<EXP> t = parseT(); if(t.isNothing()) return t; return parseE2(t.fromJust()); } // E' ::= + T E' | Optional<EXP> parseE2(EXP left) { if(t.token == PLUS) { t.nextToken(); Optional<EXP> right = parseT(); if(right.isNothing()) return right; return parseE2(newPlus(left, right.fromJust())); } return just<EXP>(left); } // T ::= F T' Optional<EXP> parseT() { Optional<EXP> f = parseF(); if(f.isNothing()) return f; return parseT2(f.fromJust()); } // T' ::= * F T' | Optional<EXP> parseT2(EXP left) { if(t.token == MULT) { t.nextToken(); Optional<EXP> right = parseF(); if(right.isNothing()) return right; return parseT2(newMult(left, right.fromJust())); } return just<EXP>(left); } // F ::= N | (E) Optional<EXP> parseF() { switch(t.token) { case ZERO: t.nextToken(); return just<EXP>(newInt(0)); case ONE: t.nextToken(); return just<EXP>(newInt(1)); case TWO: t.nextToken(); return just<EXP>(newInt(2)); case OPEN: { // introduce new scope t.nextToken(); Optional<EXP> e = parseE(); if(e.isNothing()) return e; if(t.token != CLOSE) return nothing<EXP>(); t.nextToken(); return e; } default: return nothing<EXP>(); } } public: Parser(string s) : t(Tokenizer(s)) { } Optional<EXP> parse() { Optional<EXP> e= parseE(); return e; } }; void display(Optional<EXP> e) { if(e.isNothing()) { cout << "nothing \n"; } else { cout << (e.fromJust())->pretty() << "\n"; } return; } void testParserGood() { /* display(Parser("1").parse()); display(Parser("1 + 0 ").parse()); display(Parser("1 + (0) ").parse()); display(Parser("1 + 2 * 0 ").parse()); display(Parser("1 * 2 + 0 ").parse()); */ display(Parser("(1 + 2) * 0 ").parse()); display(Parser("(1 + 2) * 0 + 2").parse()); display(Parser("(1 + 2) * 0 + 2").parse()); } void testParser() { testParserGood(); } int main() { std::shared_ptr<Exp> e = std::make_shared<IntExp>(5); testParser(); return 1; }
// g++ --std=c++11 expParser.cpp #include <iostream> #include <string> #include <vector> #include <memory> using namespace std; // Utility stuff // Haskell's Maybe template<typename T> class Optional { bool b; T val; public: Optional() : b(false) {} Optional(T v) : val(v), b(true) {} bool isJust() { return b; } bool isNothing() { return !b; } T fromJust() { return val; } }; template<typename T> Optional<T> nothing() { return Optional<T>(); } template<typename T> Optional<T> just(T v) { return Optional<T>(v); } typedef enum { EOS, // End of string ZERO, ONE, TWO, OPEN, CLOSE, PLUS, MULT } Token_t; string showTok(Token_t t) { switch(t) { case EOS: return "EOS"; case ZERO: return "ZERO"; case ONE: return "ONE"; case TWO: return "TWO"; case OPEN: return "OPEN"; case CLOSE: return "CLOSE"; case PLUS: return "PLUS"; case MULT: return "MULT"; } // NOTE: The (clang) compiler is able to figure out that // along all control-flow paths, a return statement will be reached. } class Tokenize { string s; int pos; public: Tokenize(string s) { this->s = s; pos = 0; } // Scan throuh string, letter (symbol) by letter. Token_t next() { if(s.length() <= pos) return EOS; while(1) { if(s.length() <= pos) return EOS; switch(s[pos]) { case '0': pos++; return ZERO; case '1': pos++; return ONE; case '2': pos++; return TWO; case '(': pos++; return OPEN; case ')': pos++; return CLOSE; case '+': pos++; return PLUS; case '*': pos++; return MULT; default: // we simply skip all other symbols ! pos++; break; } } } // next vector<Token_t> scan() { vector<Token_t> v; Token_t t; do { t = next(); v.push_back(t); } while(t != EOS); return v; } // scan string show() { vector<Token_t> v = this->scan(); string s; for(int i=0; i < v.size(); i++) { s += showTok(v[i]); if(i+1 < v.size()) s += ";" ; // Add delimiter } return s; } // show }; // Wrapper class, provide the (current) token. class Tokenizer : Tokenize { public: Token_t token; Tokenizer(string s) : Tokenize(s) { token = next(); } void nextToken() { token = next(); } }; void testTokenize() { // Tokenize t1("1 + (3 * 4)"); { Tokenize t1(" 1 + (0 * 1)"); cout << t1.show() << endl; } { Tokenize t1(""); cout << t1.show() << endl; } } // Exp AST class Exp { public: virtual int eval() = 0; virtual string pretty() = 0; }; class IntExp : public Exp { int val; public: IntExp(int _val) { val = _val; } int eval() { return val;} string pretty() { return to_string(val); } }; class PlusExp : public Exp { std::shared_ptr<Exp> e1; std::shared_ptr<Exp> e2; public: PlusExp(std::shared_ptr<Exp> _e1, std::shared_ptr<Exp> _e2) { e1 = _e1; e2 = _e2; } int eval() { return e1->eval() + e2->eval(); } string pretty() { string s("("); s.append(e1->pretty()); s.append("+"); s.append(e2->pretty()); s.append(")"); return s; } }; class MultExp : public Exp { std::shared_ptr<Exp> e1; std::shared_ptr<Exp> e2; public: MultExp(std::shared_ptr <Exp> _e1, std::shared_ptr<Exp> _e2) { e1 = _e1; e2 = _e2; } int eval() { return e1->eval() * e2->eval(); } string pretty() { string s("("); s.append(e1->pretty()); s.append("*"); s.append(e2->pretty()); s.append(")"); return s; } }; // Short-hands typedef std::shared_ptr<Exp> EXP; EXP newInt(int i) { return std::make_shared<IntExp>(i); } EXP newPlus(EXP l, EXP r) { return std::make_shared<PlusExp>(l,r); } EXP newMult(EXP l, EXP r) { return std::make_shared<MultExp>(l,r); } // Syntax Analyse /* "1 + 2" ===Parsing==> als Object vom Typ "Exp" Grammatikregeln zur Beschreibung der syntaktisch wohlgeformten Ausdruecke. In Mathe Notation. Grammatikregeln = Ersetzungsregeln. E -> 1 E -> 2 E -> E + E 1, 2, + sind Terminalsymbole (atomaren Konstrukte der Programmiersprache) E ist ein Nichtterminalsymbol. In Informatiknotation, wir verwenden EBNF. E := 1 | 2 | E + E | E * E Ziel: Aus obigen Regeln generiere ein Problem, welches ueberpruft ob eine Sequenz bestend aus 1,2 und + ein gueltiger Ausdruck ist, d.h. ableitbar aus E. 1 + 2 * 2 ist dies gueltig? Wir versuchen eine Ableitung zu konstruieren. 1 + 2 * 2 <- E + 2 * 2 <- E + E * 2 (a) <- E * 2 <- E * E <- E (b) <- E + E * E <- E + E < E Interpretation (a) entspricht (1+2)*2 Interpretation (b) entspricht 1 + (2*2) Wir entscheiden uns fuer (b). */ // Now comes the parser (OO-style) // // Top-down parser. // Kann automatisiert werden siehe https://www.antlr.org/ class Parser { Tokenizer t; // E ::= T E' Optional<EXP> parseE() { Optional<EXP> t = parseT(); if(t.isNothing()) return t; return parseE2(t.fromJust()); } // E' ::= + T E' | Optional<EXP> parseE2(EXP left) { if(t.token == PLUS) { t.nextToken(); Optional<EXP> right = parseT(); if(right.isNothing()) return right; return parseE2(newPlus(left, right.fromJust())); } return just<EXP>(left); } // T ::= F T' Optional<EXP> parseT() { Optional<EXP> f = parseF(); if(f.isNothing()) return f; return parseT2(f.fromJust()); } // T' ::= * F T' | Optional<EXP> parseT2(EXP left) { if(t.token == MULT) { t.nextToken(); Optional<EXP> right = parseF(); if(right.isNothing()) return right; return parseT2(newMult(left, right.fromJust())); } return just<EXP>(left); } // F ::= N | (E) Optional<EXP> parseF() { switch(t.token) { case ZERO: t.nextToken(); return just<EXP>(newInt(0)); case ONE: t.nextToken(); return just<EXP>(newInt(1)); case TWO: t.nextToken(); return just<EXP>(newInt(2)); case OPEN: { // introduce new scope t.nextToken(); Optional<EXP> e = parseE(); if(e.isNothing()) return e; if(t.token != CLOSE) return nothing<EXP>(); t.nextToken(); return e; } default: return nothing<EXP>(); } } public: Parser(string s) : t(Tokenizer(s)) { } Optional<EXP> parse() { Optional<EXP> e= parseE(); return e; } }; void display(Optional<EXP> e) { if(e.isNothing()) { cout << "nothing \n"; } else { cout << (e.fromJust())->pretty() << "\n"; } return; } void testParserGood() { /* display(Parser("1").parse()); display(Parser("1 + 0 ").parse()); display(Parser("1 + (0) ").parse()); display(Parser("1 + 2 * 0 ").parse()); display(Parser("1 * 2 + 0 ").parse()); */ display(Parser("(1 + 2) * 0 ").parse()); display(Parser("(1 + 2) * 0 + 2").parse()); display(Parser("(1 + 2) * 0 + 2").parse()); } void testParser() { testParserGood(); } int main() { std::shared_ptr<Exp> e = std::make_shared<IntExp>(5); testParser(); return 1; }

Compiling Program...

Command line arguments:
Standard Input: Interactive Console Text
×

                

                

Program is not being debugged. Click "Debug" button to start program in debug mode.

#FunctionFile:Line
VariableValue
RegisterValue
ExpressionValue