Jison:区分数字和数字

时间:2015-09-29 16:05:17

标签: parsing grammar bison jison

我有一个我希望与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);}
    ;

这里我定义了NUMBERDIGIT,以便同时允许数字和数字,具体取决于上下文。我不知道的是我如何定义上下文。以上示例始终返回

Expecting 'DIGIT', got 'NUMBER'

当我尝试在Jison debugger中运行它时。如何定义语法以便始终期望分隔符后面的数字?我尝试了以下无效的

/* 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);}
    ;

1 个答案:

答案 0 :(得分:4)

经典的扫描器/解析器模型(最初来自lex / yacc,并且由jison实现)将扫描器放在解析器之前。换句话说,扫描程序需要对输入流进行标记,而不考虑解析上下文

大多数词汇扫描仪生成器(包括jison)为扫描仪提供了一种适应上下文的机制(参见“开始条件”),但扫描仪负责自行跟踪上下文,这非常难看。

在这种情况下,最简单的解决方案是仅定义NUMBER令牌,并让解析器检查实际需要DIGIT的规则的语义操作的有效性。这将起作用,因为除了使某些解析非法之外,DIGITNUMBER之间的差异不会影响解析。如果NUMBERDIGIT之间的差异确定要使用哪个生产,那将会有所不同,但这可能是不明确的,因为所有数字实际上都是数字。

另一种解决方案是允许NUMBERDIGIT允许使用数字。这需要更改e,以便接受NUMBERDIGIT,并确保在DIGIT和{{1}的情况下NUMBER获胜是可能的。这需要将其规则提前放在语法文件中,并在最后添加DIGIT

\b