我是 Antlr 的新手,我使用 Antlr 3 定义了基本语法。语法编译并且 ANTLRWorks 生成解析器和词法分析器代码没有任何问题。
语法如下:
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 网站和其他一些示例,空白区域是“”。我不知道该怎么办。我需要这个空的。
当它解释时,我得到以下异常:
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 : ' ';
最佳答案
我对用法仍然有点不确定,但我认为当我们说“空输入”时我们正在谈论同一件事。这是一个让事情开始的答案,从修改后的语法开始。
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
它之所以有效,是因为即使文本 Name
后面没有任何内容,filters
也会匹配:它使用第一个替代方案匹配空输入。
语法也接受这个:
Module1 I Name WHERE Module2
filters
规则满足与第二个替代项匹配的文本 WHERE Module2
(在语法中定义为 'WHERE' module
)。
更简洁的方法是将 filters
和 table
更改为以下规则(当然,要认识到我在第一名)。
filters : 'WHERE' module; //no more '|'
table : module object objectType filters?; //added '?'
语法匹配与之前相同的输入,但术语更清晰一些:而不是说“filters
is required in table
and filters
” > 匹配空”,我们现在说“filters
在 table
中是可选的,而 filters
不匹配空”。
在这种情况下,这相当于同样的事情。匹配空 (foo: | etc;
) 是完全有效的,但使用它时遇到的问题比匹配可选 (foo?
) 规则时遇到的问题更多。
Update following your update.
我在这里退一步,让我们脱离理论,进入实践。下面是更新的语法、调用它的 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 - 解释期间 Antlr MismatchedSetException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13510880/