Расширение оператора выбора токена

У меня есть выражения в ANTLR3

num_addition
    : num_multi ((plus^|minus^) num_multi)*
    ;

Я хочу изменить токены «плюс» и «минус» на другой токен. Поэтому я попытался создать это правило перезаписи.

num_addition
    : num_multi (plus num_multi)* -> ^(num_multi ^(plus_special num_multi)*)
    | num_multi (minus num_multi)* -> ^(num_multi ^(minus_special num_multi)*)
    ;

Если я сделаю это, генерация в ANTLRWORKS займет больше времени, но она сгенерирует правильную грамматику и токены. Если я применю этот стиль к другим правилам, таким как «множество», «разделение», «равный» и т. д., в конечном итоге это приведет к тому, что ANTLRWORKS ничего не сделает, когда я нажму «Создать».

Согласно ANTLRWORKS ошибок нет, но когда я нажимаю генерировать, ничего не происходит.

Я неправильно переписываю для того, чего хочу достичь?


person meriley    schedule 06.03.2014    source источник


Ответы (1)


Вы не можете внедрить в свой AST любое производство или терминал, которые не соответствуют правилу синтаксического анализатора, для которого вы создаете AST. В вашем случае вы можете вставить plus или minus, так как они соответствуют правилу синтаксического анализатора, но вы не можете вставить plus_special или minus_special, так как они не соответствуют правилу синтаксического анализатора num_addition.

Однако вы можете вводить воображаемые токены.

Попробуйте что-то вроде этого:

grammar T;

tokens {
  // Some imaginary tokens:
  PLUS_SPECIAL;
  MINUS_SPECIAL;
}

// ...

num_addition
 : (a=num_multi -> $a) ( PLUS  b=num_multi -> ^(PLUS_SPECIAL  $num_addition $b)
                       | MINUS b=num_multi -> ^(MINUS_SPECIAL $num_addition $b)
                       )*
 ;

// ...

PLUS : '+';
MINUS : '-';
person Bart Kiers    schedule 06.03.2014
comment
Я ожидаю, что вы также можете вставить обычные токены (PLUS вместо PLUS_SPECIAL). Но вы правы насчет произвольных производств. - person Mike Lischke; 06.03.2014
comment
@MikeLischke, да, вы можете вставлять обычные токены (или AST из продуктов), если они совпадают внутри производства: вы не можете вставлять обычные токены, которые не совпадают внутри производства, из которого вы хотите создать AST. Я перефразирую свой ответ. - person Bart Kiers; 06.03.2014
comment
Отличный ответ. Именно то, что я искал! Граммер генерирует, но это определенно кажется медленнее. - person meriley; 06.03.2014
comment
Я использовал этот код во всех своих математических и логических операторах, и мне потребовалось около 4 минут, чтобы даже начать генерацию кода с помощью ANTLRWorks. Это было всего около 20 секунд назад. Это кажется неожиданным. - person meriley; 06.03.2014
comment
@meriley у тебя случайно не определено backtrack=true;? Если это так, вы можете попробовать включить memoize=true;, чтобы ускорить процесс. Также стоит попробовать дать ANTLR больше места в куче. Также проверьте, что это не ANTLRWorks, который все испортил: также проверьте из своей оболочки. - person Bart Kiers; 06.03.2014
comment
Спасибо. Я понял проблему. Я был не очень эффективен с одним из моих новых правил, и это приводило к раздуванию вещей. - person meriley; 08.03.2014