จะกำหนดการยกเว้นหลายอักขระในกฎ ANTLR3 lexer ได้อย่างไร

ฉันกำลังพยายามสร้างกฎ lexer สำหรับ Antlr3 ซึ่งจะจับคู่สตริงที่มีเครื่องหมายคำพูดสามอัน ตัวอย่างเช่น:

"""this is some text"""

นี่คือวิธีที่ฉันทำ:

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

ใช้งานได้ดี แต่ต้องหลีกเครื่องหมายคำพูดทุกอันในข้อความอินพุต เช่นนี้

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

ฉันกำลังพยายามกำจัดการหลีกเลี่ยงเครื่องหมายคำพูดที่บังคับนี้ และแยกวิเคราะห์อะไรก็ได้ (!) ระหว่างเครื่องหมายคำพูดสามอัน เช่นนี้

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

ฉันกำลังพยายามเปลี่ยนกฎเป็น:

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

และ Antlr3 3.5 บ่น:

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

เกิดอะไรขึ้น? วิธีแก้ปัญหาที่เป็นไปได้คืออะไร?


person yegor256    schedule 30.06.2013    source แหล่งที่มา
comment
คุณถูก! เปลี่ยนสิ่งนี้เป็นคำตอบแล้วฉันจะยอมรับมัน   -  person yegor256    schedule 03.07.2013


คำตอบ (2)


เนื่องจาก .* และ .+ ไม่โลภ โดยค่าเริ่มต้น จึงได้ลองทำดังนี้:

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

?

person Bart Kiers    schedule 02.07.2013

วิธีที่ดีที่สุดน่าจะเป็นภาคแสดง

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

ใช้งานได้ใน ANTLR 4 และตราบใดที่คุณเปลี่ยน input เป็น _input ในเพรดิเคต

person Sam Harwell    schedule 30.06.2013
comment
ใช้งานได้เฉพาะในกรณีที่อินพุตทั้งหมดเริ่มต้นด้วย """ และลงท้ายด้วย """ มิฉะนั้น หากข้อความเป็น (""" hello """) ข้อยกเว้นจะถูกส่งออกไป: rule TEXT failed predicate: {input.LA(2) != '"' || input.LA(3) != '"'}? - person yegor256; 01.07.2013