2

我正在使用 DLTK 在 Eclipse 中为方案实现 IDE。到目前为止,我正在编写语法以识别词汇结构。

我正在关注官方的 EBNF,可以在这里查看:
http ://rose-r5rs.googlecode.com/hg/doc/r5rs-grammar.html

我无法得到一种简单形式的数字语法。例如十进制数字,我有

grammar r5rsnumbers;

options {
  language = Java;
}


program:
NUMBER;

// NUMBERS


NUMBER : /*NUM_2 | NUM_8 |*/ NUM_10; //| NUM_16;
fragment NUM_10 : PREFIX_10 COMPLEX_10;
fragment COMPLEX_10 
: REAL_10 (
            '@' REAL_10
            | '+' (
                    UREAL_10 'i'
                    | 'i'
                    )?  
            | '-' (
                    UREAL_10 'i'
                    | 'i'
                    )?
            )?
    | '+' (
        UREAL_10 'i'
        | 'i'
        )?  
    | '-' (
        UREAL_10 'i'
        | 'i'
        )?;

fragment REAL_10 : SIGN UREAL_10;
fragment UREAL_10 
    : UINTEGER_10 ('/' UINTEGER_10)?
    | DECIMAL_10;
fragment UINTEGER_10 : DIGIT_10+ '#'*;

fragment DECIMAL_10 
    : UINTEGER_10 SUFFIX
    | '.' DIGIT_10+ '#'* SUFFIX
    | DIGIT_10+ '.' DIGIT_10* '#'* SUFFIX
    | DIGIT_10+ '#'+ '.' '#'* SUFFIX;

fragment PREFIX_10 
    : RADIX_10  EXACTNESS
    | EXACTNESS RADIX_10;

fragment DIGIT : '0'..'9';
fragment EMPTY : '""'; // empty is the empty string
fragment SUFFIX : EMPTY | EXPONENT_MARKER SIGN DIGIT_10+;
fragment EXPONENT_MARKER : 'e' | 's' | 'f' | 'd' | 'l';
fragment SIGN : EMPTY | '+' |  '-';
fragment EXACTNESS : EMPTY | '#i' | '#e';
fragment RADIX_10 : EMPTY | '#d';
fragment DIGIT_10 : DIGIT;

问题是,它没有识别任何东西。我不明白我从 PREFIX_10 得到的警告或如何解决它。如果我不在规则中使用片段,则文件不会编译,因为他抱怨 DIGIT_10 规则与几乎所有其他先前规则匹配相同的输入。

num_2、num_8 和 num_16 也一样

另外,我不确定我的空字符串解决方案。

我怎么绕过这里?

4

1 回答 1

3

请注意,您的 ANTLR 规则:

EMPTY : '""';

不匹配空字符串,而是两个双引号。

但是您不希望词法分析器规则匹配一个空字符串:这将导致它进入无限循环,因为任何字符串/源中都有无限数量的空字符串。

所以 BNF 规则:

<real 10>
    ::= <sign> <ureal 10>

<sign>
    ::= <empty> | {+} | {-}

不应翻译为以下 ANTLR 规则

REAL_10 
  :  SIGN UREAL_10
  ;

SIGN 
  :  EMPTY 
  |  '+' 
  |  '-'
  ;

但像这样:

REAL_10 
  :  SIGN? UREAL_10
  ;

SIGN 
  :  '+' 
  |  '-'
  ;

另请注意,您的规则:

fragment COMPLEX_10 
: REAL_10 (
            '@' REAL_10
            | '+' (
                    UREAL_10 'i'
                    | 'i'
                    )?  
            | '-' (
                    UREAL_10 'i'
                    | 'i'
                    )?
            )?
    | '+' (
        UREAL_10 'i'
        | 'i'
        )?  
    | '-' (
        UREAL_10 'i'
        | 'i'
        )?;

有点难读。以不同的方式缩进可能会使这更容易理解:

fragment COMPLEX_10
  :  REAL_10 ( '@' REAL_10 
             | '+' (UREAL_10 'i' | 'i')? 
             | '-' (UREAL_10 'i' | 'i')?
             )?
  |  '+' (UREAL_10 'i' | 'i')?  
  |  '-' (UREAL_10 'i' | 'i')?
  ;

这可以通过编写来简化:

fragment COMPLEX_10
  :  REAL_10 ('@' REAL_10)?
  |  REAL_10? ('+' | '-') UREAL_10? 'i'
  ;

另请注意,许多 BNF 符号不区分大小写文字。'i'因此,您可能想改用 ANTLR 语法,而不是编写您的 ANTLR 语法('i' | 'I')

编辑

塞巴斯蒂安写道:

但我仍然对PREFIX_10规则有问题:fragment PREFIX_10 : RADIX_10? EXACTNESS? | EXACTNESS? RADIX_10?;它告诉我替代方案 2 永远无法匹配,尽管它应该与#i #d2#d #i个替代方案单独匹配,还是我在这里做错了什么?

(片段)规则有一些问题PREFIX_10

fragment PREFIX_10 
  :  RADIX_10? EXACTNESS? // alternative 1
  |  EXACTNESS? RADIX_10? // alternative 2
  ;

一方面,两者都匹配一个空字符串。因为替代 1 将始终匹配一个空字符串,所以替代 2 永远不会匹配,这就是 ANTLR 告诉你的。

现在,查看 BNF 规则:

<exactness>
    ::= <empty> | {#i} | {#e}

<prefix 10>
    ::= <radix 10> <exactness>
      | <exactness> <radix 10>

<radix 10>
    ::= <empty> {#d}

(请注意,<empty> {#d}equals {#d},所以<empty>是 IMO 只是放错了位置。所有其他半径都没有和<empty>部分)

我会将它们翻译成以下(未经测试!)ANTLR规则:

fragment EXACTNESS
  :  '#i' 
  |  '#e'
  ;

fragment PREFIX_10
  :  RADIX_10 EXACTNESS?
  |  EXACTNESS RADIX_10 // **
  ;

fragment RADIX_10
  :  '#d'
  ;

**请注意,它不是

fragment PREFIX_10
  :  RADIX_10 EXACTNESS? // matches '#d'
  |  EXACTNESS? RADIX_10 // matches '#d'
  ;

因为词法分析器不知道通过哪个替代来匹配#d

如果 BNF 规则<radix 10>应该是这样的(即他们忘记放置 a |):

<radix 10>
    ::= <empty> 
      | {#d}

那么 ANTLRPREFIX_10仍应如下所示:

fragment PREFIX_10
  :  RADIX_10 EXACTNESS?
  |  EXACTNESS RADIX_10
  ;

但是所有其他使用的规则都PREFIX_10应该是PREFIX_10可选的。

高温高压

于 2011-06-07T14:57:55.523 回答