我正在研究一个小型文本编辑器项目,并希望为几种语言添加基本的语法高亮(Java,XML ......仅举几例).作为一种学习经历,我想添加一个流行或非流行的Java词法分析器.
你推荐什么项目.Antlr可能是最知名的,但它似乎相当复杂和沉重.
这是我所知道的选项.
这应该很简单.我正在使用ANTLR编写词法分析器语法,并希望将变量标识符的最大长度限制为30个字符.我试图用这一行完成这个(遵循正常的正则表达式 - 除了''thing - 语法):
ID : ('a'..'z'|'A'..'Z') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'){0,29} {System.out.println("IDENTIFIER FOUND.");}
;
Run Code Online (Sandbox Code Playgroud)
代码生成没有错误,但由于生成的代码中的一行简单而导致编译失败:
0,29
显然,antlr将括号内的文本部分与打印线一起放在接受状态区域.我搜索了ANTLR网站,但没有找到相应表达式的示例或引用.这个表达式的语法应该是什么?
我的主要问题:我知道你可以通过反射来输出类字段,即使你不知道变量名,类型,甚至有多少.但是,有没有办法列出当前函数或当前范围内的所有变量,假设我不知道变量名是什么?
换一种说法:
int x = 5;
int y = 42;
// some more code
//Now I want to println x and y, but assuming I cannot use "x" or "y".
Run Code Online (Sandbox Code Playgroud)
我也很高兴回答这个问题:假设我允许存储所有变量的名称,这有帮助吗?例如:
Set<String> varNames = new HashSet<String>();
int x = 5;
varNames.add("x");
int y = 42;
varNames.add("y");
// some more code
//Now with varNames, can I output x and y without using "x" or "y"?
Run Code Online (Sandbox Code Playgroud)
我为什么这么问?我正在使用ANTLR将XYZ语言翻译成java,我想提供一种简单的方法来在任何时间点输出程序的整个状态.
第三种可能的解决方案我很满意:如果在Java中这是不可能的,有什么方法可以为访问调用函数并检查堆栈的函数编写字节码?这也可以解决问题.
令人惊奇的是,如果Java具有相当于Python eval()或php的功能get_defined_vars().
如果它有所作为,我使用Java 6,但Java 5,6或7的任何东西都应该是好的.
谢谢!
我使用AST树使用Antlr 3开发了一个复杂的语法.ANTLR生成Lexer和Parser.问题是当用户输入例如无效的语法时,语法期望';'.用户不输入,然后在我的Eclipse IDE中我得到以下异常:
line 1:24 mismatched input '<EOF>' expecting ';'
Run Code Online (Sandbox Code Playgroud)
如何处理此异常,因为我试图捕获此异常,但是没有捕获异常.这是一个例外吗?我似乎不明白为什么没有捕获此异常.我试图找出答案,但Antlr网站似乎已经停止了一段时间了.
我查看了以下内容:使用"$"和Java进行ANTLR异常处理并遵循该示例,但是当Lexer通过添加RuntimeException()生成代码时,我得到了无法访问的代码.
我不知道该怎么做.
当我尝试从解析器获取语法错误的数量时,它显示0.
编辑:
我找到了一个解决方案,通过查看:ANTLR不会在无效输入上抛出错误
但是,当我尝试获取Exception消息时,它为null.我是否正确设置了一切?请参阅示例语法:
grammar i;
options {
output=AST;
}
@header {
package com.data;
}
@rulecatch {
catch(RecognitionException e) {
throw e;
}
}
// by having these below it makes no difference
/**@parser::members {
@Override
public void reportError(RecognitionException e) {
throw new RuntimeException("Exception : " + " " + e.getMessage());
}
}
@lexer::members {
@Override
public void reportError(RecognitionException e) {
throw new RuntimeException("Exception …Run Code Online (Sandbox Code Playgroud) 我正在尝试用Maven构建一个ANTLR项目,项目结构就像
src/main +
|-antlr4
|-fo/bar
|-G1.g4
|-G2.g4
|-imports
Run Code Online (Sandbox Code Playgroud)
其中G1进口G2如:
grammar G1;
import G2;
Run Code Online (Sandbox Code Playgroud)
但是,当我使用Maven构建时,我收到以下错误:
[ERROR] Message{errorType=CANNOT_FIND_IMPORTED_GRAMMAR, args=[G2, fo\bar\G1.g4], e=null, fileName='null', line=-1, charPosition=-1}
Run Code Online (Sandbox Code Playgroud)
它的工作原理没有问题,如果我把G1.g4和G2.g4直属antlr4目录.在我看来,当将Grammar文件放在一个包中时,它需要在import语句中使用特殊语法.
我注意到Antlr4 maven插件无法在不同目录中找到语法文件的问题,但在这里,语法在一个目录中.
我正在尝试编写AST解释器/ REPL.ANTLRv4提供两个非常相似的接口(ParseTreeVisitor和ParseTreeListener)来遍历解析树.我似乎无法找到它们之间的任何重大差异,并且文档相当稀疏.一个界面比另一个更好吗?
我使用 ANTLR4 将一种语言翻译成另一种语言。例如,当我读取数字文字时,我可以返回Integeror Double。
@Override
public Integer visitIntegerValue(Parser.IntegerValueContext ctx) {
return Integer.valueOf(ctx.getText());
}
@Override
public Double visitDoubleValue(Parser.DoubleValueContext ctx) {
return Double.valueOf(ctx.getText());
}
Run Code Online (Sandbox Code Playgroud)
最终,如果您进一步扩展此方法并引入其他构造(例如字符串和条件),则对于访问者来说唯一合理的类型是class Visitor extends BaseVisitor<Object>,但它会导致代码大量添加instanceof. 例如
@Override
public CollectionQuery visitCondition(Parser.ConditionContext ctx) {
Property property = (Property) visit(ctx.property());
String operator = (String) visit(ctx.operator());
Object value = visit(ctx.amount());
Object condition;
if (value instanceof String && operator.equals("$regex")) {
condition = Pattern.compile((String) value, Pattern.CASE_INSENSITIVE);
}
...
}
Run Code Online (Sandbox Code Playgroud)
虽然我不介意这种“动态性”,但我想知道这是否是一种可维护的继续方式,或者是否应该使用其他技术,例如创建目标语言结构的适当层次结构。
我在bash 的 Antlr 解析器中找到了这个语法:
file_descriptor
: DIGIT -> ^(FILE_DESCRIPTOR DIGIT)
| DIGIT MINUS -> ^(FILE_DESCRIPTOR_MOVE DIGIT);
Run Code Online (Sandbox Code Playgroud)
语法有什么->作用?
它叫什么名字,我可以通过谷歌搜索来阅读它?
《Antlr4 权威指南》只有一页内容。它指的是“词法分析器命令”,但它从未命名运算符。书中的用法与 bash 解析器中的用法不同。
注意:这是一个自我回答的问题,旨在提供有关ANTLR用户最常犯错误之一的参考.
当我测试这个非常简单的语法时:
grammar KeyValues;
keyValueList: keyValue*;
keyValue: key=IDENTIFIER '=' value=INTEGER ';';
IDENTIFIER: [A-Za-z0-9]+;
INTEGER: [0-9]+;
WS: [ \t\r\n]+ -> skip;
Run Code Online (Sandbox Code Playgroud)
通过以下输入:
foo = 42;
Run Code Online (Sandbox Code Playgroud)
我最终得到以下运行时错误:
第1行:第6行不匹配输入'42'期望INTEGER
第1行:8输入不匹配';' 期待'='
为什么不承认ANTLR 42作为INTEGER在这种情况下?
它应该匹配模式[0-9]+就好了.
如果我颠倒了定义的顺序INTEGER并且IDENTIFIER定义它似乎有效,但为什么顺序首先重要?
我正在尝试在 Visual Studio 16.9.2 的 .NET 5 项目中安装 ANTLR 4 支持,但我无法确定应该使用众多 ANTLR NuGet 包中的哪一个。我想要一个根本不需要 Java(不仅仅是在运行时)并且不需要扩展的程序。
我最初使用 Antlr4 和 Antlr4.Runtime 包,它们似乎可以一起工作,但后来我发现它们缺少 CharStreams 类,据我所知,这是获取 ICharStream 对象的预期方法。
然后我尝试使用 Antlr4.Runtime.Standard 而不是 Antlr4.Runtime,但这似乎与 Antlr4 包不兼容。(它给了我很多编译错误。)然后我尝试将 Antlr4 换成其他软件包,但找不到与 Antlr4.Runtime.Standard 一起使用的软件包。
请有人指出生成器+运行时的有效组合?官方的包太多了,没必要不断地试错。我查看了几个在线教程,但它们往往适用于仍然使用 VSIX 的早期版本的 VS。