互动式蚂蚁

互动式蚂蚁,第1张

互动式蚂蚁

Dutow写道:

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

这很慢,有些指令我不想运行两次,这可以用ANTLR来完成吗?

是的,ANTLR可以做到这一点。也许不是开箱即用,但是有了一些自定义代码,这肯定是可能的。您也不需要为此重新解析整个令牌流。

假设您要逐行解析一种非常简单的语言,其中每行要么是一个

program
声明,要么是一个声明,要么是
uses
一个
statement

它应始终以

program
声明开头,然后是零个或多个
uses
声明,然后是零个或多个
statement
s。
uses
声明不能在
statement
s
之后,并且不能超过一个
program
声明。

为简单起见,a

statement
只是一个简单的赋值:
a = 4
b = a

这种语言的ANTLR语法如下所示:

grammar REPL;parse  :  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();};

但是,我们当然需要添加一些检查。同样,默认情况下,解析器会在其构造函数中使用令牌流,但是由于我们计划逐行在解析器中滴入令牌,因此我们需要在解析器中创建一个新的构造函数。您可以通过将自定义成员分别放在

@parser::members{ ... }
@lexer::members { ...}
区域中来将它们添加到词法分析器或解析器类中。我们还将添加几个布尔标志,以跟踪
program
声明是否已经发生以及是否
uses
允许声明。最后,我们将添加一个
process(Stringsource)
方法,该方法为每行新代码创建一个词法分析器,该词法分析器将被馈送到解析器。

所有这些看起来像:

@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  } }

现在在语法中,我们将检查几个 门控语义谓词
是否以正确的顺序解析声明。并且在解析了某个声明或语句之后,我们希望从那时开始翻转某些布尔标志以允许或禁止声明。这些布尔标志的翻转是通过匹配解析器规则的标记

@after { ... }
执行的每个规则的部分完成的(毫不奇怪)。 __

现在,您最终的语法文件如下所示(包括一些

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();  } }parse  :  programDeclaration EOF  |  {programDeclDone}? (usesDeclaration | statement) EOF  ;programDeclaration@after{  programDeclDone = true;}  :  {!programDeclDone}? PROGRAM ID {System.out.println("ttt program <- " + $ID.text);}  ;usesDeclaration  :  {usesDeclAllowed}? USES idList {System.out.println("ttt uses <- " + $idList.text);}  ;statement@after{  usesDeclAllowed = false; }  :  left=ID '=' right=(INT | ID) {System.out.println("ttt " + $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.*;import java.util.Scanner;public class 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")) {     break; } 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
一次:

> program A   program <- A> program Bline 1:0 rule programDeclaration failed predicate: {!programDeclDone}?

uses
不能在
statement
s 之后出现:

> program X   program <- X> uses a,b,c   uses <- a,b,c> a = 666   a <- 666> uses d,eline 1:0 rule usesDeclaration failed predicate: {usesDeclAllowed}?

并且必须从

program
声明开始:

> uses fooline 1:0 rule parse failed predicate: {programDeclDone}?


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5506260.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-13
下一篇 2022-12-13

发表评论

登录后才能评论

评论列表(0条)

保存