为了账号安全,请及时绑定邮箱和手机立即绑定

ANTLR4 javascript 访问者中的 ctx

ANTLR4 javascript 访问者中的 ctx

慕后森 2022-05-22 16:19:24
使用 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';// LiteralSTRLIT             : '\'' .*? '\'' ;// Identifier ID              : [a-zA-Z0-9]+;// skipLINE_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 - 添加语法和源代码
查看完整描述

1 回答

?
慕村9548890

TA贡献1884条经验 获得超4个赞

当您调用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 目标中受到保护。


查看完整回答
反对 回复 2022-05-22
  • 1 回答
  • 0 关注
  • 186 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信