If statement OCaml中的Yacc NULL?
我正在OCamlyacc和ocamlex中实现以下语法: my IF-ELSE子句的OCaml类型声明如下:If statement OCaml中的Yacc NULL?,if-statement,ocaml,yacc,ocamlyacc,If Statement,Ocaml,Yacc,Ocamlyacc,我正在OCamlyacc和ocamlex中实现以下语法: my IF-ELSE子句的OCaml类型声明如下: (* 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
(* 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 *)
我可以在OCamlyacc中将IF-ELSE部分定义为:
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*/
但是,如果问号用于没有ELSE行1的IF语句,那么如何为语句类型stmt设置NULL?我无权访问只有表达式exp和一条语句的语句类型
我曾考虑过在那里放一个while0{print0}语句,但这不是你应该做的,特别是因为它将在while语句中解析,而它不应该这样做。一个解决方案是显式地添加一个nop语句,根据定义它什么都不做
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
如果您不能修改您的类型,您仍然可以执行虚拟assignment:lv=lv
另一个可能更干净的解决方案是显式地添加
如果对您的语句执行以下操作:
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
谢谢ghilesZ的帖子,但我无法修改OCaml中的类型规则。因此,禁止添加新规则或扩展任何类型 我终于明白我该做什么了。我认为OCaml中缺少了一些特别的东西,所以我故意省略了这个特定任务的细节,我认为这些细节会让我的问题变得模糊,但实际上是有用的 让我给出我的答案,但首先让我给出一些额外的细节: 因此,通过使用上面的语法规则和下面提供的OCaml,解决方案将是:
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*/
你基本上保留了ELSE,但你只是在空的大括号里放了一个空的或者什么都不做的动作
最后,我翻转了顺序,因为要正确解析这两个IF语句,需要设置优先级,这可以通过以下方法完成:
%nonassoc RPAREN /* Right parenthesis */
%nonassoc ELSE