sách gpt4 ăn đã đi

java - 交互式 Ant

In lại 作者:搜寻专家 更新时间:2023-11-01 01:57:32 30 4
mua khóa gpt4 giày nike

我正在尝试使用 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

但是我也隐藏了真正的错误。

或者我可以每次都重新解析所有行,但是:

  1. 会很慢
  2. 有些指令我不想运行两次

这可以用 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/

30 4 0
Chứng chỉ ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com
Xem sitemap của VNExpress