Presentation is loading. Please wait.

Presentation is loading. Please wait.

CMPE 152: Compiler Design February 12 Class Meeting

Similar presentations


Presentation on theme: "CMPE 152: Compiler Design February 12 Class Meeting"— Presentation transcript:

1 CMPE 152: Compiler Design February 12 Class Meeting
Department of Computer Engineering San Jose State University Spring 2019 Instructor: Ron Mak

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

3 Pascal Statement Syntax Diagrams

4 Pascal Statement Syntax Diagrams, cont’d
For now, greatly simplified!

5 Parse Tree: Conceptual Design
More accurately called an abstract syntax tree (AST). BEGIN alpha := -88; beta := 99; result := alpha + 3/(beta – gamma) + 5 END

6 Parse Tree: Conceptual Design
At the conceptual design level, we don’t care how we implement the tree. This should remind you of how we first designed the symbol table.

7 Parse Tree: Basic Tree Operations
Create a new node. Create a copy of a node. Set and get the root node of a parse tree. Set and get an attribute value in a node. Add a child node to a node. Get the list of a node’s child nodes. Get a node’s parent node.

8 Intermediate Code Interfaces
Goal: Keep it source language-independent.

9 Intermediate Code Implementations

10 An Intermediate Code Factory Class
wci/intermediate/ICodeFactory.cpp ICode *ICodeFactory::create_icode() {     return new ICodeImpl(); } ICodeNode *ICodeFactory::create_icode_node(const ICodeNodeType type)     return new ICodeNodeImpl(type);

11 Coding to the Interfaces (Again)
    // Create the ASSIGN node.     ICodeNode *assign_node =             ICodeFactory::create_icode_node((ICodeNodeType) NT_ASSIGN); ...     // Create the variable node and set its name attribute.     ICodeNode *variable_node =             ICodeFactory::create_icode_node(                              (ICodeNodeType) NT_VARIABLE);     // The ASSIGN node adopts the variable node as its first child.     assign_node->add_child(variable_node); wci/frontend/pascal/parsers/AssignmentStatementParser.cpp

