digits -> letters CSE 428: Lectures

Spring 2000, CSE 428

Interpretation of a small imperative language

We illustrate an example of interpreter for a simple imperative language.

The language

The abstract syntax of the language is specified by the following grammar:

   Com ::= Ide := NExp                      assignment
         | Com ; Com                        concatenation
         | if BExp then Com else Com        conditional
         | while BExp do Com                iteration
         | begin Ide in Com end             block with variable declaration
         | begin Ide alias Ide in Com end   block with alias declaration
The intended meaning of a command like
   begin 
      x 
   in c
   end
is that a new variable x is introduced, and it is local to the block. The intended meaning of a command like
   begin 
      x alias y
   in c
   end
is that a new name x is introduced, and it is associated to the same location of the variable y. In other words, in c we can access the same variable by two names: x and y.

NExp represents numerical expressions:

   NExp ::=  Num | Ide | NExp NOp NExp 
   NOp  ::=  + | * | - | /
BExp represents boolean expressions:
   BExp ::= true | false | NExp COp NExp | not BExp | BExp BOp BExp
   COP  ::= < | =
   BOP  ::= and | or
Num generates the natural numbers, that can be represented as sequences of digits starting with a digit different from 0:
   Num ::= 0 | Non_Zero_Digit Seq_Digit
   Non_Zero_Digit ::= 1 | 2 | 3 | ... | 9
   Digit ::= 0 | Non_Zero_Digit
   Seq_Digit ::= lambda | Digit Seq_Digit
Ide generates the identifiers, which can be choosen to simply be sequences of letters:
   Ide    ::=  Letter | Letter Ide
   Letter ::=  a | b | c | ... | z
Note that the grammar is ambiguous, but we will not worry about that because we assume that it represents the abstract syntax.

Structures necessary for the interpreter

We will specify our interpreter in a C++like language.

Parse trees

We need trees with a different number of subtrees, up to three, depending on the command. For the assignment we need only one subtree; for the concatenation we need two subtrees, for the conditional we need three subtrees, etc. Hence we will declare a structure of the following kind:

   class tree{
      node* root;
      tree* first;
      tree* second;
      tree* third;
   public:
      tree* subtree(int n){
            switch (n) of {
               case 1: return first;
               case 2: return second;
               case 3: return third;
            }
      }
      ...
   }
The class node will be analogous to the homonimous class seen in the notes about the evaluation of expressions.