0

我正在使用野牛(3.0.4)和词法分析器来实现 Decaf 编程语言的(部分)语法。我只是在实现类内的内容。

因此,我的任务很简单:将每个生产规则(作为字符串)存储在树中,然后将其打印出来。

例如,如果您将以下代码行作为输入

class Foo { Foo(int arg1) { some2 a; } }

你(必须)得到以下输出

<ClassDecl>         --> class identifier <classBody>
<ClassBody>         --> { <VariableDecl>* <ConstructorDecl>* <MethodDecl>* }
<ConstructorDecl>   --> identifier ( <ParameterList> ) <Block>
<ParameterList>     --> <Parameter> <, Parameter>*
<Parameter>         --> <Type> identifier
<Type>              --> <SimpleType>
<SimpleType>        --> int
<Block>             --> { <LocalVariableDecl>* <Statement>* }
<LocalVariableDecl> --> <Type> identifier ;
<Type>              --> <SimpleType>
<SimpleType>        --> identifier

第一个问题(已解决)是它解析了变量声明而不是构造函数声明,尽管我在类本身的范围内没有变量声明(即我只有在构造函数的块内)。这解决了。

不过,如果我给出以下内容class abc { some1 abc; john doe; },它会说syntax error, unexpected SEMICOLON, expecting LP. 因此,第 19 行的字符导致了问题。

这是.y文件(仅classBody规则)

class_decl:
  CLASS ID LC class_body RC
  ;


/* FIXME: Gotta add more grammar here */
class_body: var_declmore constructor_declmore method_declmore
  | var_declmore constructor_declmore
  | var_declmore method_declmore
  | constructor_declmore method_declmore
  | method_declmore
  | var_declmore
  | constructor_declmore
  | %empty
  ;


var_declmore: var_decl
  | var_declmore var_decl
  ;


constructor_declmore: constructor_decl
  | constructor_declmore constructor_decl 
  ;

var_decl: type ID SEMICOLON
  | type ID error
  ;

constructor_decl: ID LP parameter_list RP block
  | ID error parameter_list RP block
  ;

这是完整.y文件的要点。

4

1 回答 1

2

本质问题是constructor_declmore可以为空,并且两者var_declconstructor_decl都可以以 开头ID

这是一个问题,因为在解析器能够识别 a 之前constructor_decl,它需要减少 a (empty) constructor_declmore。但它显然不能做这种减少,除非它知道 var_declmore已经完成。

因此,当它看到一个时,ID它必须在两个动作之一之间做出决定:

  1. 减少一个空的constructor_declmore,从而决定没有更多var_decl的s;或者

  2. 移动ID以开始解析新的var_decl.

在没有优先级声明的情况下(在这里没有帮助),bison/yacc 总是解决 shift/reduce 冲突以支持 shift 动作。因此,在这种情况下,它假定FooID以 a 开头的var_decl,导致您注意到的错误消息。

还应该查看语法产生的 reduce/reduce 冲突。它来自method_declmore: method_decl规则,它与创建 a 的另一种可能方式相冲突,即method_declmore从空开始method_declmore然后添加 a method_decl

于 2017-11-03T17:28:37.517 回答