Dannon
Dannon

Reputation: 2216

Yacc NULL in OCaml?

I am implementing the following grammar in OCamlyacc and OCamllex:

The OCaml type declaration for my IF-ELSE clauses is as such:

(* Some code not shown *)
and stmt  = ASSIGN of lv * exp
      | IF of exp * stmt * stmt 
      | WHILE of exp * stmt
      | DOWHILE of stmt * exp
      | READ of id
      | PRINT of exp 
      | BLOCK of block
(* Some code not shown *)

I can define the IF-ELSE portion in OCamlyacc as such:

stmt:
   |    IF LPAREN e RPAREN stmt                 { S.IF ($3, $5, ???) } /*line 1*/
   |    IF LPAREN e RPAREN stmt ELSE stmt       { S.IF ($3, $5, $7) }  /*line 2*/

But, how can I put "NULL" for a statement type ("stmt"), where the question marks are for the IF-Statement that does not have an ELSE (line 1)? I do not have access to a statement type that only has an expression ("exp") and only one statement.

I thought about putting a "while(0){print(0)}" statement there, but that is not how you are suppose to do it, especially because it will parse in a while-statement when it shouldn't.

Upvotes: 0

Views: 302

Answers (2)

ghilesZ
ghilesZ

Reputation: 1596

One solution can be to explicitly add a nop statement that does by definition nothing.

stmt  = ASSIGN  of lv   * exp
      | IFTE    of exp  * stmt * stmt
      | WHILE   of exp  * stmt
      | DOWHILE of stmt * exp
      | READ    of id
      | PRINT   of exp 
      | BLOCK   of block
      | NOP

If you can't modify your types, you can still do the dummy assigment : lv = lv

Another solution wich may be cleaner imo, is to add explicitly add the if-then operation to your statements :

stmt  = ASSIGN  of lv   * exp
      | IFTE    of exp  * stmt * stmt
      | IFT     of exp  * stmt  
      | WHILE   of exp  * stmt
      | DOWHILE of stmt * exp
      | READ    of id
      | PRINT   of exp 
      | BLOCK   of block

Upvotes: 1

Dannon
Dannon

Reputation: 2216

Thank you ghilesZ for your post, but I am not able to modify the type rules in OCaml. Therefore, adding in a new rule or extending any types is forbidden.

I finally figured out what I had to do. I thought there was something special in OCaml that I was missing, so I purposely left out details of this specific assignment that I thought would just over cloud my question, but in fact were useful.

Let me show my answer to this, but first let me give some extra details: enter image description here

Therefore, by using the grammar rules up above and the provided OCaml below, the solution would be:

stmt:
   |    IF LPAREN e RPAREN stmt ELSE stmt       { S.IF ($3, $5, $7) }  /*line 1*/
   |    IF LPAREN e RPAREN stmt                 { S.IF ($3, $5, S.BLOCK ([],[])) } /*line 2*/

You basically keep the ELSE, but you just put in empty curly braces, effectively putting in a "NULL" there or a "do-nothing" action.

Lastly, I flipped the ordering, because for these two IF-statements to be parsed correctly, you need to set precedence, which can be done with:

%nonassoc RPAREN  /* Right parenthesis */
%nonassoc ELSE

Upvotes: 0

Related Questions