使用ocamlyacc减少/减少冲突

时间:2012-03-21 12:14:50

标签: parsing ocaml ocamlyacc

我正在努力学习涉及类型表达式以及变量访问的语法。在解析期间无法确定此访问的结果类型,并在第二步中进行评估。这个评估不是问题,但似乎很难编写明确的解析器规则。

所有适用于不同类型的操作(例如比较运算符)都会产生reduce/reduce冲突。显然,这是因为解析器无法确定“x.a = y.b”是否应解析为“bool_expr EUQAL bool_expr”或“num_expr EUQAL num_expr”,因为类型不确定。但是,comp_op规则的结果类型是确定的(因为它始终是一个布尔值)。

在解析过程中是否解决了这个问题而没有丢弃所有类型信息,并且总是在评估阶段检查它?

这是一个缩短的语法示例(使用 ocamllex ocamlyacc ):

comp_op:
  | bool_expr EQUAL bool_expr  { T.Equiv (T.Wrapper $1, T.Wrapper $3) }
  | num_expr EQUAL num_expr    { T.Equiv (T.Wrapper $1, T.Wrapper $3) }
  /* the wrapper type basically just wraps the expressions to get a common type */

bool_expr:
  | TRUE                       { T.Bool true }
  | FALSE                      { T.Bool false }
  | access                     { T.BoolAccess $1 }

num_expr:
  | NUMBER                     { T.Num $1 }
  | access                     { T.NumAccess $1 }

access:
  /* some more complex rules describing the access to variables */

感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

正如ygrek所说,你不应该尝试混合解析和打字。编写只有一个表达式的语法类别的解析器要容易得多,然后有一个单独的类型检查传递来解析它。

理论上,这是因为键入规则所做的区分比传统的解析技术所表达的要精细得多。他们一直试图使用例如属性语法来更具说明性地指定输入规则,但是你通常的LL / LR技术当然不是很合适,就像用正则表达式解析嵌套括号一样。

最后,您应该使用menhir而不是ocamlyacc,因为它更好。您将拥有更具可读性和表达性的语法(命名参数,参数化规则......),更好的错误报告和语法调试功能。

答案 1 :(得分:0)

如前所述,您将很难编写“类型正确的解析器” - 根据您的语言,这甚至可能是不可能的。

无论如何,这里的问题是,你的语法不知道“访问”生产的类型;据我所知,这种产生类似于从变量中读取,变量的类型在分析时是未知的。 我看待它的方式,你要么放弃100%类型正确的解析,要么找到一种“神奇地”知道变量类型的方法。 你可以跟踪类型声明,让lexer查找它遇到的变量的类型;然后,词法分析器将根据变量的类型发送变量标识符标记。

我不确定这种方法是否有效,因为我不知道你的语言是什么样的。