Abstract Syntax Trees are a "pared down" parse tree. Each node is an element of the language. The non-leaf nodes represent operators while the leaf nodes represent operands.
Example 1 Abstract Syntax Tree for a + b where a is opnd1 and b is opnd2.
In parenthesized form, this could be written:
(plus ("a" "b") ) or (+ (a b ) )
or indenting,
(plus
("a" "b")
)
The production that relates to such a node is
then we can add attributes and functions such as:
This might be printed out:
(IF ("<" ("a" "b") := ("m" 2") ) )
or, indenting,
(IF
(
"<" ("a" "b")
:= ("m" 2")
)
)
Example 3 Abstract Syntax Tree for
WHILE (a < b)
m = 2 ;
This might be printed out:
(WHILE ("<" ("a" "b") ) := ("m" 2") ) )
or with indenting
(WHILE (
"<" ("a" "b")
":=" ("m" 2")
)
)
(Other indentings possible here) Consider the following program:
void input_a() {
a = b3;
xyz = a + b + c - p / q;
a = xyz * ( p + q );
p = a - xyz - p;
}
Its ast might be printed out:
Unit [
Line(1)
(void (input_a)
Line (2)
(:=
(a, b3) )
Line (3)
(:=
(xyz, +
(a +
(b -
(c /
(p q))))))
Line (4)
(:=
(a *
(xyz +
(p q))))
Line (5)
(:=
(p -
(a -
(xyz p))))
Line (6)
EndVoid) ]
The output need not look exactly like that above, but you should print out
line numbers and somehow show the ast structure. You will use the JJTree tool to build your ast's. Below is an excerpt from the solution:
options {
IGNORE_CASE = false;
OPTIMIZE_TOKEN_MANAGER = true;
MULTI = false;
STATIC = false;
}
PARSER_BEGIN(tea)
import java.io.*;
public class tea {
public static void main(String[] args) throws ParseException,
FileNotFoundException
{
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("");
System.out.println("Parse completed.");
}
}
PARSER_END(tea)
SKIP: /* Whitespace */
{
"\t"
| "\n"
| "\r"
| " "
}
TOKEN: /* Most Things */
{
<IF: "if">
| <ELSE: "else">
| <TYPE: "void">
| <VARIABLE_TYPE: "int">
| <LPAREN: "(">
| <RPAREN: ")">
| <LBRACE: "{">
| <RBRACE: "}">
| <COMMA: ",">
| <SEMICOLON: ";">
| <WHILE: "while">
| <DO: "do">
| <FOR: "for">
}
TOKEN: /* Expression Tokens */
{
<ADDOP: "+" | "-">
| <MULOP: "*" | "/" | "%">
| <ASSIGNOP: "=">
| <NOT: "!">
| <AND: "&&">
| <OR: "||">
| <RELOP: "!=" | "==">
| <LTGT: ">" | "<" | ">=" | "<=">
}
TOKEN: /* Generic Name & Number */
{
<NUMBER: (["0"-"9"])+>
| <NAME: ["a"-"z","A"-"Z"] (["a"-"z","A"-"Z","0"-"9","_"])*>
}
SimpleNode program() :
{}
{
method_declaration() <EOF> { return jjtThis; }
}
void method_declaration() :
{
Token tok1, tok2;
} {
(tok1=<TYPE>|tok1=<VARIABLE_TYPE>) tok2=<NAME> <LPAREN> <RPAREN>
<LBRACE> statement_block() <RBRACE>
{
jjtThis.ovalue = tok1.image;
jjtThis.value = tok2.image;
}
}
void statement_block() #void :
{}
{
( statement() )*
}
void statement() #void :
{}
{
simplestatement() <SEMICOLON>
| compoundstatement()
| <LBRACE> statement_block() <RBRACE>
}
void simplestatement() #void :
{}
{
declarativestatement() | assignmentstatement()
}
void declarativestatement() :
{
Token tok1;
} {
tok1=<VARIABLE_TYPE> assignmentstatement() (<COMMA> assignmentstatement())*
{
jjtThis.value = tok1.image;
}
}
void assignmentstatement() :
{
Token temp;
} {
temp=<NAME> [<ASSIGNOP> expression()]
{
jjtThis.value = temp.image;
}
}
Important notes:
Before you begin, you may want to download my SimpleNode.java
The process is:
Run your program on the usual inputs. Hand in (at a minimum) : your source files, the input programs, and the output AST's. Continue to document your "package".