Control Structures Due 14April08 - Part1 IfThenElsifElse

We will examine Part2 - Loops on Wednesday

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

Linked to this handout are examples with SPIM for Phase5 implemention If-Then-Elsif-Else control structures uses a scheme that meants that our If Statement will now always use two labels. One label is the Out-label for the end of the structure. One label is for the Elsif or Else part, which may be optional. In the example below, we have an If with no Elsif nor Else part and two labels are used, even though in the beginning project, Phase 0, only one was needed. This was all that was needed for the very restricted ADA-to-be language we were translating.

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.

  1. If-then-elsif-else-end if
         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
                   |     lambda {NullList();}
    else_part_opt  :     else_part
                   |     lambda {NullList();}
    else_part      :      Else stmtlist
    Consider the following ada fragment:
                   if bexpr1 then slist1 elsif bexpr2 then slist2
                             elsif bexpr3 then slist3
                             else              slist4
    The 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 */
         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
     * #makeelsif()
     *      top ->|stlstentry|
     *             -----------
     *            |bexprentry|   >>>  |stmtentry|<- top
     *            ------------        -----------
     *            |    ?    |         |    ?    |

    You are already familiar with the other semantic actions:

    The grammar rule to reduce to booleanexpr will introduce the bexprentry onto the semantic stack.

    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
     *      top ->|    elselist    |
     *            ------------------
     *            | list of elsifs |
     *            ------------------
     *            |    then list   |
     *            ------------------
     *            |   bexprentry   |    >>>  |stmtentry|<- top
     *            ------------------         -----------
     *            |        ?       |         |    ?    |
    return to Class page