The material in Chapter 6.6 is somewhat helpful. Our technique of first building the semantic representation as an AST and then traversing this tree in codegen.c to generate SPIM code is a little different.
iftest1 with AST results
iftest1a with tokens, semstack
including source, AST, SPIM and execution
We use the notation that {} denotes pseudo code and () enclose tuples.
{Evaluate bexpr1} (JUMP0, bexpr1, Elsif1} {code for thenlist} (JUMP, Out) (LABEL, Elsif1) {Evaluate bexpr2} (JUMP0, bexpr2, Elsif2} {code for elsiflist-1} (JUMP, Out) (LABEL Elsif2) {Evaluate bexpr3} (JUMP0, bexpr3, Else} {code for elsiflist-2} (JUMP, Out) (LABEL Else) {code for elselist} (LABEL, Out)This points out the need for at least two labels to translate the If Statement now, one for the Out-label and one to have ready for the Elsif or Else label. I called with the "Past Else" and needed to keep track of it in a global variable gpastelse in codegen.c
There is also the additional need in GenStmt (codegen.c) for
MACHINEADDRPTR outlabel, pastelselabel; int holdpast; STMTPTR elsifstmt;
I will cover these hints in two steps.
Control1 - this handout - refers to the If-Then-Elsif-Else-Endif control structures.
The grammar (and the implied changes to simple.lex): ifstmt : If bexpr Then stmtlist elsif_list else_part_opt End If { MakeIf(); } elsif_list : elsif_list Elsif booleanexpr Then stmtlist {MakeElsif(); MergeStmts();} | lambda {NullList();} else_part_opt : else_part | lambda {NullList();} else_part : Else stmtlistConsider the following ada fragment:
if bexpr1 then slist1 elsif bexpr2 then slist2 elsif bexpr3 then slist3 else slist4The structures, let's look at it graphically first:
slist1 elsif-stmt ifthen-stmt /-----> ------------------ slist2 ------------------- / | EXPRTREE bexpr2| /------> | EXPRTREE bexpr1 | / |----------------- / | thenlist * --------/ /-----> | slist * --------/ | elsiflist * ------------/ |================= | elselist * ------\ | next * --------- =================== \ ------------------\ | nextstmt | \ \ ------------------| \ / \slist4 / ------> / elsif-stmt / ------------------ slist3 | EXPRTREE bexpr3| /------> ------------------ / | slist * --------/ ================== | next *--> NULL | ------------------
You will probably want to review the current definition of a statement and see that it includes a field (next) which is used to link the individual statements up into a statement list. Also review what a stmtlist looks like (see the semantic routine mergestmts(); and nulllist();) and an ifthen statement (since it is set up with the field bexpr and slist; in addition to the next field).
Just to make it simpler, here is a copy of the relevant piece of code from semform.h. Note - I have set separate STMTTYPE tags for for ifthenstmt, elsifstmt and elsestmt so that I can check things in sem.c, but I recommend using the same structure with the unneeded entries set NULL:
typedef struct stmt{ /* statement description */ STMTTYPE type; union { struct { EXPRTREE bexpr; struct stmt *slist; /* the then-part */ struct stmt *elsiflist; /* the elsif part */ struct stmt *elselist; /* the else part */ }ifthen; /* ifthen, elsif AND else stmt */ struct { ATTRPTR id; EXPRTREE bexpr; struct stmt *slist; } loop; struct { ATTRPTR id; EXPRTREE bexpr; } exit; struct { ADDRTREE lhs; EXPRTREE rhs; }assign; /* assignstmt */ struct { PROCEDURETYPE type; PARAMLIST params; }procall; /* stdproccall */ }se; struct stmt *next; /* next statement in list */ } STMTNODE, *STMTLIST, *STMTPTR; /* stmtlistnode */So how is this structure to be created. Let's look at the semantic actions indicated in the grammar above.
elsif_list ::= elsif_list elseif booleanexpr Then stmtlist #makeelsif #mergestmts * #makeelsif() * /* SEMANTIC STACK MANIPULATION: * top ->|stlstentry| * ----------- * |bexprentry| >>> |stmtentry|<- top * ------------ ----------- * | ? | | ? | */
You are already familiar with the other semantic actions:
The grammar rule to reduce to stmtlist will introduce the stmtlistentry onto the semantic stack.
ifstmt ::= If booleanexpr Then stmtlist elsif_list else_part_opt End If #makeif #makeif(); /* SEMANTIC STACK MANIPULATION: * top ->| elselist | * ------------------ * | list of elsifs | * ------------------ * | then list | * ------------------ * | bexprentry | >>> |stmtentry|<- top * ------------------ ----------- * | ? | | ? | */return to Class page