330 likes | 347 Views
This text discusses the process of type checking control statements in a Pascal compiler design, including handling variables, subscripts, and fields. It also covers the syntax diagram and parse tree for variables.
E N D
CMPE 152: Compiler DesignOctober 3 Class Meeting Department of Computer EngineeringSan Jose State UniversityFall 2019Instructor: Ron Mak www.cs.sjsu.edu/~mak
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); ExpressionParserexpression_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
Syntax Diagram for Variables • 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. The outer loop back allows any number of subscripts and fields.
Parse Tree for Variables • VARIABLE nodes can now have child nodes: • SUBSCRIPTS • FIELD Assume that b and d are enumeration constants and that b =1 and d = 3 Parser classVariableParser
Demo • Pascal Syntax Checker III • Parse a Pascal block • declarations • statements with variables • Type checking
Chapter 11 Pascal Program Header • The program parameters are optional. • Identifiers of input and output file variables. • Default files are standard input and standard output. • Examples: • PROGRAM newton; • PROGRAM hilbert(input, output, error);
Pascal Programs, Procedures, and Functions • Procedure and function declarations come last. • Any number of procedures and functions, and in any order. • A formal parameter list is optional.
Formal Parameter List • By default, parameters are passed by value. • The actual parameter value in the call is copied and the formal parameter is assigned the copied value. The routine cannot changethe value of the caller’s actual parameter value.
Formal Parameter List, cont’d • VAR parameters are passed by reference. • The formal parameter is assigned a reference (pointer) to the actual parameter value. Since the routine has access to the actual parameter, it can changethe caller’s actual parameter value.
Nested Scopes and the Symbol Table Stack PROGRAM Test; VAR i, j, k, n : integer; PROCEDURE p(j : real); VAR k : char; FUNCTION f(x : real) : real; VAR i:real; BEGIN {f} f := i + j + n + x; END {f}; BEGIN {p} k := chr(i + trunc(f(n))); END {p}; BEGIN {test} p(j + k + n) END {test}.
Nested Scopes and the Symbol Table Stack PROGRAM Test; VAR i, j, k, n : integer; PROCEDURE p(j : real); VAR k : char; FUNCTION f(x : real) : real; VAR i:real; BEGIN {f} f := i + j + n + x; END {f}; BEGIN {p} k := chr(i + trunc(f(n))); END {p}; BEGIN {test} p(j + k + n) END {test}.
Nested Scopes and the Symbol Table Stack PROGRAM Test; VAR i, j, k, n : integer; PROCEDURE p(j : real); VAR k : char; FUNCTION f(x : real) : real; VAR i:real; BEGIN {f} f := i + j + n + x; END {f}; BEGIN {p} k := chr(i + trunc(f(n))); END {p}; BEGIN {test} p(j + k + n) END {test}.
Nested Scopes and the Symbol Table Stack PROGRAM Test; VAR i, j, k, n : integer; PROCEDURE p(j : real); VAR k : char; FUNCTION f(x : real) : real; VAR i:real; BEGIN {f} f := i + j + n + x; END {f}; BEGIN {p} k := chr(i + trunc(f(n))); END {p}; BEGIN {test} p(j + k + n) END {test}.
Nested Scopes and the Symbol Table Stack PROGRAM Test; VAR i, j, k, n : integer; PROCEDURE p(j : real); VAR k : char; FUNCTION f(x : real) : real; VAR i:real; BEGIN {f} f := i + j + n + x; END {f}; BEGIN {p} k := chr(i + trunc(f(n))); END {p}; BEGIN {test} p(j + k + n) END {test}.
Nested Scopes and the Symbol Table Stack PROGRAM Test; VAR i, j, k, n : integer; PROCEDURE p(j : real); VAR k : char; FUNCTION f(x : real) : real; VAR i:real; BEGIN {f} f := i + j + n + x; END {f}; BEGIN {p} k := chr(i + trunc(f(n))); END {p}; BEGIN {test} p(j + k + n) END {test}.
Nested Scopes and the Symbol Table Stack PROGRAM Test; VAR i, j, k, n : integer; PROCEDURE p(j : real); VAR k : char; FUNCTION f(x : real) : real; VAR i:real; BEGIN {f} f := i + j + n + x; END {f}; BEGIN {p} k := chr(i + trunc(f(n))); END {p}; BEGIN {test} p(j + k + n) END {test}.
Nested Scopes and the Symbol Table Stack PROGRAM Test; VAR i, j, k, n : integer; PROCEDURE p(j : real); VAR k : char; FUNCTION f(x : real) : real; VAR i:real; BEGIN {f} f := i + j + n + x; END {f}; BEGIN {p} k := chr(i + trunc(f(n))); END {p}; BEGIN {test} p(j + k + n) END {test}. Each routine’s name is defined in the parent’s scope. Each routine’s local names are defined in that routine’s scope.
Parsing Programs, Procedures, and Functions • Classes ProgramParser and DeclaredRoutineParserare subclasses of DeclarationsParser. • DeclaredRoutineParser depends on VariableDeclarationsParser to parse the formal parameter list.
Class DeclaredRoutineParser • Parse any declared (programmer-written) routine: • a procedure • a function • the program itself
DeclaredRoutineParserMethods • parse() • First call parse_routine_name() • Enter the routine name into the enclosing scope’s symbol table. • Push a new symbol table for the routine onto the symbol table stack. • Pop off the symbol table for the routinewhen done parsing the routine.
Procedure and Function Calls • A procedure call is a statement. • A function call is a factor. • If there are no actual parameters, there are also no parentheses.
Class Predefined • Load the global symbol table with the predefined identifiers. • integer, real, char, boolean, true, false. • Now it must also load the global symbol table with the identifiers of the predefined procedures and functions. • write, writeln, read, readln • abs, arctan, chr, cos, eof, eoln, exp, ln, odd, ord, pred, round, sin, sqr, sqrt, succ, trunc
Classes for Parsing Calls • A new statement parser subclass: CallParser. • CallParser has two subclasses, CallDeclaredParser and CallStandardParser. • CallStandardParserparses calls to the standard (predefined) Pascal routines. • Each parse() method returns the root of a parse subtree._
Class CallParser • CallParser.parse() calls either: • CallDeclaredParser.parse() • CallStandardParser.parse() • Protected method parseActualParameters()is used by both subclasses.
Formal Parameters and Actual Parameters • Formal parameters: In a procedure or function declaration: • Actual parameters: In a procedure or function call:
CallParser::parse_actual_parameters() • Example call to procedure proc:proc(i, -7 + m, a[m], v, y, a, t, 'r')generates the parse tree: The CALL node can have a PARAMETERS node child. <CALL id="proc" level="1" line="81"> <PARAMETERS> <VARIABLE id="i" level="1" type_id="integer" /> <ADD type_id="integer"> <NEGATE> <INTEGER_CONSTANT value="7" type_id="integer" /> </NEGATE> <VARIABLE id="m" level="1" type_id="integer" /> </ADD> <VARIABLE id="a" level="1" type_id="real"> <SUBSCRIPTS type_id="real"> <VARIABLE id="m" level="1" type_id="integer" /> </SUBSCRIPTS> </VARIABLE> <VARIABLE id="v" level="1" type_id="real" /> <VARIABLE id="y" level="1" type_id="real" /> <VARIABLE id="a" level="1" type_id="arr" /> <VARIABLE id="t" level="1" type_id="boolean" /> <STRING_CONSTANT value="r" type_id="char" /> </PARAMETERS> </CALL> The PARAMETERS node has a child node for each actual parameter.
Parsing Calls to the Standard Routines • Class CallStandardParser parses calls to the standard procedures and functions. • These calls are handled as special cases. • Method parse() calls private ad hoc parsing methods.
Parsing Calls to the Standard Routines • Example: method parseAbsSqr() • One integer or one real actual parameter. • The return type is the same as the parameter type. • Each actual argument to standard procedure write or writeln can be followed by specifiers for the field width and the number of decimal places after the point. • Example: writeln(str:10, k:12, x:20:5)
Pascal Syntax Checker IV • Now we can parse entire Pascal programs! • Demo • Onward to executing entire Pascal programs!
Assignment #5: Time Type • Add a built-in time data type to Pascal. • Add the type to the global symbol table. • Implement it as a record type with integer fields hour, minute, and second. • Field hour should be limited to values 0 through 23, and fields minute and second should each be limited to values 0 through 59.
Assignment #5: Time Type TimeTest.pas • Be able to declare timevariables and assign values to their fields. • Compile and executeTimeTest.pas. • Each valid assignmentstatement should printthe assignment message. PROGRAM TimeTest; VAR now, later: time; wrong: time; BEGIN now.hour := 12; now.minute := 15; now.second := 37; later := now; wrong.hour := 24; wrong.minute := 60; wrong.second := 0; END.
Assignment #5, cont’d • Start with the C++ source files from Chapter 12. • 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.
Assignment #5, 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 14.