ANTLR4 javascript 访问者中的 ctx
ctx in ANTLR4 javascript visitor
使用 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());
访客的使用似乎并不简单, post 在一定程度上有所帮助。
使用 上下文。当我击中每个节点时,有什么好的方法来跟踪 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()
。此外,"anchor" 使用 EOF 令牌的起始规则是明智的,这将强制 ANTLR 消耗整个输入:
progm : stmt+ EOF;
如果你想解析和访问整个解析树(使用prog()
),但只对print
node/context感兴趣,那么最好使用监听器而不是访客。查看此页面如何使用侦听器: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
解析器规则时 "listens"。
请注意,我将 print
重命名为 print_
,因为 print
在 Python 目标中受到保护。
使用 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());
访客的使用似乎并不简单,
使用 上下文。当我击中每个节点时,有什么好的方法来跟踪 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()
。此外,"anchor" 使用 EOF 令牌的起始规则是明智的,这将强制 ANTLR 消耗整个输入:
progm : stmt+ EOF;
如果你想解析和访问整个解析树(使用prog()
),但只对print
node/context感兴趣,那么最好使用监听器而不是访客。查看此页面如何使用侦听器: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
解析器规则时 "listens"。
请注意,我将 print
重命名为 print_
,因为 print
在 Python 目标中受到保护。