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

标签 java antlr grammar

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

来自 1 的整数 1至 100000 中的 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); 

我面临以下问题:

  1. 当我给出输入时:set value1 3我收到一个异常(exception):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';

但如果我将输入作为 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/

相关文章:

javascript - 如何解析 C# 代码然后将其序列化回文本文件

c - 这个C BNF语法不完整吗?

sql - ANTLR4 : ordering problem of parser rules for a keyword used in several rules (AND, 之间)

java - java中如何根据输入数据顺序/名称动态调用不同的setter方法?

javascript - less 文件的语法验证器

java - Objective-C 类别与其他语言的功能比较

java - ANTLR3:角色上没有可行的替代方案

parsing - Ocaml 解析字符串以生成树

java - 我们如何为给定的一组数字生成 N 长度数字的唯一组合

java - 在android中滚动 ListView 时如何不刷新