2

DLTK を使用して、Eclipse でスキーム用の IDE を実装しています。これまでのところ、語彙構造を認識する文法をプログラミングしています。

私はここで見ることができる公式の EBNF に従っています:
http://rose-r5rs.googlecode.com/hg/doc/r5rs-grammar.html

数字の文法の単純な形式を取得できません。たとえば、10進数、私は持っています

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 : '""';

空の文字列には一致しませんが、2 つの二重引用符に一致します。

しかし、レクサー ルールが空の文字列のみに一致することは望ましくありません。これにより、任意の文字列/ソースに空の文字列が無限に存在するため、無限ループに陥ります。

したがって、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 文法を記述する代わりに、('i' | 'I')代わりに使用することをお勧めします。

編集

セバスチャンは次のように書いています。

しかし、私はまだPREFIX_10ルールに問題があります:fragment PREFIX_10 : RADIX_10? EXACTNESS? | EXACTNESS? RADIX_10?;これは、代替2が一致することは決してないことを示していますが、2つの代替は個別に一致する必要があり#i #dます#d #iか、それともここで何か間違っていますか?

(フラグメント) ルールにはいくつか問題がありますPREFIX_10

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

1 つには、両方とも空の文字列に一致します。選択肢 1 は常に空の文字列に一致するため、選択肢 2 は決して一致しません。これは、ANTLR が伝えていたことです。

ここで、BNF ルールを見てみましょう。

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

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

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

<empty> {#d}( に等しいことに注意してください。{#d}したがって、<empty>IMO は単に間違って配置されています。他のすべての半径には and がありません<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>ようになる場合 (つまり、 を配置するのを忘れた場合|):

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

その後、ANTLRPREFIX_10は次のようになります。

fragment PREFIX_10
  :  RADIX_10 EXACTNESS?
  |  EXACTNESS RADIX_10
  ;

ただし、使用する他のすべてのルールはオプションにするPREFIX_10必要がありPREFIX_10ます。

HTH

于 2011-06-07T14:57:55.523 に答える