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:
- the lexical analysis generated by ocamllex from file lexer.mll,
- the syntactic analysis generated by ocamlyacc from file parser.mly,
- the semantic analysis written in OCAML and inserted as actions in parser.mly.
- 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 ?