javascript - 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 - 添加语法和源代码
解决方案
当您调用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 目标中受到保护。
推荐阅读
- scala - 参数化测试 SCIO (JobTest) 和 Scala 测试 (forAll)
- json - 如何在flutter中访问ModelName / ProviderName的数据表单实例
- replace - C#如何读取文本文件-查找/替换文本-删除空格-最后用替换的数量更新一行
- html - 在 VBA 中的 Access 中将 RTF 嵌入式 OLE 转换为 HTML
- ios - 统一导出后xcode中的admob横幅错误
- ios - 如何在 UIAlertAction 中传递多个处理程序
- python - Django 如何从外部 api 数据更新模型对象字段
- git - 'git branch' 根本不显示任何内容
- oracle - 运行使用其他模式的用户 Oracle 过程
- c++ - 不知道出了什么问题(字符串输入)