ANTLR4 javascript访问者中的ctx
使用ANTLR4v4.8 我正在编写transpiler,探索ANTLR(带访问者的javascript目标)的使用 语法->lex/parse很好,我现在坐在解析树上 语法ANTLR4 javascript访问者中的ctx,javascript,antlr,antlr4,visitor,Javascript,Antlr,Antlr4,Visitor,使用ANTLR4v4.8 我正在编写transpiler,探索ANTLR(带访问者的javascript目标)的使用 语法->lex/parse很好,我现在坐在解析树上 语法 grammar Mygrammar; /* * parser rules */ progm : stmt+; stmt : progdecl | print ; progdecl : PROGDECLKW ID '..'; print : WRITEKW STRLIT '..'; /* * lex
grammar Mygrammar;
/*
* parser rules
*/
progm : stmt+;
stmt
: progdecl
| print
;
progdecl : PROGDECLKW ID '..';
print : WRITEKW STRLIT '..';
/*
* lexer rules
*/
PROGDECLKW : 'DECLAREPROGRAM';
WRITEKW : 'PRINT';
// Literal
STRLIT : '\'' .*? '\'' ;
// Identifier
ID : [a-zA-Z0-9]+;
// skip
LINE_COMMENT : '*' .*? '\n' -> skip;
TERMINATOR : [\r\n]+ -> skip;
WS : [ \t\n\r]+ -> skip;
hw.mg
***************
* Hello world
***************
DECLAREPROGRAM hw..
PRINT 'Hello World!'..
PrintContext {
parentCtx: null,
invokingState: -1,
ruleIndex: 3,
children: null,
start: CommonToken {
source: [ [MygrammarLexer], [FileStream] ],
type: -1,
channel: 0,
start: 217,
index.js
...
const myVisitor = require('./src/myVisitor').myVisitor;
const input = './src_sample/hw.mg';
const chars = new antlr4.FileStream(input);
...
parser.buildParseTrees = true;
const myVisit = new myVisitor();
myVisit.visitPrint(parser.print());
访问者的使用似乎并不简单,而post在一定程度上起到了帮助作用
关于上下文的使用。当我点击每个节点时,是否有一种跟踪ctx的好方法?使用
myVisit.visit(树)
作为起始上下文是可以的。当我开始访问每个节点时,使用非根上下文myVisit.visitPrint(parser.print())
抛出错误
错误:
***************
* Hello world
***************
DECLAREPROGRAM hw..
PRINT 'Hello World!'..
PrintContext {
parentCtx: null,
invokingState: -1,
ruleIndex: 3,
children: null,
start: CommonToken {
source: [ [MygrammarLexer], [FileStream] ],
type: -1,
channel: 0,
start: 217,
与异常一起出现:输入不匹配异常[错误]我相信这是因为
children
是null
而不是被填充。这反过来又是由于
第9:0行不匹配的输入'',应为{'DECLAREPROGRAM','PRINT'}
问题:以上是传递上下文的唯一方法还是我做错了? 如果使用正确,那么我倾向于将此报告为bug
编辑17.3-在调用
parser.print()
时添加语法和源代码,但向其提供输入:
***************
* Hello world
***************
DECLAREPROGRAM hw..
PRINT 'Hello World!'..
这是行不通的。对于print()代码>。对于整个输入,您必须调用prog()
。此外,明智的做法是使用EOF令牌“锚定”您的启动规则,这将强制ANTLR使用整个输入:
progm : stmt+ EOF;
如果您想解析并访问整个解析树(使用prog()
),但只对print
节点/上下文感兴趣,那么最好使用侦听器而不是访问者。检查此页面如何使用侦听器:
编辑
以下是侦听器的工作原理(由于我没有正确设置JS,因此是Python演示):
导入antlr4
从游乐场.MygrammarLexer导入MygrammarLexer
从游乐场.MygrammarParser导入MygrammarParser
从playway.MygrammarListener导入MygrammarListener
类打印预处理器(MygrammarListener):
def enterPrint_u(self,ctx:MygrammarParser.Print_u上下文):
打印(“输入的打印:`{}`.”格式(ctx.getText())
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
来源=”“
***************
*你好,世界
***************
申报程序hw。。
打印“你好,世界!”。。
"""
lexer=MygrammarLexer(antlr4.InputStream(源))
parser=MygrammarParser(antlr4.CommonTokenStream(lexer))
antlr4.ParseTreeWalker().walk(printproprocessor(),parser.progm())
运行上述代码时,将打印以下内容:
Entered print: `PRINT'Hello World!'..`
因此,简而言之:这个侦听器接受您输入的整个解析树,但当我们输入print
解析器规则时,只“侦听”
请注意,我将print
重命名为print
,因为print
在Python目标中受保护。您的语法似乎无法解析输入。请编辑您的问题并添加语法和输入,以便其他人可以复制。@BartKiers语法添加,谢谢。尽管语法是这个错误的根源,parser.print()是否正确仍然是个问题。我的观点是,如果解析器产生错误,访问者将不会按照您期望的方式操作。此外,如果无法访问正在解析的源代码和使用的语法,就无法对您的问题进行评论/建议。我仍然看不出您试图解析的输入是什么(您的'./src_sample/hw.mg'
文件的内容)@BartKiers我明白了。也许我会推迟我自己对ctx的强调,直到这个错误得到解决,以保持简单。再次感谢您的关注。我的想法是:当你不能使用个人访问者方法时,为什么要生成个人访问者方法visitPrint
,visitProgdecl
等等?我与java示例形成对比,java示例提供了传递上下文的好方法visitPrintExpr(LabeledExprParser.PrintExprContext ctx)
(来自ANTLR参考书的示例),在java示例中,这种方法工作得很好。progm:stmt+EOF代码>是,同意。我已经做了这个更新(并不是说它对上面的vis-a-vis有帮助)。“我与java示例形成对比……”:java访问者可以做什么,JS目标也可以。对于Java目标,您试图实现的目标也是不可能的:对于Java,您也不能解析整个inout文件,然后对其调用print()
。“我的想法:为什么要生成单个访问者方法…”因为您可以解析输入的不同部分,然后相应地调用这些访问者方法。但是,您不能向它提供由progm
解析的内容,然后调用print()
(不考虑目标语言)。我查看了多个java示例,看不到任何单独的解析运行正在进行。也许你可以指一个?为了能够有选择地解析每个访问者方法的代码部分,我需要对其进行预解析,并事先知道需要为哪个方法解析哪个部分?我不能相信这一点。