2015-04-22 36 views
6

Wiele języków związany ciąg z pewnego rodzaju środki, tak:Jak mogę uciec z postaci ucieczki za pomocą ANTLR 4?

"Rob Malda is smart."

ANTLR 4 można dopasować taki ciąg z reguły Lexer jak ten:

QuotedString : '"' .*? '"';

Aby wykorzystać niektóre znaki w ciągu znaków muszą zostać usunięte, być może w ten sposób:

"Rob \"Commander Taco\" Malda is smart."

ANTLR 4 może również dopasować ten ciąg;

EscapedString : '"' ('\\"|.)*? '"';

(zaczerpnięte z P96 ostatecznego ANTLR 4 Reference)

Oto mój problem: Załóżmy, że postać na ucieczkę jest taki sam charakter jak ogranicznik strun. Na przykład:

"Rob ""Commander Taco"" Malda is smart."

(. Jest to całkowicie legalne w PowerShell)

Co lexer reguła będzie pasować do tego? Myślę, to będzie działać:

EscapedString : '"' ('""'|.)*? '"';

Ale tak nie jest. Lexer tokenizuje znak ucieczki " jako koniec ogranicznika łańcucha.

Odpowiedz

7

negować niektóre postacie z operatorem ~:

EscapedString : '"' ('""' | ~["])* '"'; 

lub, jeśli nie może być przerwy w swojej linii łańcucha, zrobić:

EscapedString : '"' ('""' | ~["\r\n])* '"'; 

Nie chcesz używać niechciany operator, inaczej "" nigdy nie zostanie zużyty, a "a""b" zostanie oznaczony jako "a" i "b" zamiast pojedynczego tokena.

+1

Działa, dziękuję. Ale działa tylko wtedy, gdy używam chciwego kwantyfikatora, a nie nie chciwego. Dlaczego? –

+1

@ james.garriss nie ma za co. Dodałem kilka dodatkowych informacji na temat nieagresywnego dopasowywania. –

+0

To bardzo interesujące zobaczyć, jak negacja działa jak nie-chciwy kwantyfikator. Chłodny. –

1

(nie głosować na tę odpowiedź; głos na odpowiedź @Bart Kiers').

Daję to pod względem kompletności, jak jest to mały kawałek gramatyki PowerShell. Łącząc logikę ucieczki od P76 do ostatecznego ANTLR 4 Reference z odpowiedzią Barta, oto zasady niezbędne dla Lexing uciekł sznurki w PowerShell:

EscapedString 
    : '"'  (Escape | '""' | ~["])* '"' 
    | '\''  (Escape | '\'\'' | ~['])* '\'' 
    | '\u201C' (Escape | .)*? ('\u201D' | '\u2033') // smart quotes 
    ; 

fragment Escape 
    : '\u0060\'' // backtick single-quote 
    | '\u0060"'  // backtick double-quote 
    ; 

Zasady te obsługiwać następujące cztery sposoby ucieczki ciągi w PowerShell:

'Rob ''Commander Taco'' Malda is smart.' 
"Rob ""Commander Taco"" Malda is smart." 
'Rob `'Commander Taco`' Malda is smart.' 
"Rob `"Commander Taco`" Malda is smart."