ANTLR эквивалент бизона REJECT action? - PullRequest
0 голосов
/ 18 мая 2009

Я пытаюсь проанализировать список пар Name=Value, где значение может содержать все, кроме пробелов (то есть значения могут содержать знаки равенства).
Имя ограничено обычными символами идентификатора.

Проблема в том, что токен «Значение» соответствует всему. Например, для ввода:

dude=sweet

анализатор сопоставит вход целом с токеном 'Value' (и выдаст MismatchedTokenException).

В bison была возможность назначать состояния токенам (или это было только для нетерминалов?), Так что они становятся «подходящими» для сопоставления только после явного перехода в это состояние.

РЕДАКТИРОВАТЬ Если подумать, это не сработает и в бизонах - разделение токенов уже произошло (в flex ); однако, я думаю, что был способ получить REJECT токенов, заставив flex попробовать второй лучший матч.

Вот моя грамматика ANTLR.

grammar command_string;

start   
    :    commandParam* EOF
    ;
commandParam 
    :   IDENTIFIER '=' CONTINUOUS_VALUE 
    ;
IDENTIFIER 
    :   ('-'|'_'|'a'..'z'|'A'..'Z'|'0'..'9')+ 
    ;
CONTINUOUS_VALUE
    :   ~( ALL_WS )+
    ;
WS
    :   (ALL_WS) +      { $channel = HIDDEN; }
    ;
fragment ALL_WS     
    :   ' ' | '\t' | '\r' | '\n' 
    ;

1 Ответ

1 голос
/ 31 августа 2009

У вас есть некоторое совпадение между CONTINUOUS_VALUE и IDENTIFIER (символы в IDENTIFIER являются подмножеством CONTINUOUS_VALUE. Вероятно, есть несколько способов решить эту проблему. Один из способов - запустить CONTINUOUS_VALUE с помощью «=», а затем убрать его вне текста. В CSharp это выглядело бы так:

CONTINUOUS_VALUE
    :   '=' ~( ALL_WS )+ { Text = Text.Substring(1, Text.Length - 1); }
    ;

Затем просто удалите '=' из правила commandParam.

Вторым способом было бы создать правила синтаксического анализатора IDENTIFIER и CONTINUOUS_VALUE (строчные буквы, как минимум, с первой буквы), тогда у вас есть контекст, чтобы выяснить, какой из них должен соответствовать. Вы могли бы также сделать их фрагментами и ссылаться на них в commandParam, но я не уверен, можете ли вы вкладывать фрагменты или нет, так как у вас уже есть фрагмент ALL_WS.

Кроме того, вам не нужен какой-то разделитель между парами NameValue?

...