0

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

问题是当我解释表解析器时,我得到了一个 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           : ' ';
4

1 回答 1

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

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

table该语法像以前一样接受以下输入(以 rule 开头):

Module1 我的名字

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

语法也接受这一点:

模块 1 我命名 WHERE 模块 2

filters规则满足与WHERE Module2第二个备选方案匹配的文本('WHERE' module在语法中定义)。

更简洁的方法是更改filters​​并table遵循以下规则(当然,要认识到我table首先更改了)。

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

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

在这种情况下,它相当于同样的事情。对空 ( 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
于 2012-11-22T12:44:31.490 回答