Parsing 在Menhir/Ocamlyacc中为运算符指定动态优先级和优先级

Parsing 在Menhir/Ocamlyacc中为运算符指定动态优先级和优先级,parsing,ocaml,operator-precedence,ocamlyacc,menhir,Parsing,Ocaml,Operator Precedence,Ocamlyacc,Menhir,我正在尝试使用Menhir解析器(类似于Ocamlyacc)解析一种语言,其中操作符具有动态属性(优先级和优先级)。在词法转换阶段,所有操作符都填充OP:string标记(因此“+”变成(OP“+”),等等) 操作符属性在解析时确定,并填充一个关联操作符及其属性的表。给定此表,如何指示Menhir根据此表的数据动态更改规则解析运算符的优先级 谢谢, CharlieP.我很抱歉用“你做错了”这样的评论来回答。我有三个反对意见,我希望它们是建设性的,按相关性的降序排列: Menhir不适用于动态语法

我正在尝试使用Menhir解析器(类似于Ocamlyacc)解析一种语言,其中操作符具有动态属性(优先级和优先级)。在词法转换阶段,所有操作符都填充
OP:string
标记(因此“+”变成
(OP“+”)
,等等)

操作符属性在解析时确定,并填充一个关联操作符及其属性的表。给定此表,如何指示Menhir根据此表的数据动态更改规则解析运算符的优先级

谢谢,
CharlieP.

我很抱歉用“你做错了”这样的评论来回答。我有三个反对意见,我希望它们是建设性的,按相关性的降序排列:

  • Menhir不适用于动态语法更新;如果您坚持在解析时更改语法,那么应该使用提供此功能的工具,例如GLR解析器。Dypgen手册中提到了动态更新操作员优先级的可能性,这种方式可能与您的需求相匹配,也可能与您的需求不匹配(似乎您可以添加新的操作员和相应的优先级,但不能更改现有操作员的优先级)。请参见第页的第6.6节。。。42

  • 我认为,动态更新CFG语法并不是处理用户定义的运算符先例的最佳方法。Agda有非常通用的用户定义的mixfix操作符,它们的解决方案大致如下:使用CFG解析器解析静态已知的语法结构,但对于可能使用奇特的先行项和关联性的表达式,只需将它们解析为标记列表。例如,
    let x=if foo then x+y*z else bar
    将被解析为类似于
    let(x,if(foo,Expr(x,+,y,*,z),bar)
    。稍后的专门过程可以收集所需的信息,将它们解析到
    Expr
    节点的专门结构中。请使用解析器生成器(静态称为rich CFG),并对复杂、定义不明确、动态的内容使用后处理过程。Agda的成员有一些关于该主题的文献,例如Danielsson和Norell,2009

    从设计的角度来看,我强烈建议您在几个不同的过程中分离词法分析和语法分析,每个过程都有很好的定义,并且只使用以前结构中收集的信息,而不是试图动态地改变自己的行为。您将拥有更简单、更健壮的功能

  • 在我看来,动态或用户定义的优先级和优先级有点不好。OCaml有一个不同的系统,其中运算符优先级由它们的前几个字符决定(例如,
    @
    @
    @+
    都是正确关联的)。对于选择中缀运算符的人来说,这有点限制,但会使代码读者的生活更加舒适,因为他们只需要学习一组语法规则,而不必动态地调整他们的眼睛以适应任何新的代码。如果您想允许插入具有完全不同语法的大量外来代码段,引用机制(如camlp4
    )比摆弄操作符级别的关联性和优先级要健壮得多,而且解析起来也简单得多

    也就是说,项目有不同的需求,如果你坚持要为我不知道的应用程序动态更改运算符优先级和关联性,我会完全理解。请记住,这不是唯一的解决方法,有时一致性和简单性比绝对灵活性更好