ANTLR не соответствует экранированному символу Юникода - PullRequest
0 голосов
/ 08 октября 2011

Я пишу синтаксический анализатор / интерпретатор для языка, подобного C, и мне нужно интерпретировать экранированные символы. Одна из них - это экранированная Юникодом последовательность с этим шаблоном "\ 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", для которой я ожидаю 'e', ​​но вместо этого я получаю '/', что является запасным правилом для всего остального.

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

1 Ответ

1 голос
/ 09 октября 2011

Как уже упоминалось Адамом, 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')
  ;
...