使语法接受不同数值范围的问题

时间:2011-02-15 04:41:47

标签: java antlr grammar

我正在尝试创建一个接受两个整数范围的语法:

110000的整数1 和,025999

的整数2

这是我写的:

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

我面临以下问题:

  1. 当我将输入设为:set value1 3时,我得到一个例外:line 1:11 required (...)+ loop did not match anything at input '3'。另一方面,如果我将输入作为set value1 8,则其工作正常。为什么呢?

  2. 当我将输入设为:set value2 832时,我收到了异常:line 1:12 missing EOF at '3'。 如果我从语法中删除integer1integer2,另一个工作正常。为什么这样?为什么他们不合作。

  3. 我希望integer1拒绝0并接受10000。我应该在语法上做些什么改变?

  4. 我删除了integer2并修改了integer1

    integer1 @init {int N= 0;}: ((DIGIT { N++; } )+ { N <=4 }?) | '10000';

  5. 但如果我将输入设为set value1 10,则需要三个零。除了'10000'之外,它还没有准备接受任何以'1'开头的东西。

    提前致谢:)

    PS:我使用的是antlr-3.24

1 个答案:

答案 0 :(得分:2)

你的语法看起来有点奇怪:在组合语法的词法分析器部分中处理整数值的标记化要容易得多,然后在解析器规则中检查谓词是否值与边界一致。此外,在不同的通道上放置空格要容易得多,这样您就不必使用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