Rascal 语法的预测编辑器

Predictive editor for Rascal grammar

我正在尝试为用 Rascal 编写的语法编写一个预测编辑器。其核心是一个函数,它以符号列表作为输入并返回符号类型列表作为输出,这样任何这些类型的实例都将是语法下输入符号的句法合法延续。因此,如果输入列表是 [4,+],则输出可能是 [integer]。在 Rascal 中有没有聪明的方法来做到这一点?我可以想到执行此操作的命令式编程方法,但我怀疑它们没有充分利用 Rascal 的强大功能。

这是个很大的问题。这是一些导致答案的线索,但完整的答案将完全为您实施:-)

  1. 使用 # 运算符将您感兴趣的语言的原始语法具体化为一个值,以便您可以轻松地查询该语法的简明表示。表示是在扩展 TypeGrammar.
  2. 的模块 TypeParseTree 上定义的
  3. 为输入查询构造相同的表示。这可以通过多种方式完成。一种非常棒的语言参数方法是将 Rascal 的解析器算法扩展到 return 部分树以用于部分输入,但我相信现在这会很麻烦。一个更简单的解决方案需要为一组部分输入编写语法,即在特定点具有较短规则的语言语法。语法将是模棱两可的,但在这种情况下不是问题。
    • 使用标签标记 "short" 规则,以便您以后可以轻松找到它们:syntax E = @short E "+";
    • 使用扩展的和现在有歧义的语法进行解析;
    • 生成的解析树将包含与您用于具体化原始语法的 ParseTree 中相同的表示,只是规则更长,如 prod(E, [E,+,E],...)
    • 然后 select 最适合你完成目标的树(使用 @short 标签),并提取它们的产品“prod”,看起来像这样prod(E,[E,+],...)。例如,使用 / 运算符:[candidate : /candidate:prod(_,_,/"short") := trees],您可以使用光标位置来查找附近的候选对象,而不是那里的所有 short 棵树。
  4. 使用列表匹配在原始语法中查找前缀,例如 if (/match:prod(_,[*prefix, predicted, *postfix],_) := grammar) ...,前缀是从 @short 规则中提取的查询。 predicted 是您的答案,postfix 是之后的答案。
  5. 返回 predicted 符号作为用户阅读的类型:"<type(predicted, ())>"(即使它是一些复杂的正则表达式类型并正确引用等,也会很好地打印它)