0

我在 OCamlyacc 和 OCamllex 中实现以下语法:

我的 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 
      | 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*/

但是,如何将“NULL”用于语句类型(“stmt”),其中问号用于没有 ELSE的IF 语句(第 1 行)?我无法访问只有一个表达式(“exp”)和一个语句的语句类型。

我考虑过在那里放一个“while(0){print(0)}”语句,但这不是你应该做的,特别是因为它会在不应该的时候解析一个while 语句

4

2 回答 2

1

一种解决方案可以是显式添加根据定义什么都不做的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

如果你不能修改你的类型,你仍然可以做虚拟分配:lv = lv

另一个可能更清洁 imo 的解决方案是将 if-then 操作显式添加到您的语句中:

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
于 2017-04-30T11:32:44.970 回答
0

感谢 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,但您只需放入空花括号,有效地在此处放入“NULL”或“无操作”操作。

最后,我颠倒了顺序,因为要正确解析这两个 IF 语句,您需要设置优先级,这可以通过以下方式完成:

%nonassoc RPAREN  /* Right parenthesis */
%nonassoc ELSE
于 2017-04-30T13:01:45.303 回答