Как определить многосимвольное исключение в правиле лексера 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)
...
Что случилось? Каков возможный обходной путь?
2 ответа
Решение
Поскольку .*
а также .+
по умолчанию несерьезны, попытались просто сделать:
TEXT
: '"""' .* '"""'
{
...
}
;
?
Лучший способ, вероятно, с предикатом.
TEXT
: '"""'
( ~'"'
| {input.LA(2) != '"' || input.LA(3) != '"'}? '"'
)*
'"""'
;
Это работает в ANTLR 4 так же, как вы меняете input
в _input
в предикате.