Welcome.
Contact Us
Professor: Garo Bournoutian (garo@ucsd.edu)
Head Tutor: Victor Alor(valor@ucsd.edu) &
Eduardo Ramirez (eduardo@ucsd.edu)
Other Coworkers:
https://cseweb.ucsd.edu/~gbournou/CSE131/hours.html
Overview
Input
test.rc
-Syntactically correct
-Semantically incorrect
test.rc
-Syntactically correct
-Semantically correct
Output
Project 1
Error
Messages
(semantic analysis)
Project 2
(code gen)
a.out /
executable
Compilation Phases
Lexical Analysis (Lexer.java)
token parsing (already done for you)
Syntactic and Semantic Analysis (rc.cup,
MyParser.java)
Project 1
Semantic Analysis: does the meaning of the
written code make sense?
Code Gen
Project 2
Completing Phase 0
Any questions from Phase 0?
Edit the grammar file (rc.cup) to support new rules.
new x;
delete x;
Eliminate bugs in starter code
FIFO -> LIFO
Modify grammar to allow for unary expressions
Support hexadecimal and octal numbers
rc.cup
rc.cup syntax
Expr ::=
rc.cup syntax
Expr ::= Designator:LABEL T_ASSIGN Expr
{:
-- ACTION CODE -RESULT = ((MyParser) parser).DoAssignExpr (LABEL);
:}
|
Expr0:_1
{:
-- Place return value of rule in RESULT -RESULT = _1;
:}
;
Conversion
To explain how the previous blocks work.
Imagine that rc.cup is converted into a larger parser.
One of this parsers fields is a MyParser object, the other
class you will be working on.
Imagine that the previously profiled rules are converted to the
below.
Class BiggerParser {
Parser parser = new MyParser();
Public STO Designator T_ASSIGN Expr(Label){
Object RESULT = ((MyParser) parser).DoAssignExpr (Label);
return RESULT;
}
Public STO Expr0(_1){
Object RESULT = _1
return RESULT;
}
11
MyParser.java
The other main file to modify.
Contains all the methods for semantic analysis,that
will be called from rc.cup
Modify the functions as needed
You may add, remove or change them
SymbolTable.java
Look into this file to understand how the backing data
structure of your compiler, the Symbol Table, is
constructed
Understand relationship between Symbol Table and
Scope
Symbol Table is made of a stack of Scopes
Note difference between m_stkScopes vs
m_scopeGlobal
int x = 2;
|
GlobalDecls
|
GlobalDecl
|
VarDecl
OptStatic
DecoratedType
T_ID
OptArrayList
OptInit
....
T_ASSIGN
|
T_INT
Expr
|
Expr0...Expr8
|
Designator...Designator3
|
T_INT_LITERAL
STO Hierarchy
STO
FuncSTO
StructdefSTO
ExprSTO
ConstSTO
VarSTO
ErrorSTO
Types Hierarchy
Type
BasicType
NumericType
IntType
VoidType
BoolType
ArrayType
CompositeType
StructType
FloatType
PointerType
NullPointerType
Useful methods
Treat the provided STO classes as templates:
isFloat(), isInt(), isArray().
Tailor each one to meet a specific set of requirements
Leverage Javas instanceof operator.
All types should have:
isAssignableTo(Type t) -- coercible type
isEquivalentTo(Type t) -- same type
getSize() -- return types size
More information required for complex types:
Arrays need array dimensions and element type
Structs need to keep track of struct members
What to return when sizeof() is called
Type Setting
int x;
float y;
function :
{
x
y
x
}
Why ok?
void main()
= 1; // OK
= x + 2.2; // OK
= y; // ERROR
Why an error?
Type Checking
Consider the line: y = x + 2.2;
From rc.cup:
Expr7 ::= Expr7:_1 AddOp:_2 Expr8:_3
{:
RESULT = _1;
:}
Type Checking
How will we grab types of different STOs to check
their compatibility?
One approach is for each operator create a method
in Myparser that does the following:
if(a.getType().isEquivalentTo(b.getType())){
//Perform operation and generate STO with correct type
//Return STO
}
Type Checking
In MyParser.java, consider adding a function that will
check expressions using a given operator:
STO DoBinaryExpr(STO a, Operator o, STO b) {
STO result = o.checkOperands(a, b);
if (result instanceof ErrorSTO) {
// handle propagating errors
}
//do stuff...
return result ;
}
Operator Hierarchy
Operator
BinaryOp
ArithmeticOp
AddOp,
MinusOp,
etc
UnaryOp
BooleanOp
BitwiseOp
ComparisonOp
AndOp
OrOp
BwAndOp,
BwOrOp,
XorOp
EqualOp,
NotEqualOp,
LessThanOp,
etc
NotOp,
IncOp,
DecOp
CheckOperands
Then each Operator class can have something like this...
STO checkOperands(STO a, STO b) {
aType = a.getType();
bType = b.getType();
if (!(aType instanceof NumericType) || !(bType instanceof
NumericType)) {
// error
return new ErrorSTO(...);
} else if (aType instanceof IntType && bType instanceof IntType) {
// return ExprSTO of int type
} else {
// return ExprSTO of float type
}
}
Error Reporting
If a violation of a spec rule occurs e.g. adding a bool
and an int, then print the corresponding error
Only print error messages defined in ErrorMsg.java
Only report FIRST error encountered in a statement
This can be done by using the ErrorSTO
ErrorSTO
Unlike other STOs this one isnt used to store or
characterize values in your program.
Rather it is used to propagate errors.
If an error is encountered, create an ErrorSTO and
propagate it up the parse tree
This informs other higher level rules that an error
has occurred,so as to prevent further error
checking and unnecessary print statements.
Functions
Hey recall that were building a static, one-pass
compiler.
As a consequence we parse code as we go along.
As a function is parsed, we semantically check its
declaration and body in one go.
So there is no need to store/remember code in body
Functions
For Project 1
Type check the statements in the body of the
function.
Validate the return logic of the function.
Check if it is a valid type
If return by reference check if the value can be
returned by reference.
Add support for function overloading (Phase 2)
FuncSTO
The processing of a function culminates in the
creation of a FuncSTO.
The purpose of this STO is to carry information about
its corresponding function.
Should store information such as:
Return type
Return by reference (like a flag to indicate)
Parameters (can just be type for each parameter
as well as flag for pass by reference, or perhaps
a Vector<STO> of all the parameter VarSTOs)
Function Definition
FuncDef ::=
Whats
the job of
each
method?
Function Example
function : bool foo(float a, float b, float &c) {
bool x;
x = a > b;
x = (a + c) <= 2;
return x;
}
Function Calls
When making a function call:
1.Store the callsite arguments into a Vector of
STOs
2.Get the matching FuncSTO from the symbol
table. If no such FuncSTO exists generate the
corresponding error
3. If the corresponding FuncSTO exists check its
parameters with the arguments at the callsite. If
they fail to match generate the corresponding
error.
4. Check that its return type is being correctly used.
Return by Value
vs.
Return by Reference
Return by Value
In the function, the return expression just has to
be assignable to the functions return type
At the callsite, the resulting expression is an rval
Return by Reference
In the function, the return expression has to have
an equivalent type AND must be a modifiable
lval
At the callsite, the resulting expression results in a
modifiable lval
Important Tips
Read through the spec to see where you are going -plan ahead
Do not simply dump code to make things work,
design is very important and will affect your Project
2
Thinking ahead will save a lot of time and pain later.