In this part of the project, you will modify parser.y to create an abstract syntax tree. Do not attempt other stages of the project before AST functions work. We are providing header files and a printTree() routine. So, your job is to add corresponding semantic actions to the parser to populate the tree. However, more information might be necessary for efficient semantic analysis. Try to keep modifications of ast.h ant printTree to the minimum.
/* types of objects */
typedef enum tempObjType {
DECL_O, /* declaration */
STMT_O, /* statement (no return) */
EXP_O, /* expression (return) */
LIT_O, /* literal (constant) */
ID_O /* identifier */
} ObjType;
/* data types */
typedef enum tempDataType {
INTEGER_D, /* integer */
BOOLEAN_D, /* boolean */
STRING_D, /* string */
VOID_D /* none */
} DataType;
/* This is used to store literal values */
typedef struct {
DataType type; /* type of literal stored */
union litValue_tag {
char* str; /* value for string constant */
int num; /* value for numeric constant, */
/* or 0 (false) or 1 (true) for boolean constants */
} litValue;
} Value;
typedef struct tempObject* ObjectP;
typedef struct tempArgs* ArgsP;
typedef Value* ValueP;
typedef struct tempDecl* DeclP;
typedef struct tempFArgs* FArgsP;
/* Store information about the objects - either a */
/* command string or information about literals */
typedef union {
ValueP litVal; /* information about literals */
char* name; /* everything else is a character */
/* string with the name of the function or operator */
} ValueInfo;
/* Object structure. Used to store anything that */
/* will result in code generation: expressions, */
/* statements, declarations, etc. */
typedef struct tempObject {
ObjType type;
DeclP decl;
ValueInfo value;
ArgsP args;
} Object;
/* Linked list of objects. Used to specify parameters */
/* to statements and expressions. */
typedef struct tempArgs {
ObjectP object;
ArgsP next;
} Args;
/* Declarations of variables and functions */
typedef struct tempDecl {
DataType type; /* type */
char* name; /* variable/func name */
FArgsP fargs; /* formal arguments (if any) */
ObjectP bound; /* array bounds (if any) */
ObjectP object; /* code associated with it */
DeclP next; /* next declaration */
} Decl;
/* Formal arguments (to functions and procedures) */
typedef struct tempFArgs {
char* name; /* argument name */
DataType type; /* argument datatype */
FArgsP next; /* next argument */
} FArgs;
{
Statement Start: ASSIGN,
{
Identifier Object: x,
}
{
Literal Object: integer <2>,
}
}
x is an identifier with value "x" (indicating that "x" should
be looked up to determine its type and l-value). 2 is a literal, with
type INTEGER_D and value 2. x is assigned 2 in a
statement. The value for this statement is a command "ASSIGN" with
two arguments - x and 2.
In general, all commands are represented as strings. The possible commands are:
"NOP" - no operation "SEQ" - statement sequence "ASSIGN" - assignment statement "EXIT" - EXIT statement "PUT" - PUT statement "GET" - GET statement "SKIP" - SKIP statement "IF" - IF statement "RET" - RETURN statement "WHILE" - WHILE statement "LOOP" - LOOP statement "UMINUS" - unary operation - "PLUS" - binary operation + "MINUS" - binary - "TIMES" - binary * "DIV" - binary / "POWER" - binary power "NOT" - not operation "AND" - and operation "OR" - not operation "EQ" - equality "NEQ" - inequality "GEQ" - greater than or equal to "GT" - greater than "LT" - less than "LEQ" - less than or equal toand names of identifiers. No other commands should be necessary.
Declarations are entered into the Decl data structure. It is a linked list of declarations consisting of type of variable (return type of function, void for procedure), its name, its arguments, and code. Declarations are pointed to by a scope (represented as Object). If the scope consists of just declarations, an empty Object (containing command "NOP") is creating, pointing to the declaration.
Program
=================================================
begin
put "hello, world"
end
AST printout
=================================================
{
Scope Start: PUT,
+++ Arguments Start +++
{
Literal Object: string <"hello, world">,
}
+++ Arguments End +++++
}
Program
=================================================
begin
put "hello", skip
put "world"
end
AST printout
=================================================
{
Scope Start: SEQ,
+++ Arguments Start +++
{
Statement Object: PUT,
+++ Arguments Start +++
{
Literal Object: string <"hello">,
}
{
Statement Object: SKIP,
}
+++ Arguments End +++++
}
{
Statement Object: PUT,
+++ Arguments Start +++
{
Literal Object: string <"world">,
}
+++ Arguments End +++++
}
+++ Arguments End +++++
}
Program
=================================================
/* A program using arrays but not functions or procedures */
begin
integer : n
integer: array[n]
n <- 123
array[2] <- 4
end
AST printout
=================================================
{
Scope Start: SEQ,
--- Declaration Starts ---
integer n
integer array [
{
Identifier Object: n,
}
]
--- Declaration Ends -----
{
Statement Object: ASSIGN,
{
Identifier Object: n,
}
{
Literal Object: integer <123>,
}
}
{
Statement Object: ASSIGN,
{
Identifier Object: array,
{
Literal Object: integer <2>,
}
}
{
Literal Object: integer <4>,
}
}
}
}
Program
=================================================
begin
integer function hello (integer : i, integer : j )
begin
end
procedure foo (boolean : b)
begin
boolean function trueORfalse (integer: guess)
begin
return(FALSE)
end
end
end
AST printout
=================================================
{
Scope Start: NOP,
--- Declaration Starts ---
integer hello (integer : i, integer : j)
{
Scope Start: NOP,
}
string foo (boolean : b)
{
Scope Start: NOP,
--- Declaration Starts ---
boolean trueORfalse (integer : guess)
{
Scope Start: RET,
{
Literal Object: boolean <0>,
}
}
--- Declaration Ends -----
}
--- Declaration Ends -----
}
/* AST: A long example */
/* A program using input and output */
/* Computation of the harmonic series: 1 + 1/2 + 1/3 + 1/4 + ... */
begin
integer : Terms
integer :Num_1
integer : Sum
put "Please, enter the number of Term to sum"
get Terms
/* The computation is done here ! */
/* comments are bracketed by * and / */
while Num_1 not = terms do
Sum <- Sum + (1/Num_1)
Num_1 <- Num_1 + 1
end
put "The result of the first ", Terms, " terms is:"
put "aB )'$"
put "He said ","hello",".", skip
end
*** Printing Tree ***
{
{
Scope Start: SEQ,
--- Declaration Starts ---
integer Terms
integer Num_1
integer Sum
--- Declaration Ends -----
+++ Arguments Start +++
{
Statement Object: PUT,
Declaration_None,
+++ Arguments Start +++
{
Literal Object: string <"Please, enter the number of Term to sum">,
Declaration_None,
Arguments_None
}
+++ Arguments End +++++
}
{
Statement Object: SEQ,
Declaration_None,
+++ Arguments Start +++
{
Statement Object: GET,
Declaration_None,
+++ Arguments Start +++
{
Identifier Object: Terms,
Declaration_None,
Arguments_None
}
+++ Arguments End +++++
}
{
Statement Object: SEQ,
Declaration_None,
+++ Arguments Start +++
{
Statement Object: WHILE,
Declaration_None,
+++ Arguments Start +++
{
Expression Object: NEQ,
Declaration_None,
+++ Arguments Start +++
{
{
Identifier Object: Num_1,
Declaration_None,
Arguments_None
}
{
Identifier Object: terms,
Declaration_None,
Arguments_None
}
+++ Arguments End +++++
}
{
Statement Object: SEQ,
Declaration_None,
+++ Arguments Start +++
{
Statement Object: ASSIGN,
Declaration_None,
+++ Arguments Start +++
{
Identifier Object: Sum,
Declaration_None,
Arguments_None
}
{
Expression Object: PLUS,
Declaration_None,
+++ Arguments Start +++
{
Identifier Object: Sum,
Declaration_None,
Arguments_None
}
{
Expression Object: DIV,
Declaration_None,
+++ Arguments Start +++
{
Literal Object: integer <1>,
Declaration_None,
Arguments_None
}
{
Identifier Object: Num_1,
Declaration_None,
Arguments_None
Arguments_None
}
+++ Arguments End +++++
}
+++ Arguments End +++++
}
+++ Arguments End +++++
}
{
Statement Object: ASSIGN,
Declaration_None,
+++ Arguments Start +++
{
Identifier Object: Num_1,
Declaration_None,
Arguments_None
}
{
Expression Object: PLUS,
Declaration_None,
+++ Arguments Start +++
{
Identifier Object: Num_1,
Declaration_None,
Arguments_None
}
{
Literal Object: integer <1>,
Declaration_None,
Arguments_None
}
+++ Arguments End +++++
}
+++ Arguments End +++++
}
+++ Arguments End +++++
}
+++ Arguments End +++++
}
{
Statement Object: SEQ,
Declaration_None,
+++ Arguments Start +++
{
Statement Object: PUT,
Declaration_None,
+++ Arguments Start +++
+++ Arguments Start +++
{
Literal Object: string <"The result of the first ">,
Declaration_None,
Arguments_None
}
{
Identifier Object: Terms,
Declaration_None,
Arguments_None
}
{
Literal Object: string <" terms is:">,
Declaration_None,
Arguments_None
}
+++ Arguments End +++++
}
{
Statement Object: SEQ,
Declaration_None,
+++ Arguments Start +++
{
Statement Object: PUT,
Declaration_None,
+++ Arguments Start +++
{
Literal Object: string <"aB )'$">,
Declaration_None,
Arguments_None
}
+++ Arguments End +++++
}
{
Statement Object: PUT,
Declaration_None,
+++ Arguments Start +++
{
Literal Object: string <"He said ">,
Declaration_None,
Arguments_None
}
{
Literal Object: string <"hello">,
Declaration_None,
Arguments_None
}
}
{
Literal Object: string <".">,
Declaration_None,
Arguments_None
}
{
Statement Object: SKIP,
Declaration_None,
Arguments_None
}
+++ Arguments End +++++
}
+++ Arguments End +++++
}
+++ Arguments End +++++
}
+++ Arguments End +++++
}
+++ Arguments End +++++
}
+++ Arguments End +++++
}
Compilation Ends
/* AST example */
/* YIELDS statement */
begin
integer : a
a <- 89 + { integer : x integer : y
get x , y yields x + y * x ^ y }
put "Test yield", skip
end
*** Printing Tree ***
{
Program Start: SEQ,
--- Declaration Starts ---
integer a
--- Declaration Ends -----
+++ Arguments Start +++
{
Statement Object: ASSIGN,
Declaration_None,
+++ Arguments Start +++
{
Identifier Object: a,
Declaration_None,
Argument_None
}
{
Expression Object: PLUS,
Declaration_None,
+++ Arguments Start +++
{
Literal Object: integer <89>,
Declaration_None,
Argument_None
}
{
Statement Object: SEQ,
--- Declaration Starts ---
integer x
integer y
--- Declaration Ends -----
+++ Arguments Start +++
{
Statement Object: GET,
Declaration_None,
+++ Arguments Start +++
{
Identifier Object: x,
Declaration_None,
Argument_None
}
{
Identifier Object: y,
Declaration_None,
Argument_None
}
+++ Arguments End +++++
}
{
Expression Object: RET,
Declaration_None,
+++ Arguments Start +++
{
Expression Object: PLUS,
Declaration_None,
+++ Arguments Start +++
{
Identifier Object: x,
Declaration_None,
Argument_None
}
{
Expression Object: TIMES,
Declaration_None,
+++ Arguments Start +++
{
Identifier Object: y,
Declaration_None,
Argument_None
}
{
Expression Object: POWER,
Declaration_None,
+++ Arguments Start +++
{
Identifier Object: x,
Declaration_None,
Argument_None
}
{
Identifier Object: y,
Declaration_None,
Argument_None
}
+++ Arguments End +++++
}
+++ Arguments End +++++
}
+++ Arguments End +++++
}
+++ Arguments End +++++
}
+++ Arguments End +++++
}
+++ Arguments End +++++
}
+++ Arguments End +++++
}
{
Statement Object: PUT,
Declaration_None,
+++ Arguments Start +++
{
Literal Object: string <"Test yield">,
Declaration_None,
Argument_None
}
{
Statement Object: SKIP,
Declaration_None,
Argument_None
}
+++ Arguments End +++++
}
+++ Arguments End +++++
}
Compilation Ends
To illustrate some critical points, some more examples will be added when
needed.