12 Intermediate Code (ICode) Node Types
enum class ICodeNodeTypeImpl {     // Program structure     PROGRAM, PROCEDURE, FUNCTION,     // Statements     COMPOUND, ASSIGN, LOOP, TEST, CALL, PARAMETERS,     IF, SELECT, SELECT_BRANCH, SELECT_CONSTANTS, NO_OP,     // Relational operators     EQ, NE, LT, LE, GT, GE, NOT,     // Additive operators     ADD, SUBTRACT, OR, NEGATE,     // Multiplicative operators     MULTIPLY, INTEGER_DIVIDE, FLOAT_DIVIDE, MOD, AND,     // Operands     VARIABLE, SUBSCRIPTS, FIELD,     INTEGER_CONSTANT, REAL_CONSTANT,     STRING_CONSTANT, BOOLEAN_CONSTANT,     // WRITE parameter     WRITE_PARM, }; Do not confuse node types (ASSIGN, ADD, etc.) with data types (integer, real, etc.). We use the enumerated type ICodeNodeTypeImpl for node types which is different from the enumerated type PascalTokenType to help maintain source language independence. wci/intermediate/icodeimpl/ICodeNodeImpl.h

13 Intermediate Code Node Implementation
class ICodeNodeImpl : public ICodeNode { ... private:     ICodeNodeType type;            // node type     ICodeNode *parent;             // node's parent     vector<ICodeNode *> children;  // node's children     map<ICodeKey, Object> contents; } wci/intermediate/icodeimpl/ICodeNodeImpl.h Each node has an vector<ICodeNode *> of child nodes. Each node has a map<ICodeKey, Object> for the node contents.

14 A Parent Node Adopts a Child Node
ICodeNode *ICodeNodeImpl::add_child(ICodeNode *node) {     if (node != nullptr)     {         children.push_back(node);         ((ICodeNodeImpl *) node)->parent = this;     }     return node; } wci/intermediate/icodeimpl/ICodeNodeImpl.cpp When a parent node adds a child node, we can say that the parent node “adopts” the child node. Keep the parse tree implementation simple!

15 What Attributes to Store in a Node?
public enum ICodeKeyImpl implements ICodeKey { LINE, ID, VALUE; } wci.intermediate.icodeimpl.ICodeNodeImpl.h Not much! Not every node will have these attributes. LINE: statement line number ID: symbol table entry of an identifier VALUE: data value Most of the information about what got parsed is encoded in the node type and in the tree structure.

16 Statement Parser Class
Class StatementParser is a subclass of PascalParserTD which is a subclass of Parser. Its parse() method builds a part of the parse tree and returns the root node of the newly built subtree.

17 Statement Parser Subclasses
StatementParser itself has subclasses: CompoundStatement-Parser AssignmentStatement-Parser ExpressionParser The parse() method of each subclass returns the root node of the subtree that it builds. Note the dependency relationships among StatementParser and its subclasses.

18 Building a Parse Tree Each parse() method builds a subtree and returns the root node of the new subtree. The caller of the parse() method adopts the subtree’s root node as a child of the subtree that the caller is building. The caller then returns the root node of its subtree to its caller. This process continues until the entire source has been parsed and we have the entire parse tree.

19 Building a Parse Tree Example:
BEGIN alpha := 10; beta := 20 END CompoundStatementParser’s parse() method creates a COMPOUND node. 2. AssignmentStatementParser’s parse()method creates an ASSIGN node and a VARIABLE node, which the ASSIGN node adopts as its first child.

20 Building a Parse Tree 3. ExpressionParser’s parse() method creates an INTEGER CONSTANT node which the ASSIGN node adopts as its second child. BEGIN alpha := 10; beta := 20 END 4. The COMPOUND node adopts the ASSIGN node as its first child.

21 Building a Parse Tree Another set of calls to the parse() methods of AssignmentStatementParser and ExpressionParser builds another assignment statement subtree. 6. The COMPOUND node adopts the subtree as its second child. BEGIN alpha := 10; beta := 20 END

22 Pascal Expression Syntax Diagrams

23 Expression Syntax Diagrams, cont’d

24 Expression Syntax Diagrams, cont’d

25 Pascal’s Operator Precedence Rules
Level Operators 1 (factor: highest) NOT 2 (term) multiplicative: * / DIV MOD AND 3 (simple expression) additive: + - OR 4 (expression: lowest) relational: = <> < <= > >= If there are no parentheses: Higher level operators execute before the lower level ones. Operators at the same level execute from left to right. Because the factor syntax diagram defines parenthesized expressions, parenthesized expressions always execute first, from the most deeply nested outwards.

26 Example Decomposition
alpha + 3/(beta – gamma) + 5

27 Parsing Expressions Pascal statement parser subclass ExpressionParser has methods that correspond to the expression syntax diagrams: parseExpression() parseSimpleExpression() parseTerm() parseFactor() Each parse method returns the root of the subtree that it builds. Therefore, ExpressionParser’s parse() method returns the root of the entire expression subtree.

28 Parsing Expressions, cont’d
Pascal’s operator precedence rules determine the order in which the parse methods are called. The parse tree that ExpressionParser builds determines the order of evaluation. Example: centigrade/ratio Do a postorder traversal of the parse tree. Visit the left subtree, visit the right subtree, then visit the root.

29 Example: Function parseExpression()
First, we need to map Pascal token types to parse tree node types. Node types need to be language-independent. private:     static map<PascalTokenType, ICodeNodeTypeImpl> REL_OPS_MAP; REL_OPS_MAP[PT_EQUALS]         = NT_EQ; REL_OPS_MAP[PT_NOT_EQUALS]     = NT_NE; REL_OPS_MAP[PT_LESS_THAN]      = NT_LT; REL_OPS_MAP[PT_LESS_EQUALS]    = NT_LE; REL_OPS_MAP[PT_GREATER_THAN]   = NT_GT; REL_OPS_MAP[PT_GREATER_EQUALS] = NT_GE; wci/frontend/pascal/parsers/ExpressionParser.cpp

30 Method parseExpression(), cont’d
ICodeNode *ExpressionParser::parse_expression(Token *token) throw (string) {     ICodeNode *root_node = parse_simple_expression(token);     token = current_token();     TokenType token_type = token->get_type();     map<PascalTokenType, ICodeNodeTypeImpl>::iterator it =                           REL_OPS_MAP.find((PascalTokenType) token_type);     if (it != REL_OPS_MAP.end())     {         ICodeNodeType node_type = (ICodeNodeType) it->second;         ICodeNode *op_node = ICodeFactory::create_icode_node(node_type);         op_node->add_child(root_node);         token = next_token(token);  // consume the operator         op_node->add_child(parse_simple_expression(token));         root_node = op_node;     }     return root_node; } wci/frontend/pascal/parsers/ExpressionParser.cpp

31 Printing Parse Trees Utility class ParseTreePrinter prints parse trees. Prints in an XML format. <COMPOUND line="11"> <ASSIGN line="12"> <VARIABLE id="alpha" level="0" /> <INTEGER_CONSTANT value="10" /> </ASSIGN> <ASSIGN line="13"> <VARIABLE id="beta" level="0" /> <INTEGER_CONSTANT value="20" /> </COMPOUND>

32 Pascal Syntax Checker I
The -i compiler option prints the intermediate code: Add to the constructor of the main Pascal class: ./Chapter5cpp execute -i assignments.txt Pascal.cpp bool intermediate = flags.find('i') != string::npos; ... if (intermediate) {     ParseTreePrinter *tree_printer = new ParseTreePrinter();     tree_printer->print(icode); }

33 Pascal Syntax Checker I, cont’d
Demo (Chapter 5) For now, all we can parse are compound statements, assignment statements, and expressions. More syntax error handling.


Download ppt "CMPE 152: Compiler Design February 12 Class Meeting"

Similar presentations


Ads by Google