CS 325            Project            Part III

 

You are to write a semantic analyzer and code generator for SIMPL.   You will incorporate this with your parser to produce Jasmin assembly language for the JVM.  You should write a driver program which calls the parser, then runs the semantic analyzer and the code generator on the syntax tree.  To design your semantic analyzer you must first design an attribute grammar for the syntax tree. 

The semantic analyzer should build the symbol table and calculate the node attributes described below.  Semantic errors that are possible in SIMPL are redefining a variable, using an undeclared variable, and an incorrect data type.  To handle these errors, print an error message and abort.

 

Symbol Table

The SIMPL compiler uses a syntax tree produced by the parser to perform semantic analysis. A central structure in the analysis is the symbol table. The form of a symbol table entry is as follows:
 

Field

Values

Description

name

String

The name of the variable.

ioType

OUT
IN
LOCAL

One of three possible functions of the variable.

dtype

NUM
BOOL

One of two possible data types of a variable.

varNum

Integer

Each variable is assigned a local variable number
(used by the JVM).

 

 


Node Attributes

During semantic analysis several attributes are calculated, and added to the nodes of the syntax tree. The table below lists the attributes attached to each node.
 

Attribute

Values

Description

Calculation

name

String

The character string representation of a token.

Supplied by the lexical scanner.

value

Integer

The numeric value of a constant.

Supplied by the lexical scanner.

lineNum

Integer

The source line on which a token was scanned.

Supplied by the lexical scanner.

symTab

Symbol Table

A pointer to the global symbol table.

Synthesized by the PROG node p1, p2, and p3 children; inherited by the p4 child.

use

DECLARE
REF

The use of a variable name; either declared or referenced.

Inherited through all children of the PROG node.

dtype

NUM
BOOL

The data type of an expression node, or a variable declaration.

Synthesized from the data types of the children nodes, or supplied by the lexical scanner, respectively.

size

Integer

The number of leaf nodes in a nodes subtree.

Synthesized from the nodes children.

lab1

String

A generated label, used by control nodes.

Synthesized in the p4 child of the PROG node, using a label generator.

lab2

String

A generated label, used by control nodes.

Synthesized in the p4 child of the PROG node, using a label generator.

 

 


The target machine for the SIMPL compiler is the JVM. Code is generated from the syntax tree, using the templates given below. (Note: the BANNER is a comment string identifying the compiler and version.)
 

Node Type

Template

PROG
dType=NUM

; BANNER
.class public p1.name
.super java/lang/Object
.method public static main([Ljava/lang/String;)V
   p1.generateCode
   p2.generateCode
   p3.generateCode
   p4.generateCode
   iload p1.varNum
   invokestatic simplIO/outputNum(I)V
   return
.limit stack p4.size+1
.limit locals symTab.size+1
.end method 

PROG
dType=BOOL

; BANNER
.class public p1.name
.super java/lang/Object
.method public static main([Ljava/lang/String;)V
   p1.generateCode
   p2.generateCode
   p3.generateCode
   p4.generateCode
   iload p1.varNum
   invokestatic simplIO/outputLog(Z)V
   return
.limit stack p4.size+1
.limit locals symTab.size+1
.end method 

ID
ioType=OUT
use=
DECLARE
dType=
NUM

   ldc "name"
   invokestatic simplIO/registerIO(Ljava/lang/String;)V
   sipush
   istore varNum

ID
ioType=OUT
 use=DECLARE
dType=
BOOL

   ldc "name"
   invokestatic simplIO/registerIO(Ljava/lang/String;)V
   bipush
   istore varNum

ID
ioType=IN 
use=DECLARE
dType=NUM

   ldc "name"
   invokestatic simplIO/inputNum(Ljava/lang/String;)I
   istore varNum

ID
ioType=IN 
use=DECLARE
dType=BOOL

   ldc "name"
   invokestatic simplIO/inputLog(Ljava/lang/String;)Z
   istore varNum

ID
ioType=LOCAL 
use=DECLARE
dType=NUM

   sipush 0
   istore varNum

ID
ioType=LOCAL 
use=DECLARE
dType=BOOL

   bipush 0
   istore varNum

ID
use=REF

   iload varNum

SPACE

   p1.generateCode
   p2.generateCode

NULL

 

!

   p1.generateCode
   p2.generateCode

IF

   p1.generateCode
   ifeq lab1
   p2.generateCode
   goto lab2
lab1:
   p3.generateCode
lab2

WHILE

lab1:
   p1.generateCode
   ifeq lab2
   p2.generateCode
   goto lab1
lab2

<-

   p2.generateCode
   istore p1.varNum

> 

   p1.generateCode
   p2.generateCode
   if_icmpgt lab1
   bipush 0
   goto lab2
lab1:
   bipush 1
lab2

=

   p1.generateCode
   p2.generateCode
   if_icmpeq lab1
   bipush 0
   goto lab2
lab1:
   bipush 1
lab2

+
dType=NUM

   p1.generateCode
   p2.generateCode
   iadd 

+
dType=BOOL

   p1.generateCode
   p2.generateCode
   ior

-

   p1.generateCode
   p2.generateCode
   isub

*
dType=NUM

   p1.generateCode
   p2.generateCode
   imul 

*
dType=BOOL

   p1.generateCode
   p2.generateCode
   iand

/

   p1.generateCode
   p2.generateCode
   idiv 

NEG
dType=NUM

   p1.generateCode

  ineg

NEG
dType=BOOL

   bipush 1
   p1.generateCode
   ixor

NUM

   sipush name

BOOL

   bipush value