Bagaimana cara mendefinisikan pengecualian multi-karakter dalam aturan lexer ANTLR3?

Saya mencoba membuat aturan lexer untuk Antlr3, yang akan cocok dengan string yang diberi tanda kutip tiga. Misalnya:

"""this is some text"""

Inilah cara saya melakukannya:

TEXT:
  '"""' ('\\"' | ~'"')+ '"""'
  { 
    this.setText(
      this.getText()
        .substring(3, this.getText().length() - 3)
        .replace("\\\"", "\"")
    ); 
  }
  ;

Berfungsi dengan baik, tetapi setiap tanda kutip harus di-escape dalam teks masukan, seperti ini:

"""this is the same text, but with \"escaped quotes\" inside"""

Saya mencoba menghilangkan pelepasan tanda kutip wajib ini, dan mengurai apa pun (!) di antara tanda kutip rangkap tiga, seperti ini:

"""sample text again, with "quotes" inside"""

Saya mencoba mengubah aturan menjadi:

TEXT:
  '"""' (~'"""')+ '"""'

Dan Antlr3 3.5 mengeluh:

error(100): Spec.g:153:13: syntax error: buildnfa: NoViableAltException(58@[])
error(100): Spec.g:0:1: syntax error: buildnfa: MismatchedTreeNodeException(3!=29)
error(100): Spec.g:0:: syntax error: buildnfa: NoViableAltException(3@[])
error(100): Spec.g:0:1: syntax error: buildnfa: MismatchedTreeNodeException(29!=28)
error(10):  internal error: Spec.g : java.lang.NullPointerException
org.antlr.tool.NFAFactory.build_Aplus(NFAFactory.java:516)
...

Apa yang salah? Apa solusi yang mungkin?


person yegor256    schedule 30.06.2013    source sumber
comment
Kamu benar! Ubah ini menjadi jawaban dan saya akan menerimanya   -  person yegor256    schedule 03.07.2013


Jawaban (2)


Karena .* dan .+ secara default tidak serakah, cobalah melakukan hal berikut:

TEXT
 : '"""' .* '"""'
   { 
     ... 
   }
 ;

?

person Bart Kiers    schedule 02.07.2013

Cara terbaik mungkin adalah dengan predikat.

TEXT
  : '"""'
    ( ~'"'
    | {input.LA(2) != '"' || input.LA(3) != '"'}? '"'
    )*
    '"""'
  ;

Ini berfungsi di ANTLR 4 selama Anda mengubah input menjadi _input pada predikatnya.

person Sam Harwell    schedule 30.06.2013
comment
Ini hanya berfungsi jika seluruh masukan dimulai dengan """ dan diakhiri dengan """. Jika tidak, jika teksnya, katakanlah, (""" hello """), pengecualiannya adalah: rule TEXT failed predicate: {input.LA(2) != '"' || input.LA(3) != '"'}? - person yegor256; 01.07.2013