我有一个最小的语法示例,我想在Jison中使用。
/* lexical grammar */
%lex
%%
s+ /* skip whitespace */
[0-9]+("."[0-9]+)?b return 'NUMBER'
[0-9] return 'DIGIT'
[,-] return 'SEPARATOR'
// EOF means "end of file"
<<EOF>> return 'EOF'
. return 'INVALID'
/lex
%start expressions
%% /* language grammar */
expressions
: e SEPARATOR d EOF
{return $1;}
;
d
: DIGIT
{$$ = Number(yytext);}
;
e
: NUMBER
{$$ = Number(yytext);}
;
这里我定义了NUMBER
和DIGIT
,以便根据上下文同时允许数字和数字。我不知道的是,我如何定义上下文。上面的例子总是返回
Expecting 'DIGIT', got 'NUMBER'
当我尝试在Jison调试器中运行它时。如何定义语法,以便总是期望分隔符后面有一个数字?我尝试了以下不工作
/* lexical grammar */
%lex
%%
s+ /* skip whitespace */
[,-] return 'SEPARATOR'
// EOF means "end of file"
<<EOF>> return 'EOF'
. return 'INVALID'
/lex
%start expressions
%% /* language grammar */
expressions
: e SEPARATOR d EOF
{return $1;}
;
d
: [0-9]
{$$ = Number(yytext);}
;
e
: [0-9]+("."[0-9]+)?b
{$$ = Number(yytext);}
;
经典的扫描器/解析器模型(最初来自lex/yacc,也由jison实现)将扫描器置于解析器之前。换句话说,期望扫描器对输入流进行标记,而不考虑解析上下文。
大多数词法扫描器生成器,包括jison,都为扫描器提供了一种适应上下文的机制(参见"开始条件"),但是扫描器要自己负责跟踪上下文,这就变得相当难看了。
在这种情况下,最简单的解决方案是只定义一个NUMBER
令牌,并让解析器检查实际需要DIGIT
的规则的语义动作的有效性。这将起作用,因为DIGIT
和NUMBER
之间的差异除了使某些解析非法之外不会影响解析。如果NUMBER
和DIGIT
之间的差异决定了使用哪个产品,则会有所不同,但这可能是不明确的,因为所有数字实际上也是数字。
另一个解决方案是允许NUMBER
或DIGIT
,其中一个数字是允许的。这将需要更改e
,使其接受NUMBER
或DIGIT
,并确保DIGIT
在NUMBER
和DIGIT
都可能的情况下胜出。这需要将其规则放在语法文件的前面,并在末尾添加b
:
[0-9]b return 'DIGIT'
[0-9]+("."[0-9]+)?b return 'NUMBER'