0

我正在编写一个简单的 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/

想法?

4

1 回答 1

0

这部作品让 Jison 感到困惑(它也让我感到困惑 :)):

NUMBER: {$$ = Number(yytext);};

NUMBER应该是一个终端,但是上面的产生式将它声明为一个空主体的非终端。由于它什么都不匹配,它立即匹配,并且您的语法不允许两个连续NUMBER的 s。因此错误。

另外,您的语法不明确,尽管我认为 Jison 的默认设置可以解决问题。不过,最好是明确的,因为它很容易。你的规则:

e   : rng 
    | e ',' e

没有指定如何,“关联”:换句话说,是否rng , rng , rng应该被视为e , rngrng , e。第一个可能更适合您,因此您应该明确地编写它:

e   :  rng
    |  e ',' rng

上面的一大优点是您不需要在第二个生产中创建新数组;您可以将其推$3到末尾$1并设置$$$1.

于 2013-11-14T15:12:18.177 回答