1

在 Rascal 中,为什么当在产品的可选部分的位置存在布局时,会导致歧义?Eg"{ }"是模棱两可的Start1,虽然它Start2从以下语法中解析得很好,我本来希望它是完全相同的。

layout Layout                               = " "?;
start syntax Start1                         = "{" "c"? "}";
start syntax Start2                         = "{" "c" "}"
                                            | "{" "}";

另外,我想知道是否有另一种表示Start2不重复的方式,而不是Start1不会导致同样的歧义。

显然,这段代码没有大量的重复,在这里Start2是一个不错的选择,但这只是一个例子。我正在使用包含三个或四个可选部分的许多产生式的语法,在最后一种情况下,显示的符号Start2已经需要将产生式的非可选部分复制 2^4=16 次,这在我看来确实很麻烦.

4

1 回答 1

1

在生成解析器之前,您的语法首先被扩展为类似于以下内容:

layout Layout                         = " "?;
syntax " "?                           =  | " ";
syntax Start1                         = "{" Layout "c"? Layout "}";
syntax "c"?                           =  | "c";
lexical " "                           = [\ ];
lexical "c"                           = [c];
lexical "{"                           = [{];
lexical "}"                           = [}];
syntax Start2                         = "{" Layout "c" Layout "}"
                                      | "{" Layout "}";
syntax start[Start1] = Layout Start1 Layout;
syntax start[Start2] = Layout Start2 Layout;

因此,对于像(花括号之间的空格)这样的输入{ },空格可以由 Start1 规则右侧的第一个 Layout 实例或第二个 Layout 实例导出。由于解析器生成所有派生树,在这种情况下,解析器可以说是模棱两可的。

通常,通过使用跟随限制引入贪婪来解决歧义,如下所示:

layout Layout = " "? !>> " "

或(等效地)像这样:

layout Layout = " "? !>> [\ ]

该限制充当对 Layout 规则的约束:如果后面有空格,它将不会派生任何内容(甚至是空字符串)。这使得只有第一个派生有效,其中空间进入 Start1 的第一个 Layout 实例。在此之后},满足约束并且解析是明确的。

于 2016-07-06T14:45:54.083 回答