这个语法是不明确的?

时间:2013-02-26 07:57:23

标签: grammar bison bnf jison

我正在尝试使用Jison定义一种语言,并且只有很少的标点符号 - 例如CoffeeScript,但没有缩进。这就是我想要实现的目标:

# Definition
object1, object2
    property1 = value1,
    property2 = value2

# Definition
object3 property = value

# Statement
object1 + object2 + object3

这定义了具有一些属性的三个对象并添加它们。请注意,第一个定义使用名称列表指定两个对象,第二个定义表明空格不应该是重要的。

尽管名称列表和属性列表之间缺少开始和结束符号,但我觉得语法并不含糊。语法指定每个名称列表后跟属性列表。如果我写一个语法只是指定定义,包括像:

这样的产品,这一切似乎都能正常工作
definition
    : name_list property_list
    ;

name_list
    : name
    | name_list ',' name
    ;

property_list
    : property
    | property_list ',' property
    ;

property
    : name '=' name
    ;

现在,我以一种相当正常的方式为语法的表达式部分添加规则,据我所知:

expr
    : expr '+' expr
    | expr '/' expr
    | name
    ;

Jison抱怨在一些编号状态下,对于一堆不同的前瞻代币,“可能采取多种行动”。减少选项通常如下:

- reduce by rule: name_list -> name
- reduce by rule: expr -> name

我相信语法是明确的,但我怎么能说服杰森呢?似乎它可能需要向前看两个令牌而不是一个令牌,但这是一个盲目的猜测,并且Jison文档指出它(但是?)不支持LL( k )语法。

1 个答案:

答案 0 :(得分:1)

你没有显示整个语法,但看起来你的问题是它无法分辨出一个简单名称的expr和一个具有单一名称的声明的开头之间的区别在名单中。考虑输入

A B = C

A B C = D

第一种情况是具有一个属性的A的单一定义,而第二种情况是A的表达式,后跟B的定义。

问题在于解析器需要在看到A并查看B的前瞻之后决定这些情况,但它不能 - 它需要更多的前瞻(看看是什么)在B)之后

通过改变语言或获得(有效)额外的预测,你可以做很多事情来避免这种情况。

  1. 更改语言。可能是一个只是单个名称的语句没有任何意义。因此,您可以将语言更改为具有不允许使用简单名称的单独statement规则:

    statement: expr '+' expr | expr '/' expr ;
    expr: statement | name ;
    

    现在它可以区分statementdeclaration而无需额外的预测,因为statement必须包含运算符。

  2. 更改工具。您可以使用bison的%glr-parser选项或类似btyacc的工具来处理非LALR(1)语法。但是,我完全不确定Jison支持的是什么。

  3. 在词法分析器中模拟额外的前瞻。你可以让你的词法分析器为你做额外的预测。您可以使用匹配[a-zA-Z]+[ \t\n]*=的词法分析器模式(即名称后跟=符号),并返回一个特殊的propname令牌而不是name。然后,您的property规则变为:

    property: propname name ;