- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在尝试使用 antlr 编写一种简单的交互式(使用 System.in 作为源)语言,但我遇到了一些问题。我在网上找到的例子都是使用每行循环,例如:
while(readline)
result = parse(line)
doStuff(result)
但是如果我正在编写类似 pascal/smtp/etc 的东西,“第一行”看起来像 X 要求怎么办?我知道它可以在 doStuff 中检查,但我认为逻辑上它是语法的一部分。
或者如果一个命令被分成多行怎么办?我可以试试
while(readline)
lines.add(line)
thử
result = parse(lines)
lines = []
doStuff(result)
nắm lấy
nop
但是我也隐藏了真正的错误。
或者我可以每次都重新解析所有行,但是:
这可以用 ANTLR 完成吗?如果不能,可以用其他东西吗?
câu trả lời hay nhất
Dutow wrote:
Or I could reparse all lines everytime, but:
it will be slow there are instructions I don't want to run twice Can this be done with ANTLR, or if not, with something else?
是的,ANTLR 可以做到这一点。也许不是开箱即用,但使用一些自定义代码,这肯定是可能的。您也不需要为它重新解析整个 token 流。
假设你想逐行解析一个非常简单的语言,其中每一行要么是一个chương trình
声明,要么是一个sử dụng
声明,要么是一个tuyên bố
。
它应该始终以程序
声明开头,后跟零个或多个sử dụng
声明,然后是零个或多个tuyên bố
。 sử dụng
声明不能跟在 statement
之后,并且不能有多个 chương trình
声明。
为简单起见,tuyên bố
只是一个简单的赋值:a = 4
hoặc b = một
。
这种语言的 ANTLR 语法可能如下所示:
grammar REPL;
phân tích
: programDeclaration EOF
| usesDeclaration EOF
| statement EOF
;
programDeclaration
: PROGRAM ID
;
usesDeclaration
: USES idList
;
statement
: ID '=' (INT | ID)
;
idList
: ID (',' ID)*
;
PROGRAM : 'program';
USES : 'uses';
ID : ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | '0'..'9')*;
INT : '0'..'9'+;
SPACE : (' ' | '\t' | '\r' | '\n') {skip();};
但是,我们当然需要添加一些检查。此外,默认情况下,解析器在其构造函数中采用 token 流,但由于我们计划在解析器中逐行添加 token ,因此我们需要在解析器中创建一个新的构造函数。您可以通过将自定义成员放在 @parser::members { ... }
hoặc @lexer::members { ... }
中来在词法分析器或解析器类中添加自定义成员> 部分分别。我们还将添加几个 boolean 标志来跟踪 chương trình
声明是否已经发生以及是否允许 sử dụng
声明。最后,我们将添加一个 process(String source)
方法,该方法为每个新行创建一个词法分析器,该词法分析器被提供给解析器。
所有这些看起来像:
@parser::members {
boolean programDeclDone;
boolean usesDeclAllowed;
public REPLParser() {
super(null);
programDeclDone = false;
usesDeclAllowed = true;
}
public void process(String source) throws Exception {
ANTLRStringStream in = new ANTLRStringStream(source);
REPLLexer lexer = new REPLLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
super.setTokenStream(tokens);
this.parse(); // the entry point of our parser
}
}
现在在我们的语法中,我们将检查几个 gated semantic predicates 如果我们以正确的顺序解析声明。在解析了某个声明或语句之后,我们将希望翻转某些 boolean 标志以允许或禁止声明。这些 boolean 标志的翻转是通过每个规则的 @after { ... }
部分完成的,该部分被执行(毫不奇怪)hiện hữu来自该解析器规则的标记被匹配。
您的最终语法文件现在看起来像这样(包括一些用于调试目的的 System.out.println
):
grammar REPL;
@parser::members {
boolean programDeclDone;
boolean usesDeclAllowed;
public REPLParser() {
super(null);
programDeclDone = false;
usesDeclAllowed = true;
}
public void process(String source) throws Exception {
ANTLRStringStream in = new ANTLRStringStream(source);
REPLLexer lexer = new REPLLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
super.setTokenStream(tokens);
this.parse();
}
}
phân tích
: programDeclaration EOF
| {programDeclDone}? (usesDeclaration | statement) EOF
;
programDeclaration
@after{
programDeclDone = true;
}
: {!programDeclDone}? PROGRAM ID {System.out.println("\t\t\t program <- " + $ID.text);}
;
usesDeclaration
: {usesDeclAllowed}? USES idList {System.out.println("\t\t\t uses <- " + $idList.text);}
;
statement
@after{
usesDeclAllowed = false;
}
: left=ID '=' right=(INT | ID) {System.out.println("\t\t\t " + $left.text + " <- " + $right.text);}
;
idList
: ID (',' ID)*
;
PROGRAM : 'program';
USES : 'uses';
ID : ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | '0'..'9')*;
INT : '0'..'9'+;
SPACE : (' ' | '\t' | '\r' | '\n') {skip();};
可以通过以下类进行测试:
import org.antlr.runtime.*;
nhập java.util.Scanner;
lớp công khai Main {
public static void main(String[] args) throws Exception {
Scanner keyboard = new Scanner(System.in);
REPLParser parser = new REPLParser();
while(true) {
System.out.print("\n> ");
String input = keyboard.nextLine();
if(input.equals("quit")) {
phá vỡ;
}
parser.process(input);
}
System.out.println("\nBye!");
}
}
要运行这个测试类,请执行以下操作:
# generate a lexer and parser:
java -cp antlr-3.2.jar org.antlr.Tool REPL.g
# compile all .java source files:
javac -cp antlr-3.2.jar *.java
# run the main class on Windows:
java -cp .;antlr-3.2.jar Main
# or on Linux/Mac:
java -cp .:antlr-3.2.jar Main
如您所见,您只能声明一个程序
一次:
> program A
program <- A
> program B
line 1:0 rule programDeclaration failed predicate: {!programDeclDone}?
sử dụng
不能在 statement
之后:
> program X
program <- X
> uses a,b,c
uses <- a,b,c
> a = 666
a <- 666
> uses d,e
line 1:0 rule usesDeclaration failed predicate: {usesDeclAllowed}?
并且您必须以程序
声明开始:
> uses foo
line 1:0 rule parse failed predicate: {programDeclDone}?
关于java - 交互式 Ant ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5110507/
这个问题可能不是很清楚,所以让我用一个例子来说明我的意思。说我要复制几个文件夹: ... 但是我需要从如下所示的文本文件中加载它们,而不是在脚本中对这些文件夹
ant 和 ant clean all 的区别? 请任何人都可以清楚地说明何时使用 Ant 和 Ant 清洁所有。 C:> Ant c:> Ant 清理所有 最佳答案 “ant”运行项目的默认目标。
我想转换如下: 到: aoeu 的值可以包含任意数量的逗号分隔元素。 我可以使用 groovy Ant 任务,但不能使用 ant-contrib 中的任何
我看到了 this相关问题,但我的情况不同,所以再次询问。基本上,我必须按特定顺序运行 12 个 ant 文件。对于每个 ant 文件,我选择不同的目标,例如“创建”或“构建并部署全部”。如何创建一个
我可以编写一个在从另一个 ant 任务执行时获取参数的 ant 任务吗? 我通常试图实现的目标是重用现有任务不同的参数。 我不知道的是: ant中有这样的子任务吗? 它可以带参数吗? 如何以及在何处指
给定一个 ant 文件集,我需要对其执行一些类似 sed 的操作,将其压缩为多行字符串(每个文件有效一行),并将结果输出到文本文件。 我在寻找什么 Ant 任务? 最佳答案 Ant script ta
我有一个包含 jars 等绝对路径的属性文件。当使用这些属性时,它们以构建文件中指定的 basedir 为前缀。 我如何获得绝对路径? build.properties: mylib=/lib/myl
我有一个任务: someString someOtherString 如何连接 s
我遇到的情况涉及运行带有可选参数的 ant 构建,这些参数总是被指定但并不总是被定义,就像这样 ant -DBUILD_ENVIRONMENT=test -Dusername_ext= -Dconf.
我正在寻找一种在 Ant 文件中包含 .jar 的方法,以便我可以立即使用它并在我的目标中调用它的方法。 就我而言,它是 ant-contrib-1.0b3.jar . 最佳答案 最好的方法是将 An
我在 ant 方面比较新,在学校我有一个作业来做一个构建文件。我的问题之一是将其名称(或路径)作为 ant 参数的文件复制到“/foldercopy”。我需要做类似的事情: Ant cpfile文件.
亲爱的,我目前在检索foreach循环中设置的属性的值时遇到一些问题。也许你们中的一个可以帮助我... 目的是检查自从生成相应的jar之后,是否已修改文件夹的一个文件。这样,我知道是否必须再次生成ja
我想创建一个宏: 然后使用它: 但是,我想为隐式元素指定一个默认值......类似于: 所以我可以这样使用它:
我想将 ANT、JavaSDK 和 FlexSDK 包含到我的项目目录中。我需要我公司的人能够从源代码编译。 我有一个以以下内容开头的 build.bat 文件: ant blah/blah/blah
我想对目录中的每个文件使用 ant 脚本集只读 但 exec 不允许 filelist: The typ
如果我以 root 身份运行任务,有没有办法检测它是否以 root 身份运行并以不同的用户身份运行某些任务。 我有一些任务需要以 root 身份运行,但其他任务只需要以当前用户身份运行。 最佳答案 如
是否可以通过ant任务使用JUnit 4.6的新MaxCore运行程序? 最佳答案 从4.6开始,不幸的是没有。您需要创建自己的自定义Ant任务才能利用MaxCore功能。 关于ant - Ant J
我有一个关于 Ant 及其对环境变量的处理的问题。 为了说明我有一个小样本。 给定 Ant 构建文件 test.xml:
该文件如下所示: a1,b1 a2,b2 ... 我知道值“a2”。 如何将值“b2”转换为属性值。 我知道如何通过以下方式选择包含“a2”的行: 但是不知道如何将属性值设置为“b2”。 我
Ant 属性可以通过属性文件设置,从属性文件解析其他属性吗? 例如,我可以这样做: 和 prop2 变成“in_test_xml1”。那挺好的。 但在这种情况下,当使用输入属性文件时: prop1
Tôi là một lập trình viên xuất sắc, rất giỏi!