Presentation is loading. Please wait.

Presentation is loading. Please wait.

CMPE 152: Compiler Design September 13 Class Meeting

Similar presentations


Presentation on theme: "CMPE 152: Compiler Design September 13 Class Meeting"— Presentation transcript:

1 CMPE 152: Compiler Design September 13 Class Meeting
Department of Computer Engineering San Jose State University Fall 2018 Instructor: Ron Mak

2 Quick Review of the Framework
Chapter 7 Quick Review of the Framework FROM: TO: Next topic: Parsing control statements, and generating parse trees.

3 CASE Statement Example:
CASE i+1 OF 1: j := i; 4: j := 4*i; 5, 2, 3: j := 523*i; END Note that Pascal’s CASE statement does not use BREAK statements.

4 CASE Statement, cont’d Example:
CASE i+1 OF 1: j := i; 4: j := 4*i; 5, 2, 3: j := 523*i; END

5 Pascal Syntax Checker II: CASE
Demo. ./Chapter7cpp compile -i case.txt ./Chapter7cpp compile -i caseerrors.txt

6 Top Down Recursive Descent Parsing
The term is very descriptive of how the parser works. Start by parsing the topmost source language construct. For now it’s a statement. Later, it will be the program.

7 Top Down Recursive Descent Parsing
“Drill down” (descend) by parsing the sub-constructs. statement →assignment statement → expression →variable → etc. Use recursion on the way down. statement →WHILE statement → statement → etc.

8 Top Down Recursive Descent Parsing, cont’d
This is the technique for hand-coded parsers. Very easy to understand and write. The source language grammar is encoded in the structure of the parser code. Close correspondence between the parser code and the syntax diagrams. Disadvantages Can be tedious coding. Ad hoc error handling. Big and slow!

9 Top Down Recursive Descent Parsing, cont’d
Bottom-up parsers can be smaller and faster. Error handling can still be tricky. To be covered later this semester.

10 Chapter 8 Syntax and Semantics Syntax refers to the grammar rules of a source language. The rules prescribe the proper form of its programs. Rules can be described by syntax diagrams. Syntax checking: Does this sequence of tokens follow the syntax rules?

11 Syntax and Semantics, cont’d
Semantics refers to the meaning of the token sequences according to the source language. Example: Certain sequences of tokens constitute an IF statement according to the syntax rules. The semantics of the statement determine How the interpreter will execute the statement, or How the compiler will generate object code for the statement.

12 Syntax and Semantics, cont’d
Semantic actions by the front end parser: Building symbol tables. Type checking (which we’ll do later). Building proper parse trees. The parse trees encode type checking and operator precedence in their structures. Semantic actions by the back end: Interpreter: The executor runs the program. Compiler: The code generator emits object code.

13 Interpreter Design Recall the design of our interpreter in the back end:

14 Control Statement Executor Classes
New StatementExecutor subclasses: LoopExecutor IfExecutor SelectExecutor The execute() method of each of these new subclasses executes the parse tree whose root node is passed to it. Each returns null. Only the execute() method of ExpressionExecutor returns a value.

15 Executing a LOOP Parse Tree
Pascal REPEAT loop Pascal WHILE loop Note that we have the flexibility in the LOOP tree to have the TEST child be a middle child. Pascal FOR loop

16 Executing a LOOP Parse Tree, cont'd
Get all the children of the LOOP node. Repeatedly execute all the child subtrees in order. If a child is a TEST node, evaluate the node’s relational expression subtree. If the expression value is true, break out of the loop. If the expression value is false, continue executing the child statement subtrees.

