Download presentation
Presentation is loading. Please wait.
Published byEmilie Ludvigsen Modified over 6 years ago
1
CMPE 152: Compiler Design September 27 Class Meeting
Department of Computer Engineering San Jose State University Fall 2018 Instructor: Ron Mak
2
Now that we can parse declarations …
We can parse variables that have subscripts and fields. Example: We can perform type checking. A semantic action. Chapter 10 var9.rec.flda[b][0,'m'].flda[d] := 'p’
3
Type Checking Ensure that the types of the operands are type-compatible with their operator. Example: You can only perform an integer division with the DIV operator and integer operands. Example: The relational operators AND and OR can only be used with boolean operands. Ensure that a value being assigned to a variable is assignment-compatible with the variable. Example: You cannot assign a string value to an integer variable.
4
Type Specifications and the Parse Tree
Every Pascal expression has a data type. Add a type specification to every parse tree node. “Decorate” the parse tree with type information. wci/intermediate/IcodeNode.h void set_typespec(TypeSpec *spec) = 0; TypeSpec *get_typespec() const = 0; wci/intermediate/icodenodeimpl/IcodeNodeImpl.h private: TypeSpec *typespec; // data type specification public: void set_typespec(TypeSpec typeSpec) { ... } TypeSpec *get_typespec() { ... }
5
Class TypeChecker Static boolean methods for type checking:
isInteger() areBothInteger() isReal() isIntegerOrReal() isAtLeastOneReal() isBoolean() areBothBoolean() isChar() areAssignmentCompatible() areComparisonCompatible() equalLengthStrings() wci/intermediate/typeimpl/TypeChecker.h
6
Class TypeChecker, cont'd
wci/intermediate/typeimpl/TypeChecker.cpp bool TypeChecker::is_integer(TypeSpec *typespec) { return (typespec != nullptr) && (typespec->base_type() == Predefined::integer_type); } bool TypeChecker::are_both_integer(TypeSpec *typespec1, TypeSpec *typespec2) return is_integer(typespec1) && is_integer(typespec2); ... bool TypeChecker::is_at_least_one_real(TypeSpec *typespec1, TypeSpec *typespec2) return (is_real(typespec1) && is_real(typespec2)) || (is_real(typespec1) && is_integer(typespec2)) || (is_integer(typespec1) && is_real(typespec2));
7
Assignment and Comparison Compatible
In classic Pascal, a value is assignment-compatible with a target variable if: both have the same type the target is real and the value is integer they are equal-length strings Two values are comparison-compatible (they can be compared with relational operators) if: one is integer and the other is real
8
Assignment Compatible
bool TypeChecker::are_assignment_compatible(TypeSpec *target_typespec, TypeSpec *value_typespec) { if ((target_typespec == nullptr) || (value_typespec == nullptr)) { return false; } target_typespec = target_typespec->base_type(); value_typespec = value_typespec->base_type(); bool compatible = false; if (target_typespec == value_typespec) compatible = true; else if (is_real(target_typespec) && is_integer(value_typespec)) else { compatible = target_typespec->is_pascal_string() && value_typespec->is_pascal_string(); return compatible; } Same type real := integer Both are strings wci/intermediate/typeimpl/TypeChecker.cpp
9
Type Checking Expressions
The parser must perform type checking of every expression as part of its semantic actions. Add type checking to class ExpressionParser and to each statement parser. Flag type errors similarly to syntax errors.
10
Method ExpressionParser::parseTerm()
Now besides doing syntax checking, our expression parser must also do type checking and determine the result type of each operation. case PT_STAR: { if (TypeChecker::are_both_integer(result_typespec, factor_typespec)) { result_typespec = Predefined::integer_type; } else if (TypeChecker::is_at_least_one_real(result_typespec, factor_typespec)) result_typespec = Predefined::real_type; else error_handler.flag(expr_token, INCOMPATIBLE_TYPES, this); break; } integer * integer integer result one integer and one real, or both real real result wci/frontend/pascal/parsers/ExpressionParser.cpp
11
Type Checking Control Statements
ICodeNode *IfStatementParser::parse_statement(Token *token) throw (string) { token = next_token(token); // consume the IF ICodeNode *if_node = ICodeFactory::create_icode_node((ICodeNodeType) NT_IF); Token *expr_token = new Token(*token); ExpressionParser expression_parser(this); ICodeNode *expr_node = expression_parser.parse_statement(token); if_node->add_child(expr_node); TypeSpec *expr_typespec = expr_node != nullptr ? expr_node->get_typespec() : Predefined::undefined_type; if (!TypeChecker::is_boolean(expr_typespec)) { error_handler.flag(expr_token, INCOMPATIBLE_TYPES, this); } ... } wci/frontend/pascal/parsers/IfStatementParser.cpp
12
ExpressionParser::parseFactor()
Now an identifier can be more than just a variable name. ICodeNode *ExpressionParser::parse_factor(Token *token) throw (string) { ... switch ((PascalTokenType) tokenType) case IDENTIFIER: return parse_identifier(token); } wci/frontend/pascal/parsers/ExpressionParser.cpp
13
ExpressionParser.parseIdentifier()
Constant identifier Previously defined in a CONST definition. Create an INTEGER_CONSTANT, REAL_CONSTANT, or a STRING_CONSTANT node. Set its VALUE attribute. Enumeration identifier Previously defined in a type specification. Create an INTEGER_CONSTANT node. CONST pi = ; TYPE direction = (north, south, east, west);
14
ExpressionParser.parseIdentifier()
Variable identifier Call method variableParser::parse().
15
Syntax Diagram for Variables
The outer loop back allows any number of subscripts and fields. A variable can have any combination of subscripts and fields. Appear in an expression or as the target of an assignment statement. Example: var9.rec.flda[b][0,'m'].flda[d] := 'p' The parser must do type checking for each subscript and field.
16
Parse Tree for Variables
Assume that b and d are enumeration constants and that b =1 and d = 3 VARIABLE nodes can now have child nodes: SUBSCRIPTS FIELD
17
Class VariableParser Parse variables that appear in statements.
Subclass of StatementParser. Do not confuse with class VariableDeclarationsParser. Subclass of DeclarationsParser. Parsing methods parse() parse_field() parse_subscripts()
18
VariableParser::parse()
Parse the variable identifier (example: var9) Create the VARIABLE node.
19
VariableParser::parse() cont’d
Loop to parse any subscripts and fields. Call methods parse_field() or parse_subscripts(). Variable variable_type keeps track of the current type specification. The current type changes as each field and subscript is parsed.
20
VariableParser::parse_field()
Get the record type’s symbol table. Attribute RECORD_SYMTAB of the record variable’s type specification.
21
VariableParser::parse_field() cont’d
Verify that the field identifier is in the record type’s symbol table. Create a FIELD node that is adopted by the VARIABLE node.
22
VariableParser::parse_subscripts()
Create a SUBSCRIPTS node. Loop to parse a comma-separated list of subscript expressions. The SUBSCRIPTS node adopts each expression parse tree.
23
VariableParser::parse_subscripts()
Verify that each subscript expression is assignment-compatible with the corresponding index type.
24
Demo Pascal Syntax Checker III Parse a Pascal block Type checking
declarations statements with variables Type checking
25
Assignment #4: Complex Type
Add a built-in complex data type to Pascal. Add the type to the global symbol table. Implement as a record type with permanent real fields re and im. Declare complex numbers and assign values to them: VAR x, y, z : complex; BEGIN x.re := 15; x.im := 37; y.re := ; y.im := ; z := x; END.
26
Assignment #4, cont’d Start with the C++ source files from Chapter 10.
Examine wci::intermediate::symtabimpl::Predefined to see how the built-in types like integer and real are defined. Examine wci::frontend::pascal::parsers::RecordTypeParser to see what information is entered into the symbol table for a record type.
27
Assignment #4, cont’d The only source files you should need to modify are Predefined.h and Predefined.cpp. If you successfully implement the new complex type, assignments to complex variables should simply work with no further code changes. Due Monday, October 8.
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.