5

我正在使用 github 上 Zach Carter 的 reflect.js(一个不错的 Javascript 解析器);我正在尝试修改他的解析器的行为,以将注释作为应该像其他任何东西一样解析的普通标记来处理。reflect.js 的默认行为是跟踪所有注释(词法分析器将它们作为标记抓取),然后将它们的列表附加到它创建的 AST(抽象语法树)的末尾。

但是,我希望将这些评论就地包含在 AST 中。我相信这种变化将涉及在此处的grammar.y 文件中添加语法规则。目前没有评论规则——如果我的理解是正确的,那就是主解析代码忽略它们的原因。

您如何编写规则以在 AST 中包含评论?

4

1 回答 1

3

天真的版本修改了原始语法的每个规则:

      LHS = RHS1 RHS2 ... RHSN ;

成为:

      LHS =  RHS1 COMMENTS RHS2 COMMENTS ... COMMENTS RHSN ;

虽然这在抽象上是有效的,但如果它是基于 LL 或 LALR 的,这可能会搞砸你的解析器生成器,因为现在它不能看到足够远的距离来决定要做什么。因此,您必须切换到更强大的解析器生成器,例如 GLR。

更智能的版本(仅和)将每个终结符 T 替换为非终结符:

      T  =  COMMENTS t ;

并修改原始词法分析器以简单地发出 t 而不是 T。你仍然有前瞻的麻烦。

但这为我们提供了真正解决方案的基础。

更复杂的版本是使词法分析器收集在令牌之前看到的注释并将它们附加到它发出的下一个令牌;本质上,我们是在词法分析器中实现语法的终端规则修改。

现在解析器(您不必切换技术)只看到它最初看到的标记;令牌携带注释作为注释。您会发现将注释分为附加到前一个标记的注释和附加到下一个标记的注释很有用,但是您无法比启发式更好地做到这一点,因为没有实用的方法来决定评论真正属于哪个标记。

您会发现弄清楚如何捕获标记和评论上的定位信息以启用原始文本(“在其适当位置的评论”)的再生是一件很有趣的事情。您会发现以不违反语言语法规则的方式使用适当的基数值、字符串转义等实际重新生成文本会更有趣。

我们使用我们的通用语言处理工具来做到这一点,并且效果相当好。令人惊讶的是,要弄清楚这一切需要做多少工作,这样您就可以专注于您的转型任务。人们低估了这一点。

于 2013-07-17T05:54:48.070 回答