Bezdepbonusu7Программирование: статьи и ответы

Вопрос

ANTLR не соответствует экранированному символу Unicode

Автор вопроса: Pieter BreedОтветов: 1

Я пишу синтаксический анализатор / интерпретатор для C-подобного языка, и мне нужно интерпретировать экранированные символы. Одна из них - это последовательность с экранированием Unicode с этим шаблоном "\ uXXXX", где X - некоторое шестнадцатеричное число.

Мои правила ANTLR выглядят так:

public char returns [char c]
    : '\\"' { $c = '"'; }
    | '\\\\' { $c = '\\'; }
    | '\\/' { $c = '/'; }
    | '\\b' { $c = '\b'; }
    | '\\f' { $c = '\f'; }
    | '\\n' { $c = '\n'; }
    | '\\r' { $c = '\r'; }
    | '\\t' { $c = '\t'; }
    | '\\u' HEXDIGIT HEXDIGIT HEXDIGIT HEXDIGIT { $c = 'e'; }
    | ~('\\' | '"') { $c = '/'; }
    ;

fragment HEXDIGIT
    : ('0'..'9'|'a'..'f'|'A'..'F')

Я скармливаю ему эту строку "\ u1234", для которой ожидаю "е", но вместо этого получаю "/", которое является резервным правилом для всего остального.

Есть ли какое-то волшебство с фрагментами и правилами или что-то, о чем я не знаю?

  • Фрагменты должны использоваться только в правилах лексера, но char выглядит как правило парсера. 08.10.2011
  • ах, верно, я вытащил HEXNUMBER как последовательность из четырех элементов HEXDIGIT. Не уверен, почему ANTLR не жалуется на перекрытие между HEXDIGIT и DIGIT в этом случае ... Pieter Breed 08.10.2011

antlrantlr3

Ответы

Ответ 1 · рейтинг 1 · Bart Kiers

Как упоминал Адам, char в настоящий момент является правилом синтаксического анализатора, но вместо этого следует сделать правило лексера, и в этом случае вы не можете позволить ему возвращать char (правила лексера всегда возвращают экземпляр Token!).

Вы можете настроить внутренний текст токена, используя его метод setText(...) следующим образом (при условии, что Java является целевым языком):

// lexer rules start with a capital!
Char
  :  '\\"'                                     { setText("\""); }
  |  '\\\\'                                    { setText("\\"); }
  |  '\\/'                                     { setText("/"); }
  |  '\\b'                                     { setText("\b"); }
  |  '\\f'                                     { setText("\f"); }
  |  '\\n'                                     { setText("\n"); }
  |  '\\r'                                     { setText("\r"); }
  |  '\\t'                                     { setText("\t"); }
  |  '\\u' HEXDIGIT HEXDIGIT HEXDIGIT HEXDIGIT
     {
       String hex = getText();
       int i = Integer.parseInt(hex.substring(2), 16);
       setText(hex + " base 10 = " + i);
     }
  |  ~('\\' | '"')
  ;

fragment HEXDIGIT
  :  ('0'..'9'|'a'..'f'|'A'..'F')
  ;

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы