2011-02-11 1 views
3

Я хотел бы реализовать «ветвь» в ANTLR3.ANTLR3: Параметры и семантические предикаты («не удается найти символ», «незаконный запуск типа»)

Я понял, используя

branch[boolean is_a] 
    : ({ $is_a}? => a) 
    | ({!$is_a}? => b); 

будет делать трюк, но я получаю компиляции ошибки «не может найти символ» и «незаконное начало типа», потому что в в создаваемом источнике, т.е. DFA45.specialStateTransition(...) не имеет параметр is_a.

Я пробовал исключить => ¹ и/или опустить $ из $is_a.

ПЕРВЫЕ наборы a и b не являются дизъюнктными.

Фактически b имеет тип ((C) => c) | a.

¹), как я не понимаю разницу между {...}? => ... и {...}? ...

ответ

3

Я не 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?

+0

@ Kay, если вы хотите, вы можете опубликовать грамматику, над которой работаете, и я посмотрю позже. Возможно, вы не можете опубликовать его во всей своей форме (работе), но в этом случае я не смогу помочь (и не может быть кто-то другой, это мое предположение). –

+0

Кажется, что язык должен быть «достаточно сложным» для решения проблемы. Сгенерированный код содержит 'alt45 = dfa45.предсказывать (вводить); 'строка в методе' branch (boolean is_a) '. DFA45.predict в свою очередь использует is_a для предикации следующей ветви, но переменная не передается вдоль. Теперь я использую 'b {if (! Is_b) throw new FailedPredicateException (...);}', который отлично работает для меня. Спасибо за ссылку «Что такое« семантический предикат »в ANTLR»! – kay

+0

@ Кай, никаких проблем! –