我在github上使用zach Carter的reflect.js(一个不错的Javascript解析器);我试图修改他的解析器的行为来处理注释作为正常的令牌,应该像其他任何东西一样解析。 reflect.js的默认行为是跟踪所有注释(词法分析器将它们作为标记抓取),然后将它们的列表附加到它创建的AST(抽象语法树)的末尾。
但是,我希望这些评论在AST中包含在内。我相信这个改变将涉及到grammar.y文件here添加语法规则。目前没有评论规则 - 如果我的理解是正确的,那么主要的解析代码会忽略它们。
如何编写规则以在AST中包含注释?
答案 0 :(得分:3)
天真版本修改原始语法的每个规则:
LHS = RHS1 RHS2 ... RHSN ;
是:
LHS = RHS1 COMMENTS RHS2 COMMENTS ... COMMENTS RHSN ;
虽然这是抽象的,但如果基于LL或LALR,这可能会搞砸你的解析器生成器,因为现在它只能看到下一个令牌来决定做什么。因此,您必须切换到更强大的解析器生成器,例如GLR。
更智能的版本用非终结符号替换(仅和)每个终端 T:
T = COMMENTS t ;
并修改原始词法分析器,以便小心地发出t而不是T.你仍然有前瞻性的麻烦。
但这为我们提供了真正解决方案的基础。
更复杂的版本是让词法分析器收集在令牌之前看到的注释并将它们附加到它发出的下一个令牌;实质上,我们在词法分析器中实现语法的终端规则修改。
现在解析器(你不必切换技术)只看到它最初看到的标记;令牌带有注释作为注释。您会发现将注释划分为附加到上一个令牌的注释以及附加到下一个令牌的注释是有用的,但是您将无法使这一点比启发式更好,因为没有实际的方法来决定评论真正属于哪个令牌。
您会发现如何捕获令牌和注释上的定位信息,以便重新生成原始文本(“在适当位置的注释”),这会很有趣。您会发现使用适当的基数值,字符串转义等以不会破坏语言语法规则的方式重新生成文本会更有趣。
我们使用我们的通用语言处理工具来做到这一点,并且它运作得相当好。令人惊讶的是,完成所有工作需要做多少工作,以便您可以专注于您的转型任务。人们低估了这一点。