【问题标题】:Antlr MismatchedSetException During Interpretation解释期间的 Antlr MismatchedSetException
【发布时间】:2012-11-22 10:39:40
【问题描述】:

我是 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           : ' ';

【问题讨论】:

  • 我怀疑您是否需要显式捕获空格,但如果没有更好地了解其用法,我无法确定。您能否举例说明您计划如何使用filters 规则?例如,如果您想使用 WHERE 关键字,输入会是什么样子?现在它没有连接到另一个规则,所以一个例子会有所帮助。
  • 好吧,我无法提供完整的细节。以上只是一个例子。我正在为我的公司开发语法,需求很大。我无法提供任何信息。你能帮忙吗?假设,需要空格。
  • 如上所述,如果没有 EMPTY,这个 NoViableAltException 仍然会发生。
  • 当我想到一个名为EMPTY 的规则时,我想到的是filters: | 'WHERE' module;(规则filters 满足第一个替代方案中的“空”输入)而不是filters: ' ' | 'WHERE' module;'(a第一个 alt 的单个空格)。只要您明确匹配空格(即,您没有跳过它),就必须在关键字和其他任何地方之间考虑它,所以我对那个 EMPTY 规则怒目而视。 ;)
  • EMPTY 只是一个空白空间。所以我想做的是:当用户什么都不输入时,语法接受它。

标签: java antlr


【解决方案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

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

此语法像以前一样接受以下输入(以规则 table 开头):

模块 1 的名称

它之所以有效,是因为 filters 匹配,即使文本 Name 后面没有任何内容:它使用第一个替代项匹配空输入。

语法也接受这个:

Module1 I 命名 WHERE Module2

filters 规则满足文本 WHERE Module2 匹配第二个选项(在语法中定义为 'WHERE' module)。

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

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

语法匹配与以前相同的输入,但术语更清晰一些:我们现在说“filters 是可选的,而不是说“tablefilters 匹配空时需要filterstablefilters 在空时不匹配”。

在这种情况下,它等同于同一件事。空匹配 (foo: | etc;) 是完全有效的,但我在使用它时遇到的问题比匹配可选 (foo?) 规则时遇到的问题更多。


更新后更新。

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

语法 进行了更改以进行测试,但遵循与以前相同的想法。

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

TestiGrammar.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();
  }
}

itest.txt测试输入文件

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

测试输出

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

【讨论】:

  • “|”也是如此实际上意味着一个空的空间?所以基本上,我不知道你是否了解 Java。但我想要实现的是这样的:私有字符串名称; name = new String(" ");
  • @user1646481 :filters: | 'WHERE' module; 中的| 之间的差距表示“如果没有读取任何内容,则认为此规则已满足”。 (新规则WS 确保跳过空格,因此实际空格完全不在图片中:它们现在实际上是“空输入”或“非输入”)。 filters 可以写成filters: 'WHERE' module | ;,把那个空的选项放在最后。
  • @user1646481 回复:new String(" "):我对 Java 很满意,但我需要一个适用于您的语法的示例来确定您的要求。没有那个,我们最终会互相交谈。 ://
  • 好的,我已经在上面进行了编辑。请查看编辑并让我知道您的想法。这应该让您了解为什么需要空字符串。
  • @user1646481 这有帮助,谢谢。 SELECT * FROM Foo;(分号前没有空格,没有提供过滤器)有效输入吗? SELECT &lt;many spaces here&gt; * &lt;many spaces here too&gt; From Foo; 在这里和那里有多余的空格怎么样?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-28
  • 1970-01-01
  • 2013-10-17
  • 1970-01-01
  • 2022-01-16
  • 1970-01-01
相关资源
最近更新 更多