#include #include #include #include using namespace std; struct Branch { int nextT; int nextF; }; typedef vector< string > TOKENS; typedef vector< Branch > FLOW; struct Program { TOKENS p; FLOW f; int pc; int num; int countPaths(int line) { //cerr << "in count paths: " << line << endl; if (p[line]=="halt" || p[line]=="halt.") return 1; if (f[line].nextF == 0) return countPaths(f[line].nextT); return countPaths(f[line].nextT)+countPaths(f[line].nextF); } bool checkSyntax() { num = p.size()-1; f.resize(num); for (int i=0; i for the while token " << pc << endl; return false; } if (!isBlock1()) { cout << "expecting an open { for the while token " << pc << endl; return false; } if (p[pc]=="}") { cout << "expecting statement for the while token " << pc << endl; return false; } int tpc2; while (p[pc]!="}" && pc < num) { tpc2 = pc; if ( !isStatement() ) return false; if (f[tpc2].nextT==0) f[tpc2].nextT = pc; } if (!isBlock2()) { cout << "expecting a close } for the while token " << pc << endl; return false; } f[tpc2].nextT = tpc; // last statement of while jumps back to while if (f[tpc].nextF==0) f[tpc].nextF = pc+1; return isSemi(); } bool isIf() { int tpc = pc; assert(p[pc]=="if"); pc++; if (!isTest()) { cout << "expecting a for the if token " << pc << endl; return false; } if (!isBlock1()) { cout << "expecting an open { for the if token " << pc << endl; return false; } assert (p[pc]!="|" && p[pc]!="}"); // at least one statement f[tpc].nextT = pc; int tpc2; while (p[pc]!="|" && p[pc]!="}" && pc < num) { tpc2 = pc; if ( !isStatement() ) return false; if (f[tpc2].nextT==0) f[tpc2].nextT = pc; } if (p[pc]=="|") { pc++; f[tpc].nextF = pc; assert (p[pc]!="}"); // at least one statement after | while (p[pc]!="}" && pc < num) { int tpc = pc; if ( !isStatement() ) return false; if (f[tpc].nextT==0) f[tpc].nextT = pc; } f[tpc2].nextT = pc+2; // true block jumps past false block } if (!isBlock2()) { cout << "expecting a close } for the while token " << pc << endl; return false; } if (f[tpc].nextF==0) f[tpc].nextF = pc+1; return isSemi(); } bool isTest() { if (!isOpenP()) return false; if (!isVar()) { cout << "expecting a variable as first argument of test token " << pc << endl; return false; } if (!isRelop()) { cout << "expecting a relational operator for test token " << pc << endl; return false; } if (!isConst()) { cout << "expecting a const as second argument of test token " << pc << endl; return false; } if (!isClosedP()) return false; return true; } bool isSemi() { if ( p[pc]!=";" ) { cout << "expecting a ; at token " << pc << endl; return false; } pc++; return true; } bool isBlock1() { if ( p[pc]!="{" ) { cout << "expecting a { at token " << pc << endl; return false; } pc++; return true; } bool isBlock2() { if ( p[pc]!="}" ) { cout << "expecting a } at token " << pc << endl; return false; } pc++; return true; } bool isOpenP() { if ( p[pc]!="(" ) { cout << "expecting a ( at token " << pc << endl; return false; } pc++; return true; } bool isClosedP() { if ( p[pc]!=")" ) { cout << "expecting a ) at token " << pc << endl; return false; } pc++; return true; } bool isVar() { if (p[pc].length()!=1 || p[pc]<"a" || p[pc]>"z") { cout << "expecting a variable at token " << pc << endl; return false; } pc++; return true; } bool isMexpr() { if ( !isTerm() ) { cout << "expecting a term at token " << pc << endl; return false; } if ( isMoper() ) return isTerm(); else return true; // single term Mexpr; } bool isTerm() { return (isConst() || isVar()); } bool isConst() { for (int i=0; i=0 && t<=255) { pc++; return true; } elese return false; } bool isMoper() { if ( (p[pc]=="+") || (p[pc]=="*") || (p[pc]=="-") || (p[pc]=="/") ) { pc++; return true; } else return false; } bool isRelop() { if ( (p[pc]=="==") || (p[pc]=="!=") || (p[pc]=="<") || (p[pc]==">") ) { pc++; return true; } else return false; } }; istream& operator>>(istream& in, Program& P) { string s; P.p.resize(0); in >> s; //cout << "read: " << s << endl; while (s[0] != '#') { P.p.push_back(s); in >> s; //cout << "read: " << s << endl; } P.p.push_back(s); // add input termination marker for convienence. return in; } ostream& operator<<(ostream& out, const TOKENS& t) { for (int i=0; i> P; // cout << P; if (P.p.size()==1) break; // empty program if (P.checkSyntax()) ; // cout << "syntax okay\n"; // cout << P.f; cout << P.countPaths(0) << endl; } while (P.p[P.p.size()-1] != "##"); }