【问题标题】:Removing ambiguities in grammar消除语法中的歧义
【发布时间】:2015-08-31 20:28:51
【问题描述】:

我用一个不知道如何解决的问题构建了一个简单的语法:

start syntax Prog = prog: Type Id;

syntax Dot = {Id "."}+ ;

syntax Id =
    id: [A-Z_a-z] !>> [0-9A-Z_a-z] \ KW
    | Rv
    ;

syntax Rv = rv: "$" [a-z_A-Z][a-z_A-Z0-9]* ;

syntax Type =
    Rv
    | Ref
    ;

syntax Ref =
    Dot
    | s: "str"
    ;

keyword KW = "str" ;

layout LAYOUTLIST = LAYOUT* !>> [\t-\n\r\ /] ;

lexical LAYOUT = [\t-\n\r\ ] ;

问题在于我们可以通过三种不同的方式解决rv (Id -> Rv) 和 (Type -> Rv) 和 (Type -> Ref -> Dot -> Id -> Rv)。问题是我需要Types 和Ids 才能成为Rvs。所以,给定一个简单的程序:

$a x

我的想法是我可以通过将Type 的规则更改为:

syntax Type =
    Rv
    > Ref
    ;

希望解析器将RvType 关联,然后检查它是否可以在Ref 分支中解析。我已经运行了一些模棱两可的诊断,但我不确定这些是什么:

  info(
    "Ambiguity cluster with 2 alternatives",
    |cwd:///grammar.txt|(0,3,<1,0>,<1,3>)),
  info(
    "Production unique to the one alternative: Type = Rv ;",
    |cwd:///grammar.txt|(0,3,<1,0>,<1,3>)),
  info(
    "Production unique to the other alternative: Dot = {Id \".\"}+ ;",
    |cwd:///grammar.txt|(0,3,<1,0>,<1,3>)),
  info(
    "Production unique to the other alternative: {Id \".\"}+;",
    |cwd:///grammar.txt|(0,3,<1,0>,<1,3>)),
  info(
    "Production unique to the other alternative: Ref = Dot ;",
    |cwd:///grammar.txt|(0,3,<1,0>,<1,3>)),
  info(
    "Production unique to the other alternative: Type = Ref ;",
    |cwd:///grammar.txt|(0,3,<1,0>,<1,3>)),
  info(
    "Production unique to the other alternative: Id = Rv ;",
    |cwd:///grammar.txt|(0,3,<1,0>,<1,3>)),
  info(
    "The alternatives have different productions at the top, one has \n  Type = Rv \nwhile the other has\n  Type = Ref ",
    |cwd:///grammar.txt|(0,3,<1,0>,<1,3>)),
  warning(
    "You should give this production a good label: \n  Ref = Dot ]",
    |cwd:///grammar.txt|(0,3,<1,0>,<1,3>)),
  error(
    "To fix this issue, you could restrict the nesting of\n  Ref = Dot \nunder\n  Type = Ref \nusing the ! operator on argument 0: !labelX\nHowever, you should realize that you are introducing a restriction that makes the language smaller",
    |cwd:///grammar.txt|(0,3,<1,0>,<1,3>))

所以,我需要某种方式使Rvs 在解析时同时成为Types 和Ids,而不会产生歧义。这可能吗?

谢谢!

【问题讨论】:

    标签: parsing rascal


    【解决方案1】:

    在这种情况下,如果您控制语言的语法,则可以通过添加显式运算符或某种形式的唯一括号或分隔符语法来选择不含歧义的语言。换句话说,我不认为语法对于本质上不是模棱两可的语言来说是意外模棱两可的,并且应该存在非模棱两可的语法。我认为目前设想的语言没有明确的上下文无关语法。

    修复示例:

    syntax Type 
      = Rv
      | "&" Ref
      ;
    

    另一种方法是尝试使用 Rascal 的消歧机制来解决这个问题,但它们在设计上不提供任何有序的回溯行为。它会使语法的语义依赖于解析算法(它控制语法规则的执行顺序)。

    您可以尝试使用 !&gt;&gt;\ 运算符和 ! 来排除某些句子和派生词,但如果可以在不丢失语言句子的情况下这样做,那么诊断工具会为您提供建议。所以这些 hack 可能会解决歧义,但它们也会改变语言的设计,让程序员更难预测什么是允许的,什么是不允许的。

    优先级机制也无济于事,因为它仅设计用于具有不同优先级的相互递归规则,例如1 + (2 * 3) vs (1 + 2) * 3

    简而言之:我会选择对语言进行一两次更改,以使语法对于通用解析器和人眼都变得明确。

    【讨论】:

    • 感谢您的回复。我实际上正在使用 Java 语法并对其进行修改。我发布的只是一个说明问题的构造示例。不幸的是,我只能用语法做些什么。我的一个想法是以某种方式将它分开,所以我有一个不同的Rv 用于TypeId,但这会导致我编写的后端代码需要更多更改。我真正想要的是某种方式来表达“如果这种类型可以解析为 Rv,那么在检查 Ref 之前执行此操作。”
    • 类似于github.com/cwi-swat/rascal/blob/master/src/org/rascalmpl/… 中的@prefer 但我认为这仅在您拥有具有相同标签的作品时才有效。在 Java 语法中,它用于 if 语句。对吗?
    • 当然,@prefer 可能在这里工作。这实际上只是触发了一个解析后过滤器,如果存在首选的树,它会从森林中删除另一棵树。我宁愿不使用prefer,而只是编写我自己的post parse过滤器,以真正控制它的语义并能够产生有意义的错误消息。
    • 要让@prefer 工作,您需要在模棱两可的派生顶部有两个不同的产生式,并用“prefer”标记其中一个
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-27
    • 1970-01-01
    • 2015-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多