Presentation is loading. Please wait.

Presentation is loading. Please wait.

CSE 3341/655; Part 3 35 This is all very wrong! What would the SW1/SW2 (RESOLVE) people say if they saw this? Problem: Lack of data abstraction; What would.

Similar presentations


Presentation on theme: "CSE 3341/655; Part 3 35 This is all very wrong! What would the SW1/SW2 (RESOLVE) people say if they saw this? Problem: Lack of data abstraction; What would."— Presentation transcript:

1 CSE 3341/655; Part 3 35 This is all very wrong! What would the SW1/SW2 (RESOLVE) people say if they saw this? Problem: Lack of data abstraction; What would happen if we changed the PT rep? We need a ParseTree class! Key point: Parser, Printer, Executor should not know the internals of the PT class Recursive Descent (contd)

2 CSE 3341/655; Part 3 36 What are the ParseTree operations? First: Need -- not just a ParseTree object, but a cursor to track where we are in PT Some ParseTree operations: int currNTNo(); // non-term. at current node int currAlt(); // Alternative no. used at current node void goDownLB(); // move cursor to left child void goDownMB(); //move cursor to second child void goDownRB(); //move cursor to third child ParseTree class

3 CSE 3341/655; Part 3 37 How do we go back up? void goUP(); // move cursor to parent node ParseTree class

