Как исключить символы / символы, используя грамматику ANTLR? - PullRequest
4 голосов
/ 09 июля 2010

Я пытаюсь написать грамматику для различных форматов времени (12:30, 0945, 1: 30-2: 45, ...), используя ANTLR. Пока это работает как шарм, пока я не набираю символы, которые не были определены в файле грамматики.

Я использую следующий тест JUnit, например:

    final CharStream stream = new ANTLRStringStream("12:40-1300,15:123-18:59");
    final TimeGrammarLexer lexer = new TimeGrammarLexer(stream);
    final CommonTokenStream tokenStream = new CommonTokenStream(lexer);
    final TimeGrammarParser parser = new TimeGrammarParser(tokenStream);

    try {
        final timeGrammar_return tree = parser.timeGrammar();
        fail();
    } catch (final Exception e) {
        assertNotNull(e);
    }

Исключение выдается (как и ожидалось), потому что "15: 123" недопустимо. Однако если я попытаюсь («15: 23а»), не будет сгенерировано исключение, и ANTLR будет рассматривать его как допустимый ввод.

Теперь, если я определяю символы в моей грамматике, ANTLR, кажется, замечает их, и я снова получаю желаемое исключение:

  CHAR: ('a'..'z')|('A'..'Z');

Но как исключить умлауты, символы и другие вещи, которые пользователь может набирать (äöü {% & <>!). Так что в основном я ищу какой-то синтаксис, который говорит: сопоставить все, но "0..9,: -"

Ответы [ 2 ]

5 голосов
/ 12 июля 2010

...Так что в основном я ищу какой-то синтаксис, который говорит: соответствует всему, НО "0..9,:-"

Следующее правило соответствует любому отдельному символу, кроме цифры, ,, : и -:

Foo
  :  ~('0'..'9' | ',' | ':' | '-')
  ;

(~ отрицает одиночные символы в правилах лексера)

Но вы можете разместить всю грамматику: у меня сложилось впечатлениеЕсть некоторые другие вещи, которые вы делаете не так, как следовало бы.Ваш звонок.

2 голосов
/ 09 июля 2010

вы можете определить литерал, который соответствует всем символам, которые вам не нужны.Если этот литерал не содержится ни в одном из ваших правил, antlr сгенерирует исключение NonViableException.

Для юникода это может выглядеть так:

 UTF8 :  ('\u0000'..'\u002A'     // ! to * 
     | '\u002E'..'\u002F'           // . / 
     | '\u003B'..'\u00FF'           // ; < = > ? @ as well as letters brackets and stuff
     ) 
     ;
...