ANTLR nie pasuje do znaku ucieczki Unicode

Piszę parser/interpreter dla języka podobnego do C i muszę zinterpretować znaki ucieczki. Jednym z nich jest sekwencja unicode z tym wzorcem „\uXXXX”, gdzie X jest liczbą szesnastkową.

Moje zasady ANTLR wyglądają tak:

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')

Podaję mu ten ciąg „ሴ”, dla którego oczekuję „e”, ale zamiast tego otrzymuję „/”, który jest regułą awaryjną dla wszystkiego innego.

Czy dzieje się jakieś magiczne juju z fragmentami i zasadami, czy coś, czego nie jestem świadomy?


person Pieter Breed    schedule 08.10.2011    source źródło
comment
Fragmenty powinny być używane tylko w regułach leksera, ale 'char' wygląda jak reguła parsera.   -  person    schedule 08.10.2011
comment
Ach tak, wyciągnąłem HEXNUMBER jako czteroelementową sekwencję HEXDIGIT. Nie wiem, dlaczego ANTLR nie narzeka na nakładanie się HEXDIGIT i DIGIT w tym przypadku ...   -  person Pieter Breed    schedule 08.10.2011


Odpowiedzi (1)


Jak wspomniał Adam, char jest w tej chwili regułą parsera, ale zamiast tego powinna być regułą leksera, w takim przypadku nie można pozwolić, aby zwróciła char (reguły leksera zawsze zwracają wystąpienie Token!).

Możesz dostosować tekst wewnętrzny tokenu za pomocą metody setText(...) w ten sposób (zakładając, że Java jest językiem docelowym):

// 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