4 CSE 3341/655; Part 3 38 void PrintIf(ParseTree& p) { write( “if” ); p.goDownLB(); PrintCond(p); p.goUp(); p.goDownMB(); PrintSS(p); // bug! p.goUp(); x = p.currAlt(); if (x == 2) then { p.goDownRB(); write (“else”); PrintSS(p); }; write(“end ;”); } // Bug! Recursive Descent

5 CSE 3341/655; Part 3 39 We didn’t see how the ParseTree is represented or what a node looks like - e.g.: how do we “go back up”? That is the point of data abstraction! You could use an array rep or pointers or whatever you like; the client (Parser/Printer/Executor) will be unaffected! ParseTree class

6 CSE 3341/655; Part 3 40 Need some more operations: If non-term at current node is, need its name, value etc. int currIdVal(); // error if we are not at node void setIdVal(int x); string idName(); void ExecAssign(ParseTree p) { p.goDownMB(); x = EvalExp(p); p.goUp(); p.goDownLB(); p.setIdVal(x); } // Bug! ParseTree class (contd.)

7 CSE 3341/655; Part 3 41 Problem: What about the parser? Key point: The parser adds nodes Hence: Need more operations Assumption: Calling procedure will create an “empty” node, set the cursor to that node, then call the appropriate parse procedure. ParseTree class

8 CSE 3341/655; Part 3 42 void ParseAssign(ParseTree& p) { p.setNTNo(7); p.setAltNo(1); // why? p.createLB(); p.createMB(); p.goDownLB(); ParseId(p); p.skipToken(); // why? and why p.skipToken? p.goUp(); p.goDownMB(); ParseExp(p); p.skipToken(); p.goUp; } Parsing

9 CSE 3341/655; Part 3 43 That is better than the original version but...... is not object-oriented. Object-oriented: Treat each node as a separate, independent object. Have a separate class for each non-terminal Each stmt. is an instance of the If class; each an instance of the Exp class;... Object-oriented?

10 CSE 3341/655; Part 3 44 class Prog { private: DS* ds; SS* ss; public: Prog() { ds = nil; ss = nil; } PrintProg() { write(“program”); ds →PrintDS(); write(“begin”); ss →PrintSS(); print(“end”); } ExecProg() { ds →ExecDS(); ss →ExecSS(); } // not quite Object-oriented approach (contd)

11 CSE 3341/655; Part 3 45 class Prog{ private: DS* ds; SS* ss; public: Prog() { ds = nil; ss = nil; } ParseProg() { skipToken(); // error check? ds = new DS(); ds →ParseDS(); ss = new SS(); ss→ParseSS(); // bug! skipToken(); skipToken();} Object-oriented approach (contd)

12 CSE 3341/655; Part 3 46 class If{ private: Cond* c; SS* ss1; SS* ss2; // why? public: If() { c = nil; ss1 = nil; ss1 = nil; } ParseIf() { int tokNo; skipToken(); // why? c = new Cond(); c →ParseCond(); skipToken(); ss1 = new SS(); ss1→ParseSS(); tokNo=getToken(); if (tokNo==“end”) {skipToken(); skipToken(); return; } skipToken(); // error check? ss2 = new SS(); ss2→ParseSS();..skip tokens.. } Object-oriented approach (contd)

13 CSE 3341/655; Part 3 47 class If{ // contd. Print If() { write(“if ”); c →PrintCond(); write(“then”); ss1 →PrintSS();... how to check alt. no?...... } // Each class can use its own approach ExecIf() { if ( c →EvalCond()) then { ss1 →ExecSS(); return;} if (!ss2) { ss2 →ExecSS();} } Object-oriented approach (contd)

14 CSE 3341/655; Part 3 48 class Stmt{ private: int altNo; Assign* s1; IF* s2; Loop* s3; Input* s4; Output* s5; public: Stmt() { altNo=0; s1 = nil;... } parseStmt() { int tokNo; tokNo = tok.getToken(); if (tokNo==...) { altNo=1; s1= new Assign(); s1->parseAssign();} if (tokNo==...) { altNo=2; s2= new IF(); s1->parseIF();} if (tokNo==...) { altNo=3; s3= new Loop(); s1->parseLoop();} if (tokNo==...) { altNo=4; s4= new Input(); s1->parseInput();} if (tokNo==...){altNo=5;s5= new Output(); s1->parseOutput();}} printStmt() { if (altNo==1) {s1->printAssign(); return; }... } execStmt() { if (altNo==1) {s1->execAssign(); return; }... } Object-oriented approach (contd)

15 CSE 3341/655; Part 3 49 Id class poses some problems: Need to make sure that two occurrences of same Id are not treated as two objects: class Assign { Id* id; Exp* exp; ParseAssign() { id = new Id(); id →Parse I d(); // Won’t Work! Need to check if the id in question already exists; and create a new one only if it does not. Solution: Make ParseId() a static method which will decide whether to create a new Id object Problem with Id class

16 50 class Assign { Id* id; Exp* exp;// nothing new here ParseAssign() { id = Id:: Parse I d(); // ParseAssign does not create a new // Id object since this Id object may already exist exp = new Exp(); exp  ParseExp();... // nothing new}... Static methods such as ParseId -- also called "class methods" Can be used even if we don't have an instance of the class But: in their bodies *cannot* refer to the normal member variables of the class! (why not?); they can only refer to static variables Problem with Id class (contd) CSE 3341/655; Part 3

17 51 class Id { string name; int val; bool declared; bool initialized; static Id* eIds[20]; // pointers to existing Id’s; *static* var static int idCount = 0; // also static Id(string n) { // *private* constructor! name = n; declared = false; initialized = false; } public: static Id* ParseId() { // get token; check if name matches eIds[k] →name for // any k = 0,..., idCount-1; if yes, return e Ids[k]; // if not: Id* nId = new Id(n1);...add to eIds[]... return nId; } int getIdVal() {return val; // check initialized first? setIdVal()? getIdName()?... Problem with Id class (contd) CSE 3341/655; Part 3

18 52 C++ needs special syntax for dealing with static variables: class Id { static Id* eIds[20]; static int idCount = 0; That is wrong -- you can't initialize in the header More generally, these are *declarations*; you also need defs; so change above to: static Id* eIds[]; static int idCount; Then outside the class: Id*Id::eIds[20]; // this is the def & allocates space int Id::idCount = 0; // this is the def & allocates space C++ : complications with static variables CSE 3341/655; Part 3

19 53 We have a number of parse procedures: ParseProg(), ParseDS(), ParseDecl(), ParseSS() etc. Each will need to use the tokenizer How to ensure there is only one? If you are using the ParseTree class approach: Include a tokenizer object as part of the parseTree object; and have ParseTree class provide methods, getToken(), skipToken(), etc. These methods will simply call the corresponding methods of Tokenizer class on the tokenizer object Tokenizer details...

20 CSE 3341/655; Part 3 54 If you are using the "OO" approach: We have a number of parse procedures: ParseProg(), ParseDS(), ParseDecl(), ParseSS() etc. Each will need to use the tokenizer How to ensure there is only one? Possible answers: Global variable Pass a single tokenizer around as a parameter Singleton pattern Tokenizer details (contd.)

21 CSE 3341/655; Part 3 55 Idea: Make constructor private (or protected); Have a local static variable (initialized to null) to hold a reference to the single instance; Provide a method Instance() that returns that class C { private: static C* instance = null; C(){ } // private constructor public: static C* Instance(){ //bit like ParseId() if (instance == 0) {instance = new C();} return instance; }... }; Singleton class

22 CSE 3341/655; Part 3 56 Scope of a variable/object: In which parts of the program do we have access to it? Life-time: When does the object come into existence and when does it go out of existence? Scope vs. Life-time


Download ppt "CSE 3341/655; Part 3 35 This is all very wrong! What would the SW1/SW2 (RESOLVE) people say if they saw this? Problem: Lack of data abstraction; What would."

Similar presentations


Ads by Google