Reputation: 2216
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
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
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:
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