我正在尝试使用 rascal mpl ,但我跑进了一个问题:

在SDF中实施岛语法时,非常常见的方法是使用{避免}属性来定义“捕获全部”水生产。这可以防止解析器使用此生产如果其他人则适用。这允许指定可以被其他产品覆盖的默认行为生成歧化。一个非常简单的例子是:

context free syntax
    Chunk*         -> Input
    Water          -> Chunk
lexical syntax
    ~[\t\n\ ]+   -> Water {avoid}  // avoid the Water production
.

我尝试用rascal mpl复制这种行为。我的目标是创建一个岛语法,在一块C / C ++代码内收集所有有条件的预处理器指令,并使用水生产跳过其余的输入。

layout LAYOUT = [\t\n\ ];
lexical WATER = ![\t\n\ ]+;

start syntax Program = Line*;       // program consists of lines

syntax Line = ConditionalDirective  // preprocessor directives
            > WATER;                // catch-all option

syntax ConditionalDirective = "#ifdef" 
                            | "#ifndef"
                            | "#if"
                            | "#elif";
.

我试图通过使用“>”运算符为条件Directive 生产更高的优先级来创建{避免}效果,但这明显不起作用。解析树仍包含含糊不清。

#ifdef asd
.

如果我例如解析上面的代码,我会得到一个视图树,如下所示:

据我所知,从 rascal文档,使用“优先级” - 驾驶员可能不是在我的情况下进入的方式,但我看不到任何其他可能性。我认为有一种方法,因为Rascal的作者明确地说明了每个SDF语法可以转换为流氓语法。

是否有一种方法来重现SDFS {避免}与Rascal MPL的功能?或者可以以某种方式过滤解析森林,重新申请优先级吗?

有帮助吗?

解决方案

简短答案:避免在SDF2中解析过滤器。在Rascal中,您可以自己定义这些,请参阅 https://github.com/cwi-swat/rascal/blob/master/src/org/rascalmpl/library/lang/sdf2/filters/preferavoid.rsc 用于模仿的示例SDF2避免不忽视注射链的行为,而不进行计数。您可以在语法中导入它,并在SDF2中使用@Avoid和@Prefer标签,或者写自己的过滤器。

警告:避免通常不足以在SDF2中定义水行为,也不是rascal。原因是水可以变长而不是其替代方案。更喜欢并避免只能在保留长度方面选择相等长度的替代。 一个简而言之,但在流氓中处理水的速度是在每种替代方案中都会计算它,并选择越来越少的水。

更倾向于避免的另一个问题是,用途将开始干扰,特别是在计算它们时。通过专门为特定的非终端或甚至替代规则专用过滤器,可以避免这种情况。

另一个选项是使用\和!歧义运营商。请参阅手册。但是,所有和所有人 我相信Post解析过滤选项是目前是处理岛语法的最佳方式,因为你控制发生了什么。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top