我正在编写一个简单的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/
使用在线解析器生成器想法?
答案 0 :(得分:0)
这个制作混淆了Jison(它也使我感到困惑:)):
NUMBER: {$$ = Number(yytext);};
NUMBER
应该是一个终端,但上面的产品声明它是一个空体的非终端。因为它可以匹配任何东西,它会立即匹配,并且你的语法不允许连续两个NUMBER
。因此错误。
另外,你的语法含糊不清,虽然我认为Jison的默认会解决这个问题。不过,最好是明确的,因为它很容易。你的规则:
e : rng
| e ',' e
未指定,
“关联”的方式:换句话说,rng , rng , rng
是否应被视为e , rng
或rng , e
。第一个对你来说可能更好,所以你应该明确地写出来:
e : rng
| e ',' rng
上述一个很大的优点是你不需要在第二个产品中创建一个新的数组;您只需将$3
推到$1
的末尾,然后将$$
设置为$1
。