17 Executing a LOOP Parse Tree, cont’d
bool exit_loop = false; ICodeNode *expr_node = nullptr; vector<ICodeNode *> loop_children = node->get_children(); ExpressionExecutor expression_executor(this); StatementExecutor statement_executor(this); while (!exit_loop) {     ++execution_count;  // count the loop statement itself     for (ICodeNode *child : loop_children) {         ICodeNodeTypeImpl child_type =                               (ICodeNodeTypeImpl) child->get_type();         if (child_type == NT_TEST)         {             if (expr_node == nullptr)             {                 expr_node = child->get_children()[0];             }             Object data_value = expression_executor.execute(expr_node);             exit_loop = cast(data_value, bool);         }         else             statement_executor.execute(child);         if (exit_loop) break;     } } wci/backend/interpreter/executors/LoopExecutor.cpp Keep looping until exit_loop becomes true. Execute all the subtrees. TEST node: Evaluate the boolean expression and set exitLoop to its value. Statement subtree: Execute it. Break out of the for loop if exitLoop is true.

18 Simple Interpreter II: Loops
Demos ./Chapter8cpp Pascal execute repeat.txt ./Chapter8cpp Pascal execute while.txt ./Chapter8cpp Pascal execute for.txt

19 Executing an IF Parse Tree
Evaluate the first child’s expression subtree. If the expression value is true ... Execute the second child’s statement subtree. If the expression value is false … If there is a third child statement subtree, then execute it. If there isn’t a third child subtree, then we’re done with this tree.

20 Executing an IF Parse Tree, cont'd
wci/backend/interpreter/executors/IfExecutor.cpp Object IfExecutor::execute(ICodeNode *node) {     vector<ICodeNode *> children = node->get_children();     ICodeNode *expr_node = children[0];     ICodeNode *then_stmt_node = children[1];     ICodeNode *else_stmt_node = children.size() > 2 ? children[2] : nullptr;     ExpressionExecutor expression_executor(this);     StatementExecutor statement_executor(this);     Object data_value = expression_executor.execute(expr_node);     if (cast(data_value, bool))     {         statement_executor.execute(then_stmt_node);     }     else if (else_stmt_node != nullptr)         statement_executor.execute(else_stmt_node);     ++execution_count;  // count the IF statement itself     return Object();    // empty } Get the IF node’s two or three children. Execute the boolean expression to determine which statement subtree child to execute next.

21 Simple Interpreter II: IF
Demo ./Chapter8cpp Pascal execute if.txt

22 Executing a SELECT Parse Tree
CASE i+1 OF 1: j := i; 4: j := 4*i; 5, 2, 3: j := 523*i; END Evaluate the first child expression subtree to get the selection value. Examine each SELECT BRANCH subtree. Look for the selection value in the SELECT CONSTANTS list of each SELECT BRANCH. If there is a match, then execute the SELECT BRANCH’s statement subtree. Is this a good way to do it?

23 Executing a SELECT Parse Tree, cont’d
Why is searching for a matching selection value among all the SELECT BRANCHes bad? It’s inefficient. Selection values that appear earlier in the parse tree are found faster. The Pascal programmer should not have to consider the order of the selection values.

24 Executing a SELECT Parse Tree, cont’d
A better solution: For each SELECT tree, create a jump table implemented as a hash table. Build the table from the SELECT parse tree. Each jump table entry contains: Key: A constant selection value. Value: The root node of the corresponding statement subtree.

25 Executing a SELECT Parse Tree, cont’d
During execution, the computed selection value is the key that extracts the corresponding statement subtree to execute.

26 SELECT Jump Table Key: constant selection value
Value: root node of the corresponding statement 1 1 2 1 3 1 4 This is an example of optimization for faster execution. 1 5 CASE i+1 OF 1: j := i; 4: j := 4*i; 5, 2, 3: j := 523*i; END

27 Multiple CASE Statements
If a Pascal source program contains multiple CASE statements, there will be multiple SELECT parse trees. Create a global jump cache, a hash table of jump tables. Each jump cache entry contains: Key : The SELECT node of a SELECT parse tree. Value: The jump table created for that SELECT parse tree.

28 Jump Cache of Jump Tables
1 2 Jump cache 1 2 3 4 5 1 1 1 1 2 3 Jump tables SELECT parse trees Key: SELECT node Value: Corresponding jump table

29 Class SelectExecutor The global jump cache, which contains a jump table for each SELECT tree in the Pascal source program. // Jump cache: entry key is a SELECT node, // entry value is the jump table. // Jump table: entry key is a selection value, // entry value is the branch statement root node. typedef map<int, ICodeNode *> JumpTable; typedef map<ICodeNode *, JumpTable *> JumpCache; wci/backend/interpreter/executors/SelectExecutor.h

30 Class SelectExecutor, cont’d
Object SelectExecutor::execute(ICodeNode *node) {     JumpTable *jump_table = jump_cache[node];     if (jump_table == nullptr)     {         jump_table = create_jump_table(node);         jump_cache[node] = jump_table;     }     vector<ICodeNode *> select_children = node->get_children();     ICodeNode *expr_node = select_children[0];     ExpressionExecutor expression_executor(this);     Object select_value = expression_executor.execute(expr_node);   int key = instanceof(select_value, int)                                     ? cast(select_value, int)                                     : cast(select_value, string)[0];     ICodeNode *statement_node = (*jump_table)[key];     if (statement_node != nullptr)         StatementExecutor statement_executor(this);         statement_executor.execute(statement_node);     ++execution_count;  // count the SELECT statement itself     return Object();    // empty } Get the right jump table from the jump cache. Evaluate the selection value. Get the right statement to execute. Can we eliminate the jump cache? wci/backend/interpreter/executors/SelectExecutor.cpp

31 Simple Interpreter II Demos ./Chapter8cpp execute case.txt


Download ppt "CMPE 152: Compiler Design September 13 Class Meeting"

Similar presentations


Ads by Google