我正在尝试创建一个接受两个整数范围的语法:
来自 1
的整数 1至 10000
和 0
中的 integer2至 25999
这是我写的:
grammar first;
tokens {
SET = 'set';
VALUE1 = 'value1';
VALUE2 = 'value2';
SEPARATOR = ' ';
}
expr : SET SEPARATOR attribute EOF;
attribute : VALUE1 SEPARATOR integer1
| VALUE2 SEPARATOR integer2;
DIGIT : '0'..'9';
integer1 @init {int N= 0;}: ((DIGIT { N++; } )+ { N <=4 }?);
integer2 : integer1
| ('1' (DIGIT DIGIT DIGIT DIGIT))
| ('2' ('0' | '1' | '2' | '3' | '4' | '5') DIGIT DIGIT DIGIT);
我面临以下问题:
当我给出输入时:
set value1 3
我收到一个异常(exception):line 1:11 required (...)+ loop did not match anything at input '3'
.另一方面,如果我将输入作为set value1 8
,它工作正常。为什么?当我给出输入时:
set value2 832
我收到异常:line 1:12 missing EOF at '3'
. 如果我删除integer1
或integer2
从语法来看,另一个工作正常。为什么这样?为什么他们不一起工作。我要
integer1
拒绝0
并接受10000
.我应该在语法上做哪些修改?我删除了
integer2
并修改了integer1
.integer1 @init {int N= 0;}: ((DIGIT { N++; } )+ { N <=4 }?) | '10000';
但如果我将输入作为 set value1 10
,它期待三个零。它不准备接受以“1”开头的任何内容,“10000”除外。
提前致谢:)
PS:我用的是antlr-3.24
最佳答案
您的语法看起来有点奇怪:在组合语法的词法分析器部分处理整数值的分词要容易得多,然后通过解析器规则中的谓词检查该值是否在范围内。此外,将空格放在不同的 channel 上要容易得多,这样您就不必用 SEPARATOR
标记乱丢解析器规则。
一个小演示:
grammar K;
@parser::members {
private boolean inbounds(Token t, int min, int max) {
int n = Integer.parseInt(t.getText());
return n >= min && n <= max;
}
}
parse
: expr
;
expr
: Set Value1 integer1 {System.out.println("Value1 :: " + $integer1.text);}
| Set Value2 integer2 {System.out.println("Value2 :: " + $integer2.text);}
;
integer1
: Int {inbounds($Int, 1, 10000)}?
;
integer2
: Int {inbounds($Int, 0, 25999)}?
;
Value1 : 'value1';
Value2 : 'value2';
Set : 'set';
Int : '0'..'9'+;
Space : (' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;};
这里有一个小类来测试它:
import org.antlr.runtime.*;
public class Main {
public static void main(String[] args) throws Exception {
String source = args[0];
ANTLRStringStream in = new ANTLRStringStream(source);
KLexer lexer = new KLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
KParser parser = new KParser(tokens);
parser.expr();
}
}
下面是上面类的一些测试运行:
有效
java -cp .:antlr-3.2.jar Main "set value1 667"
Value1 :: 667
java -cp .:antlr-3.2.jar Main "set value1 10000"
Value1 :: 10000
java -cp .:antlr-3.2.jar Main "set value2 10001"
Value2 :: 10001
无效
java -cp .:antlr-3.2.jar Main "set value1 10001"
line 0:-1 rule integer1 failed predicate: {Integer.parseInt($Int.text) >= 1 && Integer.parseInt($Int.text) <= 10000}?
Value1 :: null
java -cp .:antlr-3.2.jar Main "set value2 30000"
line 0:-1 rule integer2 failed predicate: {Integer.parseInt($Int.text) >= 0 && Integer.parseInt($Int.text) <= 25999}?
Value2 :: null
java -cp .:antlr-3.2.jar Main "set value1 0"
line 0:-1 rule integer1 failed predicate: {Integer.parseInt($Int.text) >= 1 && Integer.parseInt($Int.text) <= 10000}?
Value1 :: null
关于java - 使语法接受不同范围的数值的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4999948/