ANTLR: грамматика для лексической структуры R5RS, проблема с числами - PullRequest
2 голосов
/ 07 июня 2011

Я реализую IDE для схемы в Eclipse, используя DLTK. До сих пор я программирую грамматику для распознавания лексической структуры.

Я слежу за официальным 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

плюс, я не уверен с моим решением пустой строки.

как мне здесь добраться?

1 Ответ

2 голосов
/ 07 июня 2011

Обратите внимание, что ваше правило 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 вы можете использовать ('i' | 'I').

EDIT

Себастьян написал:

но у меня все еще есть проблемы с правилом PREFIX_10: fragment PREFIX_10 : RADIX_10? EXACTNESS? | EXACTNESS? RADIX_10?;, которое говорит мне, что альтернатива 2 никогда не может быть сопоставлена, хотя она должна соответствовать #i #d и #d #i с2 варианта по отдельности или я что-то здесь не так делаю?

Есть пара вещей, которые не так с правилом (фрагмента) 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} равно {#d}, поэтому <empty> - это только IMO, неуместно. Все остальные радиусы не имеют и <empty> part)

Iпереведите их в следующие ( непроверенные! ) правила 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}

, тогда ANTLR PREFIX_10 должен выглядеть следующим образом:

fragment PREFIX_10
  :  RADIX_10 EXACTNESS?
  |  EXACTNESS RADIX_10
  ;

, но тогда все другие правила, использующие PREFIX_10, должны сделать PREFIX_10 необязательным.

HTH

...