我正在尝试为多种语言创建文档生成器。为此,我需要一个AST,以便知道,例如,这个注释是针对一个类而且这个是针对这个类的方法。
我开始编写这个简单的Python代码,通过递归查看它来显示树:
import sys
import antlr4
from ECMAScriptLexer import ECMAScriptLexer
from ECMAScriptParser import ECMAScriptParser
def handleTree(tree, lvl=0):
for child in tree.getChildren():
if isinstance(child, antlr4.tree.Tree.TerminalNode):
print(lvl*'│ ' + '└─', child)
else:
handleTree(child, lvl+1)
input = antlr4.FileStream(sys.argv[1])
lexer = ECMAScriptLexer(input)
stream = antlr4.CommonTokenStream(lexer)
parser = ECMAScriptParser(stream)
tree = parser.program()
handleTree(tree)
并尝试使用antlr EcmaScript grammar解析此Javascript代码:
var i = 52; // inline comment
function foo() {
/** The foo documentation */
console.log('hey');
}
输出:
│ │ │ │ └─ var
│ │ │ │ │ │ └─ i
│ │ │ │ │ │ │ └─ =
│ │ │ │ │ │ │ │ │ │ └─ 52
│ │ │ │ │ └─ ;
│ │ │ └─ function
│ │ │ └─ foo
│ │ │ └─ (
│ │ │ └─ )
│ │ │ └─ {
│ │ │ │ │ │ │ │ │ │ │ │ └─ console
│ │ │ │ │ │ │ │ │ │ │ └─ .
│ │ │ │ │ │ │ │ │ │ │ │ └─ log
│ │ │ │ │ │ │ │ │ │ │ └─ (
│ │ │ │ │ │ │ │ │ │ │ │ │ │ └─ 'hey'
│ │ │ │ │ │ │ │ │ │ │ └─ )
│ │ │ │ │ │ │ │ │ └─ ;
│ │ │ └─ }
└─ <EOF>
所有评论都会被忽略,可能是由于channel(HIDDEN)
in the grammar的存在。
经过一些谷歌搜索后,我找到了this这个答案:
除非你有非常令人信服的理由将评论放在解析器中(我想听到),否则你应该把它放在词法分析器中。
那么,为什么评论不应该包含在解析器中以及如何获取包含注释的树?
答案 0 :(得分:3)
那么,为什么评论不应该包含在解析器中以及如何获取包含注释的树?
如果您从规则MultiLineComment
MultiLineComment
: '/*' .*? '*/' -> channel(HIDDEN)
;
MultiLineComment
然后arrayLiteral
将最终出现在解析器中。但是,每个解析器规则都需要包含允许它们使用的这些令牌。
例如,采用/// ArrayLiteral :
/// [ Elision? ]
/// [ ElementList ]
/// [ ElementList , Elision? ]
arrayLiteral
: '[' elementList? ','? elision? ']'
;
解析器规则:
[/* ... */ 1, 2 /* ... */ , 3 /* ... */ /* ... */]
因为这是JavaScript中的有效数组文字:
MultiLineComment
这意味着您需要使用/// ArrayLiteral :
/// [ Elision? ]
/// [ ElementList ]
/// [ ElementList , Elision? ]
arrayLiteral
: '[' MultiLineComment* elementList? MultiLineComment* ','? MultiLineComment* elision? MultiLineComment* ']'
;
代码来解决所有解析器规则:
BufferedTokenStream#getHiddenTokensToLeft
这将成为一个大混乱。
来自评论:
因此无法使用antlr生成包含注释的树?是否有一些黑客或其他图书馆可以做到这一点?
GRosenberg的回答:
Antlr为此任务提供了一种便捷方法:
BufferedTokenStream#getHiddenTokensToRight
。在遍历解析树时,访问流以获取节点关联的注释(如果有)。使用// Make a call to the REST api to create the payment return actions.payment.create({ payment: { transactions: [ { amount: { total: '<?= $amount / 100 ?>', currency: 'EUR' }, description: {'The payment transaction description.'} } ] } }); },
获取任何结尾评论。