We will be including more of java into Tea:
compilation_unit --> class_declaration ";"
class_declaration --> <modifier> "class" name ["extends" class_name]
"{" <method_declaration | variable_declaration> "}"
method_declaration --> <modifier> type name "(" ")" "{" statement_block "}"
variable_declaration --> <modifier> type name declarative_statement
....
modifier --> "public" | "static"
variable_type --> "int" | class_name
class_name --> name
In the past students have found it useful to also put out AST nodes for declarations, but that is up to you.
Input: The usual programs with declarations plus one which tests your new constructs:
#1
public class input_a {
public void main() {
int a, b, c, p, xyz;
a = 3;
xyz = a + b + c - p / 4;
a = xyz * ( p + 9 );
p = a - xyz - p;
}
}
#2
void input_b() {
if ( i > j )
i = i + j;
elsif ( i < j )
i = 1;
}
#3
void input_c() {
while ( i < j && j < k ) {
k = k + 1;
while ( i == j )
i = i + 2;
}
}
Output: Each program, followed by its AST, followed by its
symbol table. As an extra, print the entries out in alphabetical order. The table might
look something like (from Theo's):
public class input_a {
public void main() {
int a, b, c, p, xyz;
a = 3;
xyz = a + b + c - p / 4;
a = xyz * ( p + 9 );
p = a - xyz - p;
}
}
c
class = variable
type = int
dline = 3
scope = 2
references:
6
3
b
class = variable
type = int
dline = 3
scope = 2
references:
6
3
a
class = variable
type = int
dline = 3
scope = 2
references:
8
7
6
5
3
main
class = method
dline = 2
other = void
modifier = public
scope = 1
references:
2
p
class = variable
type = int
dline = 3
scope = 2
references:
8
7
6
3
xyz
class = variable
type = int
dline = 3
scope = 2
references:
8
7
6
3
input_a
class = class
dline = 1
modifier = public
scope = 0
references:
1
Do not confuse the java word class with the "class" attribute
in a symbol table! Implement your Symbol Table as an abstract data type. That is, use statements such as enter (SymbolTable,Name), rather than enter (SymbolTable[i],Name). Ask me if this is unclear.
Here is an excerpt from Theo's:
options {
IGNORE_CASE = false;
OPTIMIZE_TOKEN_MANAGER = true;
MULTI = false;
STATIC = false;
}
PARSER_BEGIN(tea)
import java.io.*;
import java.util.*;
public class tea {
public static Hashtable ST = new Hashtable();
int scope = 0;
public static void main(String[] args) throws ParseException,
FileNotFoundException
{
String temp;
STO temp2;
if ( args.length < 1 ) {
System.out.println("Please pass in the filename for a parameter.");
System.exit(1);
}
tea parser = new tea( new FileInputStream(args[0]) );
SimpleNode root = parser.program();
// root.dump("");
Enumeration t = ST.keys();
while ( t.hasMoreElements() == true ) {
temp = (String)t.nextElement();
temp2 = (STO)ST.get(temp);
System.out.println(temp);
if ( temp2.Sclass != null )
System.out.println(" class = " + temp2.Sclass);
if ( temp2.type != null )
System.out.println(" type = " + temp2.type);
if ( temp2.dline != 0 )
System.out.println(" dline = " + temp2.dline);
if ( temp2.other != null )
System.out.println(" other = " + temp2.other);
if ( temp2.modifier != null )
System.out.println(" modifier = " + temp2.modifier);
System.out.println(" scope = " + temp2.scope);
System.out.println(" references:");
Stack temp3 = (Stack)temp2.references.clone();
while ( temp3.empty() == false )
System.out.println(" " + temp3.pop());
}
// System.out.println("Parse completed.");
}
public void Add_Reference(String Name, int LineNo) {
Integer tint = new Integer(LineNo);
STO temp = (STO)ST.get(Name);
if ( temp.references.peek().equals(tint) == false ) {
temp.references.push(tint);
ST.put(Name,temp);
}
}
}
public class STO extends Object {
int dline; // Declaration Line Number
int scope; // scope of the object
String other; // "Other" string associated with class
String modifier; // Modifier of class
String Sclass; // class
String type; // type
Stack references = new Stack();
public STO(String Class, String Type, int Dline, String Modifier, String Other, int Scope ) {
Sclass = Class;
type = Type;
dline = Dline;
other = Other;
modifier = Modifier;
scope = Scope;
references.push(new Integer(dline));
}
}
PARSER_END(tea)
SKIP: /* Whitespace */
{
"\t"
| "\n"
| "\r"
| " "
}
TOKEN: /* Most Things */
{
....
}
SimpleNode program() :
{}
{
compilation_unit() <EOF> { return jjtThis; }
}
void compilation_unit() #void :
{}
{
class_declaration()
}
void class_declaration() :
{
Token t1, t2, t3=null;
}{
t1=<MODIFIER> <CLASS> t2=<NAME> [<EXTENDS> t3=<NAME>] <LBRACE>
{scope++;}(method_declaration())* {scope--;}<RBRACE>
{
jjtThis.value = t1.image; // modifier
jjtThis.ovalue = t2.image; // name
if ( t3 != null )
jjtThis.ovalue2 = t3.image; // other
jjtThis.bline = t1.beginLine; // line
ST.put(t2.image,new STO("class",null, t1.beginLine, t1.image, jjtThis.ovalue2, scope));
}
}
/*
void variable_declaration() :
{
Token t1;
}{
t1=<MODIFIER> declarativestatement()
{ jjtThis.value = t1.image;
jjtThis.bline = t1.beginLine; }
}
*/
...
void assignmentstatement() :
{
Token temp;
} {
temp=<NAME> [<ASSIGNOP> expression()]
{
jjtThis.value = temp.image;
jjtThis.bline=temp.beginLine;
if ( ST.get(temp.image) != null )
Add_Reference(temp.image,temp.beginLine);
}
}
...