ANTLR 3内の文字列リテラル内のエスケープシーケンスを処理する方法は?
質問
私はANTLR v3のドキュメント(および「確定ANTLRリファレンス」の私の信頼できるコピー)を介して見てきた、と私は文字列リテラルのエスケープシーケンスを実装するためのクリーンな方法を見つけるように見えることはできません(私は現在よ)Javaのターゲットを使用して。私のような何かを行うことができることを望んでいた。
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
」になることを望む。
残念ながら、setText(...)
断片中ESCAPE_SEQUENCE
コールは、私が欲しいものは明らかではありません全体STRING
トークン、のテキストを設定します。
、結果の文字列を通じて戻って、手動で(setText(escapeString(getText()))
ルールでSTRING
のようなもので、例えば、)エスケープシーケンスを交換する方法を追加することなく、この文法を実装する方法はありますか?
解決
ここで私は私が書いた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()));}
)
;
他のヒント
文字列を変換するためにCharSupport:
ANTLR4については、Javaの目標と標準は、文字列の文法を脱出し、私は専用のシングルトンクラスを使用していました。それはANTLR APIで提供されます:
STRING : '"'
( ESC
| ~('"'|'\\'|'\n'|'\r')
)*
'"' {
setText(
org.antlr.v4.misc.CharSupport.getStringFromGrammarStringLiteral(
getText()
)
);
}
;
私はV4のマニュアルおよび実験によって見たように、@Initはもはやレクサーの一部でサポートされています。!
他の(おそらくより効率的な)別のルールの引数を使用することである。
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)); }
);
私はちょうどそれを行うために必要な、私の目標は、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ます。
所属していません StackOverflow