解释期间Antlr MismatchedSetException

时间:2012-11-22 10:39:41

标签: java antlr

我是Antlr的新手,我使用Antlr 3定义了基本语法。语法编译,ANTLRWorks生成Parser和Lexer代码,没有任何问题。

语法如下:

grammar i;

@header {
package i;
}

module      : 'Module1'| 'Module2';
object      : 'I';
objectType  : 'Name';
filters         : EMPTY | 'WHERE' module;
table       : module object objectType;
STRING      : ('a'..'z'|'A'..'Z')+;
EMPTY           : ' ';

问题是当我解释表Parser时,我得到一个MismatchedSetException。这是因为拥有EMPTY。一旦我从语法中删除EMPTY,解释就会起作用。我查看了Antlr网站和其他一些例子,空格是''。我不知道该怎么做。我需要这个EMPTY。

当它解释时,我得到以下例外:

Interpreting...
[11:02:14] problem matching token at 1:4 NoViableAltException(' '@[1:1: Tokens : ( T__4 | T__5 | T__6 | T__7 | T__8 | T__9 | T__10 | T__11 | T__12 | T__13 | T__14 | T__15 );])
[11:02:14] problem matching token at 1:9 NoViableAltException(' '@[1:1: Tokens : ( T__4 | T__5 | T__6 | T__7 | T__8 | T__9 | T__10 | T__11 | T__12 | T__13 | T__14 | T__15 );])

我将EMPTY更改为以下内容:

EMPTY : '';

而不是:

EMPTY : ' ';

它实际上解释了它。但是,我得到以下例外:

Interpreting...
[10:57:23] problem matching token at 1:4 NoViableAltException(' '@[1:1: Tokens : ( T__4 | T__5 | T__6 | T__7 | T__8 | T__9 | T__10 | T__11 | T__12 | T__13 | T__14 | T__15 | T__16 );])
[10:57:23] problem matching token at 1:9 NoViableAltException(' '@[1:1: Tokens : ( T__4 | T__5 | T__6 | T__7 | T__8 | T__9 | T__10 | T__11 | T__12 | T__13 | T__14 | T__15 | T__16 );])

但是,ANLTWorks仍会生成Lexer和Parser代码。

我希望你能提供帮助。

编辑:

grammar i;

@header {
package i;
}

select      : 'SELECT *' 'FROM' table filters';';
filters : EMPTY | 'WHERE' conditions;
conditions  : STRING operator value;
operator    : '=' | '!=';
true            : 'true';
value           : true;
STRING  : ('a'..'z'|'A'..'Z')+;
EMPTY           : ' ';

1 个答案:

答案 0 :(得分:1)

我仍然对使用情况有点不确定,但我认为当我们说“空输入”时,我们正在谈论同样的事情。这是一个让球滚动的答案,从修改后的语法开始。

grammar i;

@header {
package i;
}

module      : 'Module1'| 'Module2';
object      : 'I';
objectType  : 'Name';
filters     : | 'WHERE' module;
table       : module object objectType filters;
STRING      : ('a'..'z'|'A'..'Z')+;
WS          : (' '|'\t'|'\f'|'\n'|'\r')+ {skip();}; //ignore whitespace

请注意,我在filters规则的末尾添加table来解释我在说什么。

该语法接受以下输入(从规则table开始),如前所述:

  

Module1 I Name

它有效,因为filters匹配,即使文本Name后面没有任何内容:它使用第一个备选方案匹配空输入。

语法也接受这个:

  

Module1 I Name WHERE Module2

filters规则对匹配第二个备选项(在语法中定义为WHERE Module2)的文本'WHERE' module感到满意。

更简洁的做法是将filterstable更改为以下规则(当然,我认识到我首先更改了table。)

filters     : 'WHERE' module; //no more '|' 
table       : module object objectType filters?; //added '?'

语法匹配与之前相同的输入,但条款更清晰:我们现在说filterstable匹配“filters,而不是”filterstablefilters中是可选的,foo: | etc;在空”上不匹配“。

在这种情况下,这相同。在空(foo?)上匹配是完全有效的,但是我使用它时遇到的问题比匹配可选(grammar i; @header { package i; } selects : ( //test rule to allow processing multiple select calls. Don't worry about the details. {System.out.println(">>select");} select {System.out.println("<<select");} )+ ; select : 'SELECT *' 'FROM' table filters? ';' {System.out.println("\tFinished select.");} //test output ; module : 'Module1'| 'Module2'; object : 'I'; objectType : 'Name'; filters : 'WHERE' conditions {System.out.println("\tFinished filters.");} //test output ; table : module object objectType {System.out.println("\tFinished table.");} //test output ; conditions : STRING operator value {System.out.println("\tCondition test on " + $STRING.text);} ; operator : '=' | '!='; true_ : 'true'; //changed so that Java code could be generated value : true_; STRING : ('a'..'z'|'A'..'Z')+; WS : (' '|'\t'|'\f'|'\n'|'\r')+ {skip();}; //ignore whitespace )规则时遇到的问题更多。


  

更新后更新。

我在这里退后一步,让我们脱离理论,进入实践。这是一个更新的语法,调用它的Java测试代码,测试输入和测试输出。请试一试。

<强>语法 改进测试但遵循与以前相同的想法。

package i;
import java.io.InputStream;

import org.antlr.runtime.ANTLRInputStream;
import org.antlr.runtime.CharStream;
import org.antlr.runtime.CommonTokenStream;

public class TestiGrammar {
  public static void main(String[] args) throws Exception {
    InputStream resource = TestiGrammar.class.getResourceAsStream("itest.txt");

    CharStream input = new ANTLRInputStream(resource);

    resource.close();

    iLexer lexer = new iLexer(input);
    CommonTokenStream tokens = new CommonTokenStream(lexer);

    iParser parser = new iParser(tokens);
    parser.selects();
  }
}

<强> TestiGrammar.java

SELECT * FROM Module2 I Name;
SELECT * FROM Module2 I Name WHERE foobar = true; 
SELECT * FROM Module2 I Name WHERE dingdong != true;

itest.txt 测试输入文件

>>select
    Finished table.
    Finished select.
<<select
>>select
    Finished table.
    Condition test on foobar
    Finished filters.
    Finished select.
<<select
>>select
    Finished table.
    Condition test on dingdong
    Finished filters.
    Finished select.
<<select

测试输出

{{1}}