这个语法有歧义吗?



我正在尝试使用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呢?看起来它可能需要提前查找两个标记而不是一个,但这是盲目的猜测,并且json文档指出它不支持LL(k)语法。

您没有显示整个语法,但看起来您的问题是它无法区分简单名称的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选项或可以处理非lalr(1)语法的btyacc之类的工具。但是,我不确定Jison支持什么。

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

    property: propname name ;
    

相关内容

  • 没有找到相关文章

最新更新