Presentation is loading. Please wait.

Presentation is loading. Please wait.

CS 432: Compiler Construction Lecture 9

Similar presentations


Presentation on theme: "CS 432: Compiler Construction Lecture 9"— Presentation transcript:

1 CS 432: Compiler Construction Lecture 9
Department of Computer Science Salisbury University Fall 2016 Instructor: Dr. Sophie Wang 4/15/2018

2 Where are we? We now have a simple scripting engine! What’s next?
Expressions Assignment statements Control statements Compound statements Untyped variables What’s next? Parse Pascal declarations Type checking Parse procedure and function declarations and calls Compile entire Pascal programs _ 4/15/2018

3 Goals and Approach The goals are
Parsers in the front end for Pascal constant definitions, type definitions, variable declarations, and type specifications. Additions to the symbol table to contain type information. 4/15/2018

4 Parsing Declarations The declarations of a programming language are often the most challenging to parse. Declarations syntax can be difficult. Declarations often include recursive definitions. You need to keep of track of diverse information. Many new items to enter into the symbol table. _ 4/15/2018

5 Pascal Declarations Classic Pascal declarations consist of 5 parts, each optional, but always in this order: Label declarations Constant definitions Type definitions Variable declarations Procedure and function declarations We will examine 2, 3, and 4 next. We’ll do procedures and functions in a couple of weeks. 4/15/2018

6 Pascal Declarations, cont'd
The CONST, TYPE, and VAR parts are optional, but they must come in this order. Note that constants and types are defined, but variables are declared. Collectively, you refer to all of them as declarations. 4/15/2018

7 Pascal Constant Definitions
Example constant definition part: CONST factor = 8; epsilon = 1.0e-6; ch = 'x'; limit = -epsilon; message = 'Press the OK button to confirm your selection.'; Classic Pascal only allows a constant value after the = sign. No constant expressions. 4/15/2018

8 Pascal Type Definitions
A Pascal simple type can be: scalar (integer, real, boolean, char) enumeration subrange Not reserved words! 4/15/2018

9 Pascal Simple Type Definitions
Examples of subrange and enumeration type definitions: CONST factor = 8; TYPE range1 = 0..factor; {subrange of integer (factor is constant)} range2 = 'a'..'q'; {subrange of char} range3 = range1; {type identifier} grades = (A, B, C, D, F); {enumeration} passing = A..D; {subrange of enumeration} week = (monday, tuesday, wednesday, thursday, friday, saturday, sunday); weekday = monday..friday; weekend = saturday..sunday; 4/15/2018

10 Pascal Array Type Definitions
index type element type An array type specification has an index type and an element type. The index type must be a simple type (subrange or enumeration). The element type can be any type. Including another array type (multidimensional arrays). 4/15/2018

11 Pascal Array Type Definitions, cont'd
Examples of array definitions. TYPE ar1 = ARRAY [grades] OF integer; ar2 = ARRAY [(alpha, beta, gamma)] OF range2; ar3 = ARRAY [weekday] OF ar2; ar4 = ARRAY [range3] OF (foo, bar, baz); ar5 = ARRAY [range1] OF ARRAY [range2] OF ARRAY[c..e] OF enum2; ar6 = ARRAY [range1, range2, c..e] OF enum2; Type definitions ar5 and ar6 above are equivalent ways to define a multidimensional array. A Pascal string type is an array of characters. The index type must be an integer subrange with a lower limit of 1. str = ARRAY [1..10] OF char; 4/15/2018

12 Pascal Record Type Definitions
A record field can be any type. Including another record type (nested records). 4/15/2018

13 Pascal Record Type Definitions, cont'd
Examples of record definitions: TYPE rec1 = RECORD i : integer; r : real; b1, b2 : boolean; c : char END; rec2 = RECORD ten : integer; r : rec1; a1, a2, a3 : ARRAY [range3] OF range2; 4/15/2018

14 Pascal Variable Declarations
Variable declarations are syntactically similar to record field declarations: Examples: VAR var1 : integer; var2, var3 : range2; var4 : ar2 var5 : rec1; direction : (north, south, east, west); Types can be named or unnamed. 4/15/2018

15 Declarations and the Symbol Table
Identifiers from Pascal declarations that we will enter into a symbol table: Names of constants Names of types Names of enumeration values Names of record fields Names of variables Information from parsing type specifications: Simple types Array types Record types 4/15/2018

