2009-02-02 74 views
19

我一直在瀏覽ANTLR v3文檔(以及我的可信副本「The Definitive ANTLR reference」),並且我似乎無法找到一種乾淨的方式在字符串文字中實現轉義序列(我目前正在使用Java目標)。我本來希望能夠做這樣的事情:如何在ANTLR 3中處理字符串文字中的轉義序列?

fragment 
ESCAPE_SEQUENCE 
    : '\\' '\'' { setText("'"); } 
    ; 

STRING 
    : '\'' (ESCAPE_SEQUENCE | ~('\'' | '\\'))* '\'' 
     { 
     // strip the quotes from the resulting token 
     setText(getText().substring(1, getText().length() - 1)); 
     } 
    ; 

例如,我想輸入令牌「'Foo\'s House'」成爲字符串「Foo's House」。

不幸的是,ESCAPE_SEQUENCE片段中的setText(...)調用設置了整個STRING令牌的文本,這顯然不是我想要的。

有沒有一種方法來實現此語法,而無需添加方法返回結果字符串並手動替換轉義序列(例如,STRING規則中的setText(escapeString(getText())))?

回答

14

這是我在我寫的JSON解析器中完成的。

STRING  
@init{StringBuilder lBuf = new StringBuilder();} 
    : 
      '"' 
      (escaped=ESC {lBuf.append(getText());} | 
      normal=~('"'|'\\'|'\n'|'\r')  {lBuf.appendCodePoint(normal);})* 
      '"'  
      {setText(lBuf.toString());} 
    ; 

fragment 
ESC 
    : '\\' 
     ( 'n' {setText("\n");} 
     | 'r' {setText("\r");} 
     | 't' {setText("\t");} 
     | 'b' {setText("\b");} 
     | 'f' {setText("\f");} 
     | '"' {setText("\"");} 
     | '\'' {setText("\'");} 
     | '/' {setText("/");} 
     | '\\' {setText("\\");} 
     | ('u')+ i=HEX_DIGIT j=HEX_DIGIT k=HEX_DIGIT l=HEX_DIGIT 
        {setText(ParserUtil.hexToChar(i.getText(),j.getText(), 
               k.getText(),l.getText()));} 

     ) 
    ; 
+4

我使用了這種方法,但是請注意,我必須在每一步中追加「getText()」而不是「escaped.getText()」。片段將未轉義的文本寫入整個STRING標記,getText()返回。對於我來說,escaped.getText()返回原始片段的反斜槓完整。 – 2009-03-20 14:39:32

3

我需要這樣做,但我的目標是C而不是Java。以下是我如何根據答案#1(和評論)做到的,以防萬一任何人需要類似的東西:

QUOTE :  '\''; 
STR 
@init{ pANTLR3_STRING unesc = GETTEXT()->factory->newRaw(GETTEXT()->factory); } 
     :  QUOTE (reg = ~('\\' | '\'') { unesc->addc(unesc, reg); } 
         | esc = ESCAPED { unesc->appendS(unesc, GETTEXT()); })+ QUOTE { SETTEXT(unesc); }; 

fragment 
ESCAPED :  '\\' 
       ('\\' { SETTEXT(GETTEXT()->factory->newStr8(GETTEXT()->factory, (pANTLR3_UINT8)"\\")); } 
       | '\'' { SETTEXT(GETTEXT()->factory->newStr8(GETTEXT()->factory, (pANTLR3_UINT8)"\'")); } 
       ) 
     ; 

HTH。

4

另一個(可能更有效)的選擇是使用規則參數:

STRING 
@init { final StringBuilder buf = new StringBuilder(); } 
: 
    '"' 
    (
    ESCAPE[buf] 
    | i = ~('\\' | '"') { buf.appendCodePoint(i); } 
    )* 
    '"' 
    { setText(buf.toString()); }; 

fragment ESCAPE[StringBuilder buf] : 
    '\\' 
    ('t' { buf.append('\t'); } 
    | 'n' { buf.append('\n'); } 
    | 'r' { buf.append('\r'); } 
    | '"' { buf.append('\"'); } 
    | '\\' { buf.append('\\'); } 
    | 'u' a = HEX_DIGIT b = HEX_DIGIT c = HEX_DIGIT d = HEX_DIGIT { buf.append(ParserUtil.hexChar(a, b, c, d)); } 
    ); 
+0

好主意,它工作正常。感謝分享。 – 2012-07-04 07:34:24

4

對於ANTLR4,Java的目標和標準的轉義字符串語法,我用了一個專門的單例類:CharSupport翻譯字符串。它在antlr API中可用:

STRING   : '"' 
       ( ESC 
       | ~('"'|'\\'|'\n'|'\r') 
       )* 
        '"' { 
         setText( 
          org.antlr.v4.misc.CharSupport.getStringFromGrammarStringLiteral(
           getText() 
          ) 
         ); 
        } 
       ; 

正如我在V4文檔和實驗中看到的,@init在詞法分析器部分不再支持!

+0

你的例子中ESC的定義是什麼? – Jaap 2015-07-10 10:40:09

相關問題