Anda di halaman 1dari 39

CSE 131 Fall15 Discussion 1

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

Requisite Prior Knowledge

OOD (Object-Oriented Design)


Inheritance
Polymorphism
Some C/C++
SPARC assembly

Overview

Brief overview of Project 1 and Project 2


Explanation of rc.cup and MyParser.java
Parse Trees
STOs, Types and Operators Hierarchies
Phase 1
Type Checking
Error Reporting
Functions

High Level View

Input
test.rc
-Syntactically correct
-Semantically incorrect

test.rc
-Syntactically correct
-Semantically correct

Single code package

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

One of the main files your will be modifying.


Grammar file for Reduced-C (RC) language.
Contains all the parsers rules
Methods in MyParser.java will get called in action
code blocks

rc.cup syntax

Expr ::=

Designator:_1 T_ASSIGN Expr


{:
RESULT = ((MyParser) parser).DoAssignExpr (_1);
:}
Expr0:_1
{:
RESULT = _1;
:}

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

Parse Tree (Simplified)


Program
|
OptGlobalDecls

int x = 2;

|
GlobalDecls
|
GlobalDecl
|
VarDecl

OptStatic

DecoratedType

T_ID

OptArrayList

OptInit

....

T_ASSIGN

|
T_INT

Expr
|
Expr0...Expr8
|

Designator...Designator3
|
T_INT_LITERAL

CSE 131 STOs and Types: What Are They? Do They


Do Things?? Let's Find Out!
All STOs(symbol table objects) are:
Basic units of the program (e.g. values, vars)
Can be Modifiable or Not Modifiable
Can be Addressable or Not Addressable
Take care that modifiability and addressability are set
correctly for each STO when it is created.
Structure:
abstract class STO
{
private String m_strName;
private Type m_type;
private boolean m_isAddressable;
private boolean m_isModifiable;
}

STO Hierarchy

STO

FuncSTO

StructdefSTO

ExprSTO

ConstSTO

VarSTO

ErrorSTO

This is only a suggestion, but a useful one


Notice that STO methods are overridden by child STO classes
Example: isVar() overridden in VarSTO

CSE 131 STOs and Types: What Are They? Do


They Do Things?? Let's Find Out!
Used to create an organized approach for type
checking
Need to keep track of basic types (ints, floats, bools),
pointer types, array types and struct types.
What kind of information should be stored in a Type.

Types Hierarchy

Type

BasicType

NumericType

IntType

VoidType

BoolType

ArrayType

CompositeType

StructType

FloatType

Only a suggestion, but a useful one!

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

All STOs must have internal Type set to allow for


type checking.
Failure to set types or setting it incorrectly will trigger
no or incorrect error messages

Type Setting Example


VarDecl ::=

OptStatic:_1 DecoratedType:_2 T_ID:_3 OptArrayList:_4 OptInit:_5


{:
((MyParser) parser).DoVarDecl (_3, ???);
:}

Pass the type bubbled up from DecoratedType to DoVarDecl() in MyParser.java...


void DoVarDecl(String id, Type t)
{
if (m_symtab.accessLocal(id) != null)
{
m_nNumErrors++;
m_errors.print(Formatter.toString(ErrorMsg.redeclared_id, id));
}
VarSTO sto = new VarSTO(id, pass in Type);
m_symtab.insert(sto);
}

Type Checking Example


Once types have been established for each STO, type
checking can be done.

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;
:}

Based on AddOp (+ or -) we need to check whether


operands are indeed valid for addition or subtraction,
and if valid return ExprSTO...

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
}

Lets construct a better approach using object


oriented design.

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 ;
}

Delegate type checking and STO generation to


operator objects.

Operator Hierarchy

Operator

BinaryOp
ArithmeticOp

AddOp,
MinusOp,
etc

UnaryOp

BooleanOp

BitwiseOp

ComparisonOp

AndOp
OrOp

BwAndOp,
BwOrOp,
XorOp

EqualOp,
NotEqualOp,
LessThanOp,
etc

NotOp,
IncOp,
DecOp

Once again, a suggestion, but most important one

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 ::=

T_FUNCTION T_COLON ReturnType:_1 OptRef:_2 T_ID:_3


{:
((MyParser) parser).SaveLineNum ();
((MyParser) parser).DoFuncDecl_1(_3);
:}
T_LPAREN OptParamList:_4 T_RPAREN
{:
((MyParser) parser).DoFormalParams(_4);
:}
T_LBRACE OptStmtList
{:
((MyParser) parser).DoFuncDecl_2();
:}
T_RBRACE

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;
}

FuncSTO for this function would have:


Identifier foo
Return type bool
Parameter count 3
Parameters: value float, value float, reference float

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.

Function Return Types


Inside the function body
Type of the return expression needs to be checked
against the declared return type of the function
At the callsite
The function call behaves just like any other
ExprSTO
The return type becomes the type of the
expression
Only functions can have void type
void isnt equivalent or assignable to anything ever
(including itself)
void does not equal nullptr

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.

Until next time...


Find a partner if you need one
Set up version control - SVN, Git, etc.
Must be kept PRIVATE
Go to lab hours if youre stuck
Keep up with Piazza
Lots of helpful material will be posted there
Please read others posts before asking the same
question

Anda mungkin juga menyukai