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

Я пишу синтаксический анализатор / интерпретатор для 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», для которой ожидаю «е», но вместо этого получаю «/», которое является резервным правилом для всего остального.

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


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


Ответы (1)


Как упоминал Адам, 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')
  ;
person Bart Kiers    schedule 08.10.2011