Tải bản đầy đủ (.pdf) (5 trang)

Tutorial 5 solutions

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (68.99 KB, 5 trang )

Week 11 Solutions
Symbol Tables, Type Checking and Jasmin Code
1. Write method insert(SymEntry sym) for a linear symbol table.
Object insert(SymEntry newSym) {
int endOfScope = scope.peek();
for (int i = tab.size() - 1; i >= endOfScope; i--) {
SymEntry sym = symTable.elementAt(i);
if (sym.getLexeme().equals(newSym.getLexeme()))
return sym;
}
symTable.push(newSym);
return null;
}
2. Write type expressions for the folowing types
a. An array of pointers to floats, where the array index ranges from 1 to 100
array(1..100,pointer(float))
b. A two-dimensional array of integers whose rows are indexed from 0 to 9 and whose
columns are indexed from -10 to 10
array(0..9,array(-10..10,integer))
3. Given the following grammar:
P→DF
D → T id ; D | ∈
F → T id (T id) { D L } F | ∈
L→SL|∈
S → id = E ; | { D L }
T → int | float
E → INTLIT | FLOATLIT | id | id (E)
Assume that a ProductType class and FunctionType are declared as follows
class ProductType extends Type {
Type e1Type;
Type e2Type;


}
class FunctionType extends Type {
Type paraType;
Type returnType;
}


Write translation schemes:
(Note that for each translation scheme, we assume that the semantic actions of its
previous schemes have been activated. We don’t rewrite these actions unless we need to
modify them. For example, in 3.b we write
D → T id ; {insert(new SymEntry(id,T.type))} D
because there is no need to concern ourselves with the value returned by insert.
However, in 3.c, when needing to check the value, we change it to
D → T id ; {sym = insert(new SymEntry(id,T.type));
…}
D
)
a. to keep track of scope (using enterScope, exitScope).
P → {enterScope()} D F {exitScope()}
F → T id ({enterScope()} T id) { D L } {exitScope()} F
S →{{enterScope()} D L }{exitScope()}
b. to detect an undeclared variable.
D → T id ; {insert(new SymEntry(id,T.type))} D
F → T1 id1 (T2 id2 {insert(new SymEntry(id2,T2.type))}
){DL}F
S → id {sym = lookup(id.Lexeme);
if (sym == null)
throw new UndeclaredVariableException(id);}
=E;

E → id {sym = lookup(id.Lexeme);
if (sym == null)
throw new UndeclaredVariableException(id);}
T → int {T.type = Type.INT}
| float {T.type = Type.FLOAT}
c. to detect a redeclared variable.
D → T id ; {sym = insert(new SymEntry(id,T.type));
if (sym instanceof SymEntry)
throw new RedeclaredVariableException(id);}
D
{ entry = new SymEntry(id1,null);
F → T1 id1
sym = insert(entry);
if (sym != null
&& !sym.type instanceof FunctionType)
throw new RedeclaredVariableException(id);}
(T2 id2) {tmp = new FunctionType(T2.type,T1.type);
entry.setType(tmp);}
{DL}F


d. to detect an undeclared function.
E → id ({ sym = lookup(id.Lexeme);
if (sym == null)
throw new UndeclaredFunctionException(id); }
E)
e. to detect a redeclared function.
F → T1 id1
{entry = new SymEntry(id1,null)
sym = insert(entry);

if (sym != null
&& sym.type instanceof FunctionType)
throw new RedeclaredFunctionException(id1);}
(T2 id2) {tmp = new FunctionType(T2.type,T1.type);
entry.setType(tmp);}
{DL}F
f. to detect a reference to a variable as a function
E → id ({ sym = lookup(id.Lexeme);
if (sym != null
&& !sym.type instanceof FunctionType)
throw new ReferVarAsFuncException(id); }
E)
g. to detect a reference to a function as a variable
S → id {sym = lookup(id.Lexeme);
if (sym != null
&& sym.type instanceof FunctionType)
throw new ReferFuncAsVarException(id);}
=E;
E → id {sym = lookup(id.Lexeme);
if (sym != null
&& sym.type instanceof FunctionType)
throw new ReferFuncAsVarException(id);}
h. to detect a type mismatch
S → id
{sym = lookup(id.Lexeme);}
= E ; {if (sym != null
&& !sym.type.isLeftCompatibleTo(E.type))
throw new TypeMismatch(=); }



E → id ( {sym = lookup(id.Lexeme);}
E1 {if (sym != null
&& sym.type instanceof FunctionType) {
FunctionType ft = (FunctionType) sym.type;
if (!ft.paraType.isLeftCompatibleTo(E1.type))
throw new TypeMismatch(getLookaheadToken());
else E.type = ft.returnType;
}}
)
E → INTLIT {E.type = Type.INT; }
| FLOATLIT {E.type = Type.FLOAT;}
| id
{ sym = lookup(id.Lexeme);
if (sym != null )
E.type = sym.type;}
4. Given the following grammar that generates a function:
F → T id (D) { S }
D → T id D | ∈
T → int | boolean
S → id (L)
L→EL|∈
E → INTLIT | BOOLLIT
Write translation schemes to throw:
a. TooManyArgException
F → T id {tmp = new SymEntry(id,null);
insert(tmp);}
(D) {tmp.setType(new FunctionType(D.type,T.type))}
{S}
D → T id D1 {if (D1.type != null)
D.type = new ProductType(T.type,D1.type);

else
D.type = T.type; }
| ∈ { D.type = null; }
T → int
{T.type = Type.INT;}
| boolean {T.type = Type.BOOLEAN;}
S → id
{sym = lookup(id.Lexeme);
if (sym != null) {
FunctionType ft = (FunctionType) sym.type;
L.iType = ft.paraType;
}}
(L)


L → {if (L.iType == null)
throw new TooManyArgException(getLookaheadToken());}
E {if (L.iType instanceof ProductType)
L1.iType = ((ProductType)L.iType).e2Type;
else L1.iType = null; }
L1
b. TooFewArgException
L → ∈ {if (L.iType != null)
throw new TooFewArgException(getLookaheadToken());}
c. TypeMismatchException
L → E {if (L.iType instanceof ProductType) {
ProductType pt = (ProductType)L.iType;
L1.iType = pt.e2Type;
if (!pt.e1Type.isLeftCompatibleTo(E.type))
throw

new TypeMismatchException(getLookaheadToken());
}
else if (L.iType != null &&
!L.iType.isLeftCompatibleTo(E.type))
throw
new TypeMismatchException(getLookaheadToken());
else L1.iType = null; }
L1
5. Write Jasmin code of the following expression:
c = (a + b[a] ) * 10.2F
where c is a float variable, a is an integer variable and b is an array of integers
iload_1
aload_2
iload_1
iaload
iadd
i2f
ldc 10.2
fmul
fstore_3

;a
;b
;b[a]

;c




Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×