ANTLR4 javascript 访问者中的 ctx

使用 ANTLR4 v4.8


我正在编写转译器探索使用 ANTLR(带有访问者的 javascript 目标)。


语法 -> lex/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      : [\r\n]+ -> skip;

WS              : [ \t\n\r]+ -> 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]

我一起相信这是因为children它null不是被填充的。

这反过来又是由于 line 9:0 mismatched input '<EOF>' expecting {'DECLAREPROGRAM', 'PRINT'}


问题:

上面是传递上下文的唯一方法还是我做错了?如果使用正确,那么我倾向于将其报告为错误。


编辑 17.3 - 添加语法和源代码


慕后森
浏览 187回答 1
1回答

慕村9548890

当您调用parser.print()但输入输入时:**************** Hello world***************DECLAREPROGRAM&nbsp; 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 antlr4from playground.MygrammarLexer import MygrammarLexerfrom playground.MygrammarParser import MygrammarParserfrom playground.MygrammarListener import MygrammarListenerclass PrintPreprocessor(MygrammarListener):&nbsp; &nbsp; def enterPrint_(self, ctx: MygrammarParser.Print_Context):&nbsp; &nbsp; &nbsp; &nbsp; print("Entered print: `{}`".format(ctx.getText()))if __name__ == '__main__':&nbsp; &nbsp; source = """&nbsp; &nbsp; &nbsp; &nbsp; ***************&nbsp; &nbsp; &nbsp; &nbsp; * Hello world&nbsp; &nbsp; &nbsp; &nbsp; ***************&nbsp; &nbsp; &nbsp; &nbsp; DECLAREPROGRAM&nbsp; hw..&nbsp; &nbsp; &nbsp; &nbsp; PRINT 'Hello World!'..&nbsp; &nbsp; """&nbsp; &nbsp; lexer = MygrammarLexer(antlr4.InputStream(source))&nbsp; &nbsp; parser = MygrammarParser(antlr4.CommonTokenStream(lexer))&nbsp; &nbsp; antlr4.ParseTreeWalker().walk(PrintPreprocessor(), parser.progm())运行上述代码时,将打印以下内容:Entered print: `PRINT'Hello World!'..`因此,简而言之:此侦听器接受您输入的整个解析树,但仅在我们输入print解析器规则时“侦听”。请注意,我重命名print为print_因为print在 Python 目标中受到保护。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript