Handling Assignment Expressions with 'When' Clauses in Compiler Code Generation

44 views Asked by At

the compiler is divided into the front-end (that parse the source program) and the back-end (that generates the machine code). In turn, the front-end is divided in three phases:

  1. the lexical analysis generated by ocamllex from file lexer.mll,
  2. the syntactic analysis generated by ocamlyacc from file parser.mly,
  3. the semantic analysis written in OCAML and inserted as actions in parser.mly.
  4. the translation, i.e. the compilation to generate quadruplets is done inside the source file comp.ml. It contains one function for each :

I have successfully implemented a grammar to handle multiple conditions:

if [ 0 , 0 ] = 1 then
    if sum < 2 then
         [ 0 , 0 ] := 0
    elsif sum > 3 then
         [ 0 , 0 ] := 0
    end
else
    if sum = 3 then
         [ 0 , 0 ] := 1
    end
end 

The grammar used :


opt_statements:
    /* empty */
        { NOP }
|   statement opt_statements
        { SEQ ($1, $2) }
;

statement:
    cell ASSIGN E
        {
            if (fst $1) != 0 then error "assigned x must be 0";
            if (snd $1) != 0 then error "assigned Y must be 0";
            SET_CELL (0, $3)
        }
|   ID ASSIGN E
        { SET_VAR(declare_var($1) , $3)}


|   IF condition THEN opt_statements else_clause END
        {
            IF_THEN($2, $4, $5)
        }   
;

else_clause:
    /* empty */
        { NOP }
|   ELSIF condition THEN opt_statements else_clause
        {
            IF_THEN($2, $4, $5)
        }
|   ELSE opt_statements
        { $2 }
;

I want to extend my grammar to handle expressions like :


x :=
    y + 1 when [ 0 , 1 ] = 1 ,
    y when [ 0 , 0 ] = 1 ,
    y − 1 otherwise

I can see that x := e1 when c1, e2 when, ..., en otherwise

is really equivalent to:

x := e1
elif c2 then
x := e2
elif
. . .
else
x := en
end

I have added then the rules :

statement:

| ID ASSIGN when_clauses
   {}
| cell ASSIGN when_clauses
   {}

when_clauses:
   
   E OTHERWISE
       { } 
|   E WHEN condition COMMA when_clauses
       { }

;

Because this is a bottom-up analysis, I dont understand how the when expressions can be translated to elif expressions because a variable can't be assigned directly.

I have found that an idea is to create a temporary list (condition, expression) there is this function that performs it :

(** Restructure the when assignment into selections.
    @param f    Function to build the assignment.
    @param v    Initial values.
    @param ws   Sequence of (condition, expression).
    @return     Built statement. *)
let rec make_when f v ws =
    match ws with
    | [] -> f v
    | (c, nv)::t ->
        IF_THEN(c, f v, make_when f nv t)

My grammar then :

| ID ASSIGN when_clauses
       { make_when (fun v -> SET_VAR(declare_var($1), v)) $3}
| cell ASSIGN when_clauses
       { make_when (fun v -> SET_CELL(0, v)) $3 }


when_clauses:
   
   E OTHERWISE
        { []} 
|   E WHEN condition COMMA when_clauses
       { ($3, $1) :: $5  }

;

which doesn't seem to work, what am I missing ?

0

There are 0 answers