Как определить исключение нескольких символов в правиле лексера ANTLR3?

Я пытаюсь создать правило лексера для 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