CSE 109 Test 1 Monday 17 November 2004 >>>>>>>>>>>>>>>>>>>>>>SUGGESTED ANSWERS<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 1. Assume the lexical analyzer from assignments p5-p8. Assume a language whose programs consist of zero or more lines of code, followed by a line with "END", where each line has one of the forms: READ WRITE ++ -- Write a program that parses (determines syntactical correctness of) programs entered at the console (keyboard). The program should simply respond by stating whether the program is correct. Hint: Identifiers cannot be declared, so only one pass is needed. ========================================================================= class Parser {public: Parser():lex(){} void parse(); private: Lex lex; static void check(bool b, char * mess); }; void main() {Parser p; p.parse(); } void Parser::parse() {int tok,savetok; tok=lex.next(); while(tok!=Lex::END) {switch(tok) {case Lex::WRITE: case Lex::READ: tok=lex.next(); check(tok==Lex::IDENT,"Identifier expected"); break; case Lex::IDENT: savetok=lex.next(); check(savetok==Lex::SPLUS || savetok==Lex::SMINUS, " '+' or '-' expected"); tok=lex.next(); check(tok==savetok," '++' or '--' expected"); break; default: check(false," WRITE, READ, or Identifier expected"); } tok=lex.next(); check(tok=Lex::ENDOFLINE,"Junk at end of line"); lex.newLine(); tok=lex.next(); } cout<<"\nThe parse succeeded\n"; } void Parser::check(bool b, char *mess) {if(!b) {cerr<<"ERROR: "<, >=, ==, and !=. Write a class Lex for this language. Lex should read input from the console (keyboard) and write no output. Instances of Lex should skip over blanks, tabs, and linefeeds. Given Lex lx;, calls to lx.next() should return 0 for 0, 1 for 1, 2 for <, 3 for <=, 4 for >, 5 for >=, 6 for ==, 7 for != and 8 for anything else. ========================================================================= #include class Lex {public: static const int ZERO=0, ONE=1, LT=2, LTE=3, GT=4, GTE=5, EQ=6, NE=7, JUNK=8; Lex(){cin.get(ch);} int next(); private: char ch; void getch(); int oneChar(int one); int twoChar(int one,int two); }; void Lex::getch() {while(cin.good() && (ch==' ' || ch=='\t' || ch=='\n')) cin.get(ch); } int Lex::oneChar(int op) {cin.get(ch); return op; } int Lex::twoChar(int one,int two) {cin.get(ch); if(ch!='=') return one; cin.get(ch); return two; } int Lex::next() {getch(); switch(ch) {case '0': return oneChar(ZERO); case '1': return oneChar(ONE); case '<': return twoChar(LT,LTE); case '>': return twoChar(GT,GTE); case '=': return twoChar(JUNK,EQ); case '!': return twoChar(JUNK,NE); default: cin.get(ch); return JUNK; } } //<<<<<<<<<<<[A]--------------------------------------------> ^ | ^ | | | | | +-[A]<--(+)<--+ +--[A]<--(-)<---+ A -------------->(0)-----------+ | | +------>(1)---------->| | v +-->(*)-->[S]--(/)----------> =========================================================== #include void S(char &ch); void A(char &ch); void check(bool b, char *mess); int main() {char ch; cin.get(ch); S(ch); check(ch=='\n',"End of line expected\n"); cout<<"The syntax is okay\n"; } void S(char &ch) {A(ch); while(ch=='+') {cin.get(ch); A(ch); } while(ch=='-') {cin.get(ch); A(ch); } } void A(char &ch) {switch(ch) {case '*': cin.get(ch); S(ch); check(ch=='/', " '/' expected"); case '0': case '1': cin.get(ch); break; default: check(false," *, 0, or 1 expected"); } } void check(bool b,char *mess) {if(!b) {cerr<<"ERROR: "<