ANTLR4 javascript访问者中的ctx



使用ANTLR4 v4.8

我正在编写transplaner,探索ANTLR(带访问者的javascript目标(的使用。

语法->lex/parse很好,我现在坐在parse树上。

语法

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      : [rn]+ -> skip;
WS              : [ tnr]+ -> skip;

hw.mg

***************
* Hello world
***************
DECLAREPROGRAM  hw..
PRINT 'Hello World!'..

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());

访问者的使用似乎并不简单,这篇SO帖子在一定程度上有所帮助。

使用上下文时。当我到达每个节点时,有没有一个好的方法来跟踪ctx
使用myVisit.visit(tree)作为起始上下文是可以的。当我开始访问每个节点时,使用非根上下文
myVisit.visitPrint(parser.print())会引发错误。

错误:

PrintContext {
parentCtx: null,
invokingState: -1,
ruleIndex: 3,
children: null,
start: CommonToken {
source: [ [MygrammarLexer], [FileStream] ],
type: -1,
channel: 0,
start: 217,

exception: InputMismatchException [Error]
我相信这是因为childrennull而不是被填充的
这反过来又是由于line 9:0 mismatched input '<EOF>' expecting {'DECLAREPROGRAM', 'PRINT'}

问题:
以上是传递上下文的唯一方法吗?还是我做错了?如果使用是正确的,那么我倾向于将其作为bug进行报告。

编辑17.3-添加语法和源

当您调用parser.print()但向其提供输入时:

***************
* Hello world
***************
DECLAREPROGRAM  hw..
PRINT 'Hello World!'..

它不会起作用。对于print(),解析器期望像这样的输入PRINT 'Hello World!'..。对于整个输入,您将不得不调用prog()。此外,明智的做法是用EOF令牌"锚定"您的启动规则,这将迫使ANTLR消耗整个输入:

progm : stmt+ EOF;

如果您想解析并访问整个解析树(使用prog()(,但只对print节点/上下文感兴趣,那么最好使用监听器而不是访问者。查看此页面如何使用侦听器:https://github.com/antlr/antlr4/blob/master/doc/javascript-target.md

编辑

以下是监听器的工作方式(Python演示,因为我没有正确设置JS(:

import antlr4
from playground.MygrammarLexer import MygrammarLexer
from playground.MygrammarParser import MygrammarParser
from playground.MygrammarListener import MygrammarListener

class PrintPreprocessor(MygrammarListener):
def enterPrint_(self, ctx: MygrammarParser.Print_Context):
print("Entered print: `{}`".format(ctx.getText()))

if __name__ == '__main__':
source = """
***************
* Hello world
***************
DECLAREPROGRAM  hw..
PRINT 'Hello World!'..
"""
lexer = MygrammarLexer(antlr4.InputStream(source))
parser = MygrammarParser(antlr4.CommonTokenStream(lexer))
antlr4.ParseTreeWalker().walk(PrintPreprocessor(), parser.progm())

运行上述代码时,将打印以下内容:

Entered print: `PRINT'Hello World!'..`

因此,简而言之:这个监听器接受输入的整个解析树,但只有在我们输入print解析器规则时才"侦听"。

注意,我将print重命名为print_,因为print在Python目标中受到保护。

最新更新