Search code examples
if-statementocamlyaccocamlyacc

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.


Solution

  • 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