当访问者处理我的 ANTLR4 解析树时,有时我需要知道我的规则节点所在的父规则节点。在 的在线 API 文档中ParserRuleContext
,我发现没有可以返回对象所表示的规则名称的方法/字段。我知道规则名称是子ParserRuleContext
类名称的一部分,例如function_definition
规则节点是 class Function_definitionContext
。但要查询类名,我需要使用 Java 反射并手动Context
在末尾删除字符串。
是否有更简单的方法来检索对象所代表的规则名称ParserRuleContext
?
查询父规则节点的名称是一个常见的需求。例如,在处理 C++ 语法时,C++ 类声明可以位于全局范围、函数定义或另一个类声明中,这意味着规则节点class_declaration
可以嵌套在global_scope
,function_definition
或class_declaration
规则节点下。如果我只想隔离class_declaration
下的那些节点global_scope
,我需要查找父节点并确保它们不是function_definition
或class_declaration
。
我正在使用 ANTLR4 来上课,我似乎理解其中的大部分内容,但我不明白“+”的作用。我只能说它通常位于括号中的一组字符之后。
为了在antlr4-java目标中以不同的方式报告错误,我们执行以下操作:
(1)定义一个新的监听器:
class DescriptiveErrorListener extends BaseErrorListener {
public static DescriptiveErrorListener INSTANCE =
new DescriptiveErrorListener();
@Override
public void syntaxError(Recognizer<?, ?> recognizer,
Object offendingSymbol,
int line, int charPositionInLine,
String msg, RecognitionException e)
{
String printMsg = String.format("ERR: %s:%d:%d: %s",
recognizer.getInputStream().getSourceName(), line,
charPositionInLine+1, msg);
System.err.println(printMsg);
}
}
Run Code Online (Sandbox Code Playgroud)
(2) 重写词法分析器和解析器的报告器:
lexer.removeErrorListeners();
lexer.addErrorListener(DescriptiveErrorListener.INSTANCE);
..
parser.removeErrorListeners();
parser.addErrorListener(DescriptiveErrorListener.INSTANCE);
Run Code Online (Sandbox Code Playgroud)
c++目标中相应的代码是什么?
我有一个基于 antlr4 的项目,其主类包含以下代码:
package com.progur.langtutorial;
import java.io.FileInputStream;
import java.io.IOException;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
public class Main {
@SuppressWarnings("deprecation")
public static void main(String[] args) {
try {
ANTLRInputStream input = new ANTLRInputStream(
new FileInputStream(args[0]));
GYOOLexer lexer = new GYOOLexer(input);
GYOOParser parser = new GYOOParser(new CommonTokenStream(lexer));
parser.addParseListener(new MyListener());
// Start parsing
parser.program();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是,由于 ANTLRInputStream 已被弃用,我需要使用 CharStream 代替。但是,当我尝试使用 CharStream 时,我无法继续前进,
CharStream input = new ANTLRInputStream(
new FileInputStream(args[0]));
Run Code Online (Sandbox Code Playgroud)
这是因为我不知道如何替换“=”号之后的语句部分。我尝试过CharStreams.fromFileName(new FileInputStream(args[0]));
,但 Eclipse …
我正在尝试在 gradle 中设置 Antlr 任务,以在与包名称匹配的文件夹中生成源。
我尝试将包添加到语法的 @header 中,但这不会像 IntelliJ Antlr 插件那样生成包文件夹树。我还尝试按照下面的示例将包传递给属性来使用 CLI 参数。
generateGrammarSource {
maxHeapSize = "64m"
arguments += ["-package my.package.name", "-visitor"]
}
Run Code Online (Sandbox Code Playgroud)
然而我得到的是
任务:generateGrammarSource FAILED错误(2):未知的命令行选项-package my.package.name
当我将-package
和my.package.name
放入单独的条目 ( ["-package", "my.package.name", "-visitor"]
) 时,代码生成会运行,但既不会将包添加到代码中,也不会创建文件夹。好像被忽略了
我使用 Antlr 版本 4.7.2,并且 gradle 与 intellij 191 捆绑在一起。
是否有一种特定于 gradle 的方法可以根据包名称设置 antlr 插件的输出位置?
ANTLR4 ATN 中的原子转换、集合转换和 Epsilon 转换有什么区别?网上找不到任何定义。
我正在通过我的自定义语法处理我的输入文件并提取令牌并将其返回到HashMap
.在ANTLR 3中,我能够通过rule()
在解析器上调用方法并获取HashMap
类似的东西来解析文件parser.record
.
这似乎在ANTLR 4中不起作用.我参考了这本书,看来我必须调用parser.init()
才能开始解析但我在解析器中看不到任何方法.
我使用ANTLRWorks 2生成我的词法分析器和解析器文件.我没有生成监听器类.
我想支持类似于C++使用ANTLR4进行预处理宏替换的功能,该功能需要解析器稍微退出并重新扫描修改后的输入文件.
例如,在标准C++中:
#define a(x) b(x+1)
#define b(x) cc(x)
#define p1 a
....
p1(p1);
Run Code Online (Sandbox Code Playgroud)
在一个标准的C++预处理器,标识符p1
将被替换为a
引起a(a)
,然后C++预处理器将重新扫描所有该线以查看是否宏替换应再次应用到转a(a)
成b(a+1)
终于重新扫描线来获得cc(a+1)
.
我可以通过TokenStreamRewriter
在遍历解析树时使用ANTLR4来实现宏替换功能.但是目前在第一次替换p1
with之后a
,我需要保存修改后的输入文件并重新调用解析器来扫描整个输入文件并获取另一个解析树而不是仅重新扫描我已替换的行.是否有任何可能的方法将重新扫描限制为我修改的行(可能在运行中重新生成部分解析树)?输入文件很大,并且有很多这样的替换,在每次替换后重新扫描整个文件将是一个很好的性能问题.
解析器中是否有任何功能可以将解析回滚到之前的"保存点"?
我有以下语法:
grammar lab02;
@header{
package laboratorios.lab02;
}
word : [a-z]+ ;
op_plus : '+' ;
op_min : '-' ;
op_mul : '*' ;
op_div : '/' ;
WS : [ \t\r\n]+ -> skip ;
digit : ('0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9') ;
Run Code Online (Sandbox Code Playgroud)
这给出了一个错误说: error(50): lab02.g4:7:10: syntax error: 'a-z' came as a complete surprise to me while matching alternative.
我从一个例子中复制了它,但它在我的电脑上不起作用。看看数字规则:digit : ('0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9') ;
它是这样的,因为这是它不会报告错误的唯一方法。如果我使用 [0-9]+ 我得到:
error(50): lab02.g4:7:10: syntax error: '0-9' came as a complete surprise to me while matching alternative
Run Code Online (Sandbox Code Playgroud)
你知道为什么这不起作用吗?
我对 ANTLR 很Token
陌生,我试图了解ATNLR4 中到底是什么。考虑以下非常荒谬的语法:
grammar Tst;
init: A token=('+'|'-') B;
A: .+?;
B: .+?;
ADD: '+';
SUB: '-';
Run Code Online (Sandbox Code Playgroud)
ANTLR4 为其生成以下TstParser.InitContext
内容:
public static class InitContext extends ParserRuleContext {
public Token token; //<---------------------------- HERE
public TerminalNode A() { return getToken(TstParser.A, 0); }
public TerminalNode B() { return getToken(TstParser.B, 0); }
public InitContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_init; }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof TstListener …
Run Code Online (Sandbox Code Playgroud) 我目前正在...
error(56): AqlCommentTest.g4:12:4: reference to undefined rule: htmlCommentDeclaration
error(56): AqlCommentTest.g4:13:4: reference to undefined rule: mdCommentDeclaration
Run Code Online (Sandbox Code Playgroud)
词法分析器语法的导入似乎正在加载。以下文件存在问题。
AqlCommentTest.g4
grammar AqlCommentTest;
import AqlLexerRules;
import AqlComment;
program: commentDeclaration+;
commentDeclaration:
htmlCommentDeclaration #Comment_HTML
| mdCommentDeclaration #Comment_MD
;
Run Code Online (Sandbox Code Playgroud)
AqlComment.g4
grammar AqlComment;
import AqlLexerRules;
htmlCommentDeclaration: 'html' '{' '(*' STRING '*)' '}';
mdCommentDeclaration: 'md' '{' '(*' STRING '*)' '}';
Run Code Online (Sandbox Code Playgroud)
AqlLexerRules.g4
lexer grammar AqlLexerRules;
STRING : '"' [a-z]? '"' ;
Run Code Online (Sandbox Code Playgroud)
可以通过删除“import AqlLexerRules;”来停止错误 来自“AqlCommentTest.g4”文件。
为什么这可以“解决”问题?
如何检查是否实际应用了 antlr4 导入语句以及如何应用?