Проблема с грамматикой 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 предполагается, что это терминал, но вышеупомянутая продукция объявляет его как нетерминал с пустым телом. Так как он ничего не может сопоставить, он сразу же совпадает, и ваша грамматика не допускает двух последовательных NUMBERs. Отсюда и ошибка.

Кроме того, ваша грамматика неоднозначна, хотя я полагаю, что по умолчанию Jison решит проблему. Тем не менее, было бы лучше быть явным, так как это легко. Ваше правило:

e   : rng 
    | e ',' e

не указывает как , "сподвижники": другими словами, rng , rng , rng следует рассматривать как e , rng или же rng , e, Первый, вероятно, лучше для вас, поэтому вы должны написать это явно:

e   :  rng
    |  e ',' rng

Одним из больших преимуществ вышеуказанного является то, что вам не нужно создавать новый массив во втором производстве; Вы можете просто подтолкнуть $3 на конец $1 и установить $$ в $1,

Другие вопросы по тегам