Я не 100% уверен, почему вы получите эту ошибку: я должен видеть всю грамматику для этого. В любом случае, нет необходимости проверять как is_a
, так и!is_a
. И оба действительны как $is_a
, так и is_a
.
Предположим, вы разбираете список чисел и каждый четвертый номер, с которым вы хотите обращаться через другую «ветвь». Грамматика для этого будет выглядеть так:
grammar T;
parse
@init{int n = 1;}
: (number[n\%4 == 0] {n++;})+ EOF
;
number [boolean multipleOf4]
: {multipleOf4}?=> Int {System.out.println("branch A -> " + $Int.text);}
| Int {System.out.println("branch B :: " + $Int.text);}
;
Int
: '0'..'9'+
;
Space
: (' ' | '\t' | '\r' | '\n') {skip();}
;
(обратите внимание, что %
является зарезервированным символ внутри Antlr грамматик (не внутри строковых литералов и комментариев, хотя), поэтому он нуждается в побег с обратной косой черты)
и может быть протестирована с классом:
import org.antlr.runtime.*;
public class Main {
public static void main(String[] args) throws Exception {
ANTLRStringStream in = new ANTLRStringStream("11 22 33 44 55 66 77 88 99");
TLexer lexer = new TLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
TParser parser = new TParser(tokens);
parser.parse();
}
}
Теперь генерировать парсер/лексера (A), компилировать все исходные файлы (B) и запустить основной класс (C):
java -cp antlr-3.2.jar org.antlr.Tool T.g // A
javac -cp antlr-3.2.jar *.java // B
java -cp .:antlr-3.2.jar Main // C
(на Windows, запустите его, выполнив java -cp .;antlr-3.2.jar Main
)
, который производит следующий вывод:
branch B :: 11
branch B :: 22
branch B :: 33
branch A -> 44
branch B :: 55
branch B :: 66
branch B :: 77
branch A -> 88
branch B :: 99
Так что, да, вам нужен был "коттеджный семантический предикат" ({boolean}?=>
) в данном случае, а не «валидирующий семантический предикат» ({boolean}?
). Разница между двумя предикатами объясняется в этом предыдущем SO Q & A: What is a 'semantic predicate' in ANTLR?
@ Kay, если вы хотите, вы можете опубликовать грамматику, над которой работаете, и я посмотрю позже. Возможно, вы не можете опубликовать его во всей своей форме (работе), но в этом случае я не смогу помочь (и не может быть кто-то другой, это мое предположение). –
Кажется, что язык должен быть «достаточно сложным» для решения проблемы. Сгенерированный код содержит 'alt45 = dfa45.предсказывать (вводить); 'строка в методе' branch (boolean is_a) '. DFA45.predict в свою очередь использует is_a для предикации следующей ветви, но переменная не передается вдоль. Теперь я использую 'b {if (! Is_b) throw new FailedPredicateException (...);}', который отлично работает для меня. Спасибо за ссылку «Что такое« семантический предикат »в ANTLR»! – kay
@ Кай, никаких проблем! –