16 Type Specification Interfaces
Interface TypeSpec represents a type specification. Method getForm() returns the type’s form. scalar enumeration subrange array record A named type refers to its type identifier. getIdentifier() Each type specification has certain attributes depending on its form. Conceptually, a type specification is: a form (scalar, array, record, etc.) a type identifier (if it’s named) a collection of attributes Interfaces TypeForm and TypeKey are marker interfaces They define no methods. 4/15/2018

17 Type Specification Attributes
Each type specification has certain attributes depending on its form. Type form Type specification attributes Scalar None Enumeration List of enumeration constant identifiers Subrange Base type Minimum value Maximum value Array Index type Element type Element count Record A separate symbol table for the field identifiers 4/15/2018

18 TypeFormImpl TypeFormImpl enumerated values represent the type forms.
The left column of the table. public enum TypeFormImpl implements TypeForm { SCALAR, ENUMERATION, SUBRANGE, ARRAY, RECORD; ... } A separate symbol table for the field identifiers Record Element count Element type Index type Array Maximum value Minimum value Base type Subrange List of enumeration constant identifiers Enumeration None Scalar Type specification attributes Type form 4/15/2018

19 TypeKeyImpl TypeKeyImpl enumerated values are the attribute keys.
The right column of the table. A separate symbol table for the field identifiers Record Element count Element type Index type Array Maximum value Minimum value Base type Subrange List of enumeration constant identifiers Enumeration None Scalar Type specification attributes Type form public enum TypeKeyImpl implements TypeKey { // Enumeration ENUMERATION_CONSTANTS, // Subrange SUBRANGE_BASE_TYPE, SUBRANGE_MIN_VALUE, SUBRANGE_MAX_VALUE, // Array ARRAY_INDEX_TYPE, ARRAY_ELEMENT_TYPE, ARRAY_ELEMENT_COUNT, // Record RECORD_SYMTAB } A TypeFormImpl enumerated value tells us which TypeKeyImpl attribute keys to use. 4/15/2018

20 TypeSpecImpl Implement a type specification as a hash map.
Similar to a symbol table entry and a parse tree node. public class TypeSpecImpl extends HashMap<TypeKey, Object> implements TypeSpec { private TypeForm form; // type form private SymTabEntry identifier; // type identifier public TypeSpecImpl(TypeForm form) this.form = form; this.identifier = null; } ... 4/15/2018

21 TypeSpecImpl, cont'd A constructor to make Pascal string types.
public TypeSpecImpl(String value) { this.form = ARRAY; TypeSpec indexType = new TypeSpecImpl(SUBRANGE); indexType.setAttribute(SUBRANGE_BASE_TYPE, Predefined.integerType); indexType.setAttribute(SUBRANGE_MIN_VALUE, 1); indexType.setAttribute(SUBRANGE_MAX_VALUE, value.length()); setAttribute(ARRAY_INDEX_TYPE, indexType); setAttribute(ARRAY_ELEMENT_TYPE, Predefined.charType); setAttribute(ARRAY_ELEMENT_COUNT, value.length()); } A separate symbol table for the field identifiers Record Element count Element type Index type Array Maximum value Minimum value Base type Subrange List of enumeration constant identifiers Enumeration None Scalar Type specification attributes Type form You’ll see soon where Predefined.integerType and Predefined.charType are defined. 4/15/2018

22 TypeSpecImpl, cont'd Return the base type of a subrange type.
Example: Return integer for a subrange of integer. Just return the type if it’s not a subrange. public TypeSpec baseType() { return form == SUBRANGE ? (TypeSpec) getAttribute(SUBRANGE_BASE_TYPE) : this; } 4/15/2018

23 TypeSpecImpl, cont'd Is this a string type?
public boolean isPascalString() { if (form == ARRAY) { TypeSpec elmtType = (TypeSpec) getAttribute(ARRAY_ELEMENT_TYPE); TypeSpec indexType = (TypeSpec) getAttribute(ARRAY_INDEX_TYPE); return (elmtType.baseType() == Predefined.charType) && (indexType.baseType() == Predefined.integerType); } else { return false; To be a Pascal string type, the index type must be integer and the element type must be char. 4/15/2018

24 Type Factory A type factory creates type specifications.
In package intermediate. Two factory methods. Pascal string types. All other types. public class TypeFactory { public static TypeSpec createType(TypeForm form) return new TypeSpecImpl(form); } public static TypeSpec createStringType(String value) return new TypeSpecImpl(value); 4/15/2018

25 Review: The Symbol Table
Goal: The symbol table should be source language independent. Each entry in the symbol table has a name attributes At the conceptual level, we don’t worry about implementation. 4/15/2018

26 What Needs a Symbol Table?
A Pascal program Identifiers for constant, type, variable, procedure, and function names. A Pascal procedure or function Identifiers for formal parameter (argument) names. A Pascal record type Identifiers for field names. 4/15/2018

27 The Symbol Table Stack Language constructs can be nested.
Procedures and functions are nested inside a program. Procedures and functions can be nested inside of each other. Record types are defined within programs, procedures, and functions. Record types can be nested inside of each other. Therefore, symbol tables need to be kept on a symbol table stack. 4/15/2018

28 The Symbol Table Stack (cont’d)
Whichever symbol table is on top of the stack is the local symbol table. The first symbol table created (the one at the bottom of the stack) is the global symbol table. It stores the predefined information, such as entries for the names of the standard types integer, real, char, and boolean. During the translation process, symbol tables are pushed onto and popped off the stack … … as the parser enters and exits nested procedures, functions, record types, etc. Global symbol table 4/15/2018

29 Symbol Table Interfaces
Key operations Enter into the local symbol table, the table currently at the top of the stack. Look up (search for) an entry only in the local symbol table. Look up an entry in all the symbol tables in the stack. Search from the top (the local) table down to the bottom (global) table. Each symbol table has a nesting level. 0: global 1: program 2: top-level procedure 3: nested procedure, etc. 4/15/2018

30 Symbol Table Interfaces, cont’d
Java interfaces Package wci.intermediate SymTabStack SymTab SymTabEntry SymTabKey Example: public interface SymTabEntry { public String getName(); public SymTab getSymTab(); public void setAttribute(SymTabKey key, Object value); public Object getAttribute(SymTabKey key); public void appendLineNumber(int lineNumber); public ArrayList<Integer> getLineNumbers(); } For cross-referencing. 4/15/2018

31 Symbol Table Components Implementation
Implementation classes are defined in package intermediate.symtabimpl A SymTabStackImpl object can own zero or more SymTab objects. A SymTabImpl object can own zero or more SymTabEntry objects. A SymTabEntryImpl object maintains a reference to the SymTab object that contains it. _ 4/15/2018

32 A Symbol Table Factory Class
public class SymTabFactory { public static SymTabStack createSymTabStack() return new SymTabStackImpl(); } public static SymTab createSymTab(int nestingLevel) return new SymTabImpl(nestingLevel); public static SymTabEntry createSymTabEntry(String name, SymTab symTab) return new SymTabEntryImpl(name, symTab); 4/15/2018

33 Symbol Table Implementation
<String, SymTabEntry> String: name of the identifier TreeMap<String, SymTabEntry)> SymTabImpl nestinglevel: integer: the nesting level of the table 4/15/2018

34 Symbol Table Implementation
Implement the symbol table as a Java hash table. Key: the identifier name (a string) Value: the symbol table entry corresponding to the name Even better: extends TreeMap<String, SymTabEntry> implements SymTab Like a hash table except that it keeps its entries sorted. Show SymTabImpl source code 4/15/2018

35 Symbol Table Stack Implementation
<SymTab> ArrayList<SymTab> SymTabStackImpl currentNestingLevel: programId: SymTabEntry: entry for the main program id integer: the nesting level of the table on top of the stack 4/15/2018

36 Symbol Table Stack Implementation
Implement the stack as an array list of symbol tables: extends ArrayList<SymTab> implements SymTabStack Constructor Set the current nesting level will always be 0. Initialize the stack with the global symbol table. Show SymTabStackImpl code 4/15/2018

37 Symbol Table Entry Implementation
CONSTANT_VALUE, ROUTINE_CODE, ROUTINE_SYMTAB, ROUTINE_ICODE, ROUTINE_PARMS, ROUTINE_ROUTINES, DATA_VALUE <SymTabKey, Object)> HashMap<SymTabKey, Object)> SymTabEntryImpl name: symTab: definition: typeSpec: SymTab: parent symbol table String: name of the identifier TypeSpec: typeSpecification Definition: how the identifier is defined CONSTANT, ENUMERATION_CONSTANT,TYPE, VARIABLE, FIELD, VALUE_PARM, VAR_PARM,PROGRAM_PARM, PROGRAM, PROCEDURE, FUNCTION, UNDEFINED 4/15/2018

38 Symbol Table Entry Implementation
Implement a symbol table entry as a Java hash map: extends HashMap<SymTabKey, Object> implements SymTabEntry Most flexibility in what we can store in each entry. Key: attribute key (an enumerated type) Value: attribute value (an arbitrary object) Show SymTabEntryImpl source code 4/15/2018

39 What to Store in Each Symbol Table Entry
Each symbol table entry is designed to store information about an identifier. The attribute keys indicate what information we will store for each type of identifier. Store common information in fixed fields (e.g., lineNumbers) and store identifier type-specific information as attributes. public enum SymTabKeyImpl implements SymTabKey { // Constant. CONSTANT_VALUE, // Procedure or function. ROUTINE_CODE, ROUTINE_SYMTAB, ROUTINE_ICODE, ROUTINE_PARMS, ROUTINE_ROUTINES, // Variable or record field value. DATA_VALUE } 4/15/2018

40 Scope and the Symbol Table Stack
Scope refers to the part of the source program where certain identifiers can be used. Everywhere in the program where the definitions of those identifiers are in effect. Closely related to nesting levels and the symbol table stack. Global scope Nesting level 0: bottom of the symbol table stack. All predefined global identifiers, such as integer, real, boolean, char. Program scope Nesting level 1: one up from the bottom of the stack. All identifiers defined at the “top level” (not in a procedure or function) of a program. Record definitions, procedures, and functions each has a scope. 4/15/2018

41 Scope and the Symbol Table Stack, cont'd
Scopes in a Pascal program are nested. An identifier can be redefined within a nested scope. Within the nested scope, the definition in the nested scope overrides the definition in an outer scope. Each scope must have its own symbol table. As the parser parses a program from top to bottom, it enters and exits nested scopes. Whenever the parser enters a scope, it must push that scope’s symbol table onto the symbol table stack. As the parser exits a scope, it must pop that scope’s symbol table off the stack. 4/15/2018

42 Scope and the Symbol Table Stack, cont'd
Scope example: Program symbol table Global symbol table Note that the program name Test is defined in the global scope at level 0. 4/15/2018

43 New Methods for Class SymTabStackImpl
public SymTab push() { SymTab symTab = SymTabFactory.createSymTab(++currentNestingLevel); add(symTab); return symTab; } public SymTab push(SymTab symTab) ++currentNestingLevel; public SymTab pop() SymTab symTab = get(currentNestingLevel); remove(currentNestingLevel--); Push a new symbol table onto the stack. Push an existing symbol table onto the stack. Pop a symbol table off the stack. Recall that we implemented SymTabStackImpl as an ArrayList<SymTab>. 4/15/2018

44 Class SymTabStackImpl, cont'd
public SymTabEntry lookupLocal(String name) { return get(currentNestingLevel).lookup(name); } public SymTabEntry lookup(String name) SymTabEntry foundEntry = null; for (int i = currentNestingLevel; (i >= 0) && (foundEntry == null); --i) foundEntry = get(i).lookup(name); return foundEntry; Method lookup() now searches the current symbol table and the symbol tables lower in the stack. It searches the current scope and then outward in the enclosing scopes. 4/15/2018

45 How are Identifiers Defined?
Identifier are no longer only names of variables. Class DefinitionImpl enumerates all the ways an identifier can be defined. Package intermediate.symtabimpl. public enum DefinitionImpl implements Definition { CONSTANT, ENUMERATION_CONSTANT("enumeration constant"), TYPE, VARIABLE, FIELD("record field"), VALUE_PARM("value parameter"), VAR_PARM("VAR parameter"), PROGRAM_PARM("program parameter"), PROGRAM, PROCEDURE, FUNCTION, UNDEFINED; ... } Think of Definition as the role an identifier plays. 4/15/2018

46 Predefined Scalar Types
Initialized by class Predefined in the global scope. Package intermediate.symtabimpl. Example: integer public static TypeSpec integerType; public static SymTabEntry integerId; ... private static void initializeTypes(SymTabStack symTabStack) { integerId = symTabStack.enterLocal("integer"); integerType = TypeFactory.createType(SCALAR); integerType.setIdentifier(integerId); integerId.setDefinition(DefinitionImpl.TYPE); integerId.setTypeSpec(integerType); } Type specification integerType and the symbol table entry integerId refer to each other. 4/15/2018

47 Predefined Scalar Types (cont’d)
Initialized by class Predefined in the global scope. Package intermediate.symtabimpl. Example: boolean public static TypeSpec booleanType; public static SymTabEntry booleanId; ... private static void initializeTypes(SymTabStack symTabStack) { booleanId = symTabStack.enterLocal("boolean"); booleanType = TypeFactory.createType(ENUMERATION); booleanType.setIdentifier(booleanId); booleanId.setDefinition(DefinitionImpl.TYPE); booleanId.setTypeSpec(booleanType); } 4/15/2018

48 Predefined Scalar Types, cont'd
Predefined type boolean introduces two predefined constants, true and false. falseId = symTabStack.enterLocal("false"); falseId.setDefinition(DefinitionImpl.ENUMERATION_CONSTANT); falseId.setTypeSpec(booleanType); falseId.setAttribute(CONSTANT_VALUE, new Integer(0)); trueId = symTabStack.enterLocal("true"); trueId.setDefinition(DefinitionImpl.ENUMERATION_CONSTANT); trueId.setTypeSpec(booleanType); trueId.setAttribute(CONSTANT_VALUE, new Integer(1)); ArrayList<SymTabEntry> constants = new ArrayList<SymTabEntry>(); constants.add(falseId); constants.add(trueId); booleanType.setAttribute(ENUMERATION_CONSTANTS, constants); Add the constant identifiers to the ENUMERTION_CONSTANTS list attribute. 4/15/2018

49 Review: How are Identifiers Defined?
Identifier are no longer only names of variables. Class DefinitionImpl enumerates all the ways an identifier can be defined. Package intermediate.symtabimpl. public enum DefinitionImpl implements Definition { CONSTANT, ENUMERATION_CONSTANT("enumeration constant"), TYPE, VARIABLE, FIELD("record field"), VALUE_PARM("value parameter"), VAR_PARM("VAR parameter"), PROGRAM_PARM("program parameter"), PROGRAM, PROCEDURE, FUNCTION, UNDEFINED; ... } Think of Definition as the role an identifier plays. 4/15/2018

50 Review: TypeKeyImpl TypeKeyImpl enumerated values are the attribute keys. The right column of the table. A separate symbol table for the field identifiers Record Element count Element type Index type Array Maximum value Minimum value Base type Subrange List of enumeration constant identifiers Enumeration None Scalar Type specification attributes Type form public enum TypeKeyImpl implements TypeKey { // Enumeration ENUMERATION_CONSTANTS, // Subrange SUBRANGE_BASE_TYPE, SUBRANGE_MIN_VALUE, SUBRANGE_MAX_VALUE, // Array ARRAY_INDEX_TYPE, ARRAY_ELEMENT_TYPE, ARRAY_ELEMENT_COUNT, // Record RECORD_SYMTAB } The TypeFormImpl enumerated values tell us which TypeKeyImpl attribute keys to use. 4/15/2018

51 Review: Pascal Declarations
4/15/2018

52 Parsing Pascal Declarations
4/15/2018

53 Method PascalParserTD.parse()
Create a new symbol table stack (includes the level 0 global symbol table). symTabStack = SymTabFactory.createSymTabStack(); iCode = ICodeFactory.createICode(); errorHandler = new PascalErrorHandler(); Predefined.initialize(symTabStack); routineId = symTabStack.enterLocal("DummyProgramName".toLowerCase()); routineId.setDefinition(DefinitionImpl.PROGRAM); symTabStack.setProgramId(routineId); routineId.setAttribute(ROUTINE_SYMTAB, symTabStack.push()); routineId.setAttribute(ROUTINE_ICODE, iCode); Token token = nextToken(); BlockParser blockParser = new BlockParser(this); blockParser.parse(token); symTabStack.pop(); Predefined types  global symbol table. Push the new level 1 symbol table. The symbol table entry of the program id keeps a pointer to the level 1 symbol table. Parse the program’s block. When done, pop off the level 1 symbol table. 4/15/2018

54 Method PascalParserTD.parse(), cont'd
token = currentToken(); if (token.getType() != DOT) { errorHandler.flag(token, MISSING_PERIOD, this); } float elapsedTime = (System.currentTimeMillis() - startTime)/1000f; sendMessage(new Message(PARSER_SUMMARY, new Number[] {token.getLineNumber(), getErrorCount(), elapsedTime})); _ Parse the final period. 4/15/2018

55 Method BlockParser.parse()
DeclarationsParser declarationsParser = new DeclarationsParser(this); StatementParser statementParser = new StatementParser(this); // Parse any declarations. declarationsParser.parse(token); token = synchronize(StatementParser.STMT_START_SET); TokenType tokenType = token.getType(); ICodeNode rootNode = null; // Look for the BEGIN token to parse a compound statement. if (tokenType == BEGIN) { rootNode = statementParser.parse(token); } ... return rootNode; Parse declarations. Synchronize to the start of a statement. Parse the compound statement. 4/15/2018

56 Method DeclarationsParser.parse()
Parse constant definitions. If there is the CONST reserved word. Call the parse() method of ConstantDefinitionsParser Parse type definitions. If there is the TYPE reserved word. Call the parse() method of TypeDefinitionsParser Parse variable declarations. If there is the VAR reserved word. Call the parse() method of VariableDeclarationsParser _ 4/15/2018

57 ConstantDefinitionsParser
epsilon = 1.0e-6; pi = ; delta = epsilon; parse() parseConstant() parseIdentifierConstant() getConstantType() _ 4/15/2018

58 Method ConstantDefinitionsParser.parse()
token = synchronize(IDENTIFIER_SET); while (token.getType() == IDENTIFIER) { String name = token.getText().toLowerCase(); SymTabEntry constantId = symTabStack.lookupLocal(name); if (constantId == null) { constantId = symTabStack.enterLocal(name); constantId.appendLineNumber(token.getLineNumber()); } else { errorHandler.flag(token, IDENTIFIER_REDEFINED, this); constantId = null; token = nextToken(); // consume the identifier token token = synchronize(EQUALS_SET); if (token.getType() == EQUALS) { token = nextToken(); // consume the = continued … Loop over the constant definitions. Enter the constant identifier into the symbol table but don’t set its definition to CONSTANT yet. Synchronize and parse the = sign. 4/15/2018

59 ConstantDefinitionsParser.parse(), cont'd
Token constantToken = token; Object value = parseConstant(token); if (constantId != null) { constantId.setDefinition(CONSTANT); constantId.setAttribute(CONSTANT_VALUE, value); TypeSpec constantType = constantToken.getType() == IDENTIFIER ? getConstantType(constantToken) : getConstantType(value); constantId.setTypeSpec(constantType); } ... token = synchronize(IDENTIFIER_SET); } // while Parse the constant’s value. Now set the constant identifier to CONSTANT. Set the constant’s value. Set the constant’s type. Guard against the constant definition pi = pi Check for and parse the semicolon. Synchronize at the start of the next constant definition. 4/15/2018

60 Review: Type Specification Interfaces
Interface TypeSpec represents a type specification. Method getForm() returns the type’s form. scalar enumeration subrange array record A named type refers to its type identifier. getIdentifier() Each type specification has certain attributes depending on its form. Conceptually, a type specification is: a form (scalar, array, record, etc.) a type identifier (if it’s named) a collection of attributes. Interfaces TypeForm and TypeKey are marker interfaces They define no methods. 4/15/2018

61 Review: Type Specification Attributes
Each type specification has certain attributes depending on its form. Type form Type specification attributes Scalar None Enumeration List of enumeration constant identifiers Subrange Base type Minimum value Maximum value Array Index type Element type Element count Record A separate symbol table for the field identifiers 4/15/2018

62 Review: TypeFormImpl TypeFormImpl enumerated values represent the type forms. The left column of the table. public enum TypeFormImpl implements TypeForm { SCALAR, ENUMERATION, SUBRANGE, ARRAY, RECORD; ... } A separate symbol table for the field identifiers Record Element count Element type Index type Array Maximum value Minimum value Base type Subrange List of enumeration constant identifiers Enumeration None Scalar Type specification attributes Type form 4/15/2018

63 Review: TypeKeyImpl TypeKeyImpl enumerated values are the attribute keys. The right column of the table. A separate symbol table for the field identifiers Record Element count Element type Index type Array Maximum value Minimum value Base type Subrange List of enumeration constant identifiers Enumeration None Scalar Type specification attributes Type form public enum TypeKeyImpl implements TypeKey { // Enumeration ENUMERATION_CONSTANTS, // Subrange SUBRANGE_BASE_TYPE, SUBRANGE_MIN_VALUE, SUBRANGE_MAX_VALUE, // Array ARRAY_INDEX_TYPE, ARRAY_ELEMENT_TYPE, ARRAY_ELEMENT_COUNT, // Record RECORD_SYMTAB } The TypeFormImpl enumerated values tell us which TypeKeyImpl attribute keys to use. 4/15/2018

64 Review: TypeSpecImpl HashMap<TypeKey, Object)> TypeSpecImpl
ENUMERATION_CONSTANTS,SUBRANGE_BASE_TYPE,SUBRANGE_MIN_VALUE,SUBRANGE_MAX_VALUE,ARRAY_INDEX_TYPE,ARRAY_ELEMENT_TYPE,ARRAY_ELEMENT_COUNT,RECORD_SYMTAB <TypeKey, Object)> HashMap<TypeKey, Object)> TypeSpecImpl form: identifier: SymTabEntry:identifier to a SymTabEntry TypeForm: (SCALAR,ENUMERATION, SUBRANGE,ARRAY,RECORD) 4/15/2018

65 Review: TypeSpecImpl Implement a type specification as a hash map.
Similar to a symbol table entry and a parse tree node. public class TypeSpecImpl extends HashMap<TypeKey, Object> implements TypeSpec { private TypeForm form; // type form private SymTabEntry identifier; // type identifier public TypeSpecImpl(TypeForm form) this.form = form; this.identifier = null; } ... What are the keys of the hash table? How do we know which keys to use? 4/15/2018

66 Review: Type Definitions
Sample type definitions: TYPE e = (alpha, beta, gamma); sr = alpha..beta; ar = ARRAY [1..10] OF sr; rec = RECORD x, y : integer END; How can we represent type specification information in our symbol table and associate the correct type specification with an identifier? 4/15/2018

67 Type Definition Structures
type specification (class TypeSpecImpl) symbol table entry (class SymTabEntryImpl) symbol table entry (class SymTabEntryImpl) TYPE ATTRIBUTE KEY (enumeration TypeKeyImpl) Each symbol table entry has a pointer to a type specification. Each type specification of a named type has a pointer to the type identifier’s symbol table entry. 4/15/2018

68 Type Definition Structures, cont'd
SUBRANGE_BASE_TYPE When it is parsing declarations, the parser builds type specification structures. When it is parsing executable statements, the parser builds parse trees. Unnamed type Is there an unnamed type? 4/15/2018

69 Type Definition Structures, cont'd
ARRAY_ELMT_TYPE rec = RECORD x,y : integer END TYPE ATTRIBUTE KEY (enumeration TypeKeyImpl) Each record type has its own symbol table to contain its record field identifiers. 4/15/2018

70 TypeDefinitionsParser.parse()
e = (alpha, beta, gamma); sr = alpha..beta; ar = ARRAY [1..10] OF sr; rec = RECORD x, y : integer END; TypeDefinitionParser.parse() TypeSpecificationParser.parse() Loop to parse each type definition. Parse the type identifier and the = sign. Call the parse() method of TypeSpecificationParser. Parse the type specification and return a TypeSpec object. Cross-link the SymTabEntry object of the type identifier with the TypeSpec object. _ 4/15/2018

71 TypeSpecificationParser.parse()
Parse an array type. If there is an ARRAY reserved word. Call the parse() method of ArrayTypeParser Parse a record type. If there is a RECORD reserved word. Call the parse() method of RecordTypeParser Parse a simple type. In all other cases. Call the parse() method of SimpleTypeParser _ 4/15/2018

72 SimpleTypeParser.parse()
The parse() method parses: A previously-defined type identifier. An enumeration type specification. Call the parse() method of EnumerationTypeParser. A subrange type specification. Call the parse() method of SubrangeTypeParser. _ 4/15/2018

73 Pascal Subrange Type 4/15/2018

74 SubrangeTypeParser.parse()
Call TypeFactory.createType(SUBRANGE) to create a new subrange type specification. Parse the minimum constant value. Call ConstantDefinitionsParser.parseConstant() Get and check the data type of the minimum constant value: Call ConstantDefinitionsParser.getConstantType() Call checkValueType() The type must be integer, character, or an enumeration. Consume the .. token. Parse the maximum constant value. Check that both values have the same data type. Check that the minimum value <= maximum value. Set attributes of the subrange type specification. SUBRANGE_BASE_TYPE SUBRANGE_MIN_VALUE SUBRANGE_MAX_VALUE 4/15/2018

75 Parsing a Subrange Type
sr = 1..10; enum = (alpha, beta, gamma); ar = ARRAY [sr, enum] OF integer; rec = RECORD x, y : real END; SUBRANGE MIN_VALUE: 1 MAX_VALUE: 10 “sr” TYPE Pascal  PascalParserTD.parse()  BlockParser.parse()  DeclarationsParser.parse()  TypeDefinitionsParser.parse()  TypeSpecificationParser.parse()  SimpleTypeParser.parse()  SubrangeTypeParser.parse() 4/15/2018

76 Pascal Enumeration Type
4/15/2018

77 EnumerationTypeParser.parse()
Call TypeFactory.createType(ENUMERATION) to create a new enumeration type specification. Loop to parse each enumeration identifier. Call parseEnumerationIdentifier() Set the definition of the identifier to ENUMERATION_CONSTANT. Set the typeSpec field of the identifier to the enumeration type specification. Set the CONSTANT_VALUE of the identifier to the next integer value (starting with 0). Build an ArrayList<SymTabEntry> of symbol table entries for the enumeration identifiers. Set the ENUMERATION_CONSTANTS attribute of the enumeration type specification to the array list. 4/15/2018

78 Parsing an Enumeration Type
sr = 1..10; enum = (alpha, beta, gamma); ar = ARRAY [sr, enum] OF integer; rec = RECORD x, y : real END; “enum” TYPE ENUMERATION “alpha” ENUMERATION_CONSTANT “beta” ENUMERATION_CONSTANT TypeDefinitionsParser.parse()  TypeSpecificationParser.parse()  SimpleTypeParser.parse()  EnumerationTypeParser.parse()  parseEnumerationIdentifier() “gamma” ENUMERATION_CONSTANT 4/15/2018

79 Pascal Record Type rec = RECORD x,y : integer END 4/15/2018

80 RecordTypeParser.parse()
Call TypeFactory.createType(RECORD) to create a new record type specification. Create and push a new symbol table onto the symbol table stack. Set the RECORD_SYMTAB attribute of the record type specification to the new symbol table. Call VariableDeclarationsParser.parse() to parse the field declarations. Set each field’s definition to FIELD. Enter each field into the current symbol table (the one just pushed onto the top of the stack). Pop the record type’s symbol table off the symbol table stack. rec = RECORD x,y : integer END After the record type’s symbol table has been popped off the symbol table stack, it’s still referenced by the RECORD_SYMTAB attribute. 4/15/2018

81 Parsing a Record Type TypeDefinitionsParser.parse()
sr = 1..10; enum = (alpha, beta, gamma); ar = ARRAY [sr, enum] OF integer; rec = RECORD x, y : real END; “rec” TYPE RECORD symtab “X” FIELD “Y” TypeDefinitionsParser.parse()  TypeSpecificationParser.parse()  RecordTypeParser.parse()  VariableDeclarationsParser.parse() 4/15/2018

82 Pascal Array Type 4/15/2018

83 Pascal Multidimensional Array
These definitions are all equivalent: dim3 = ARRAY [1..3, 'a'..'z', boolean] OF real; dim3 = ARRAY [1..3] OF ARRAY ['a'..'z'] OF ARRAY [boolean] OF real; dim3 = ARRAY [1..3, 'a'..'z'] OF ARRAY [boolean] OF real; dim3 = ARRAY [1..3] OF ARRAY ['a'..'z, boolean] OF real; Therefore, they must all generate the same type specification structure. _ 4/15/2018

84 Pascal Multidimensional Array, cont'd
The ARRAY_ ELEMENT_TYPE references form the backbone of this structure (a linked list). The first two element types are arrays, and the third element type is real scalar. 4/15/2018

85 ArrayTypeParser.parse()
Call TypeFactory.createType(ARRAY) to create a new array type specification. Call parseIndexTypeList() to parse the list of index types. Set local variable elementType to the new array type specification. Loop to call parseIndexType() to parse each index type. Call simpleTypeParser.parse() to parse the index type. Set the attributes for a subrange or enumeration index type specification. Set the ARRAY_ELEMENT_COUNT attribute for the current array type spec. For each index type in the list after the first: Call TypeFactory.createType(ARRAY) to create the next elementType value. Set the ARRAY_ELEMENT_TYPE attribute of the previous elementType value to link to the new elementType value. Call parseElementType() to parse the final element type. Link the previous element type to the final element type. These elementType references create the backbone. 4/15/2018

86 Parsing an Array Type TypeDefinitionsParser.parse()
sr = 1..10; enum = (alpha, beta, gamma); ar = ARRAY [sr, enum] OF integer; rec = RECORD x, y : real END; “ar” TYPE SUBRANGE “sr” TYPE index type ARRAY element type ARRAY ENUMERATION “enum” TYPE index type SCALAR “integer” TYPE element type TypeDefinitionsParser.parse()  TypeSpecificationParser.parse()  ArrayTypeParser.parse()  parseIndexTypeList()  parseIndexType()  parseElementType() 4/15/2018


Download ppt "CS 432: Compiler Construction Lecture 9"

Similar presentations


Ads by Google