使用JAVA中的ANTLR从字符串中获取表达式

时间:2011-12-02 08:33:04

标签: java antlr

给出类似的字符串..

(a+(a+b)), (d*e) :- (e-f)

注意:(d * e)和(e-f)是不同的表达。如何从此字符串中获取表达式。我将语法定义为..

parse returns [String value]
  :  addExp {$value=$addExp.value;} EOF
  ;

addExp returns [String value]
  :  multExp {$value=$multExp.value;} (('+' | '-' | '*') multExp{$value+= '+' + $multExp.value;})*
  ;

multExp returns [String value]
  :  atom {$value=$atom.value;} (('*' | '/') atom {$value+=$atom.value;)*
  ;

atom returns [String value]
  :  x=ID {$value=$x.text;}
  |  '(' addExp ')' {$value='('+$addExp.value+')';}
  ;

ID    : 'a'..'z' | 'A'..'Z';

我试过..

ANTLRStringStream a=new ANTLRStringStream("(a+(a+b)), (d*e) :- (e-f)");
SLexer l=new SLexer(a);
CommonTokenStream c=new CommonTokenStream(l);
SParser p=new Sparser(c);

String exp;
while(exp = p.parse())
{
 System.out.println(exp);
}

我正在考虑像hasNext()这样的东西,然后抓取。

2 个答案:

答案 0 :(得分:1)

您的词法分析器规则TEXT可能与空字符串匹配,从而导致词法分析器创建无限量的标记。此外,您在规则之后不需要所有这些return语句:您可以通过在其后添加.text来简单地获取匹配的解析器(或词法分析器)规则。

您可以让解析器返回List<String>,或者让它返回单个String重复调用该解析器规则,直到遇到EOF

一个小小的演示:

grammar T;

@parser::members {
  public static void main(String[] args) throws Exception {
    String src = "likes(a, b) :- likes(a, X), likes(X, b). hates(a, b) " + 
        ":- hates(a,X), hates(X,b). likes(a,b) :- says(god, likes(a,b)).";
    TLexer lexer = new TLexer(new ANTLRStringStream(src));
    TParser parser = new TParser(new CommonTokenStream(lexer));
    List<String> statements = parser.parse();
    for(String s : statements) {
      System.out.println(s);
    }
  }
}

parse returns [List<String> statements]
@init{$statements = new ArrayList<String>();}
  :  (statement {$statements.add($statement.text);} ~TEXT+)+ EOF
  ;

statement
  :  TEXT OPAR params CPAR
  ;

params
  :  (param (COMMA param)*)?
  ;

param
  :  TEXT
  |  statement
  ;

COMMA : ',';
OPAR  : '(';
CPAR  : ')';
TEXT  : ('a'..'z' | 'A'..'Z')+;
SPACE : (' ' | '\t') {$channel=HIDDEN;};
OTHER : . ;

请注意,~TEXT+规则中的parseTEXT以外的一个或多个令牌匹配。

如果您现在创建词法分析器和解析器并运行TParser类:

* nix中/ MacOS的

java -cp antlr-3.3.jar org.antlr.Tool T.g
javac -cp antlr-3.3.jar *.java
java -cp .:antlr-3.3.jar TParser

java -cp antlr-3.3.jar org.antlr.Tool T.g
javac -cp antlr-3.3.jar *.java
java -cp .;antlr-3.3.jar TParser

您将看到以下内容正在打印到您的控制台:

likes(a, b)
likes(a, X)
likes(X, b)
hates(a, b)
hates(a,X)
hates(X,b)
likes(a,b)
says(god, likes(a,b))

修改

以下是如何返回与String相对的单个List<String>

@parser::members {
  public static void main(String[] args) throws Exception {
    String src = "likes(a, b) :- likes(a, X), likes(X, b). hates(a, b) " + 
        ":- hates(a,X), hates(X,b). likes(a,b) :- says(god, likes(a,b)).";
    TLexer lexer = new TLexer(new ANTLRStringStream(src));
    TParser parser = new TParser(new CommonTokenStream(lexer));
    String s;
    while((s = parser.parse()) != null) {
      System.out.println(s);
    }
  }
}

parse returns [String s]
  :  statement ~(TEXT| EOF)* {$s = $statement.text;}
  |  EOF                     {$s = null;}
  ;

答案 1 :(得分:0)

你应该能够重复调用句子()直到你输入结尾。