Проблема с грамматикой Jison, странная ошибка при генерации dparser
Я пишу простую грамматику Jison, чтобы получить некоторый опыт, прежде чем начинать более сложный проект. Я попробовал простую грамматику, представляющую собой список числовых диапазонов, разделенных запятыми, с диапазонами, в которых начальное и конечное значения были одинаковыми, чтобы использовать сокращение одного номера. Однако, когда я запускаю сгенерированный парсер на тестовом вводе, я получаю ошибку, которая не имеет для меня большого смысла. Вот грамматика, которую я придумал:
/* description: Parses end executes mathematical expressions. */
/* lexical grammar */
%lex
%%
\s+ /* skip whitespace */
[0-9]+ {return 'NUMBER'}
"-" {return '-'}
"," {return ','}
<<EOF>> {return 'EOF'}
. {return 'INVALID'}
/lex
/* operator associations and precedence */
%start ranges
%% /* language grammar */
ranges
: e EOF
{return $1;}
;
e : rng { $$ = $1;}
| e ',' e {alert('e,e');$$ = new Array(); $$.push($1); $$.push($3);}
;
rng
: NUMBER '-' NUMBER
{$$ = new Array(); var rng = {Start:$1, End: $3; }; $$.push(rng); }
| NUMBER
{$$ = new Array(); var rng = {Start:$1, End: $1; }; $$.push(rng);}
;
NUMBER: {$$ = Number(yytext);};
Тестовый ввод это:
5-10,12-16
Выход:
Parse error on line 1:
5-10,12-16
^
Expecting '-', 'EOF', ',', got '8'
Если он помещает 'a' спереди, я получаю и ожидаю ошибку об обнаружении "INVALID", но у меня нет "8" во входной строке, так что мне интересно, это внутреннее состояние?
Я использую генератор парсера онлайн по адресу: http://zaach.github.io/jison/try/
мысли?
1 ответ
Это производство сбивает с толку Jison (и это меня смутило тоже:)):
NUMBER: {$$ = Number(yytext);};
NUMBER
предполагается, что это терминал, но вышеупомянутая продукция объявляет его как нетерминал с пустым телом. Так как он ничего не может сопоставить, он сразу же совпадает, и ваша грамматика не допускает двух последовательных NUMBER
s. Отсюда и ошибка.
Кроме того, ваша грамматика неоднозначна, хотя я полагаю, что по умолчанию Jison решит проблему. Тем не менее, было бы лучше быть явным, так как это легко. Ваше правило:
e : rng
| e ',' e
не указывает как ,
"сподвижники": другими словами, rng , rng , rng
следует рассматривать как e , rng
или же rng , e
, Первый, вероятно, лучше для вас, поэтому вы должны написать это явно:
e : rng
| e ',' rng
Одним из больших преимуществ вышеуказанного является то, что вам не нужно создавать новый массив во втором производстве; Вы можете просто подтолкнуть $3
на конец $1
и установить $$
в $1
,