解析decaf的问题(变量声明与构造函数)

时间:2017-11-03 02:19:29

标签: parsing bison yacc context-free-grammar bisonc++

我正在使用bison(3.0.4)和lexer来实现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 文件的octal representation

1 个答案:

答案 0 :(得分:2)

基本问题是constructor_declmore可能为空,var_declconstructor_decl都可以ID开头。

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

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

  1. 减少空constructor_declmore,从而确定不再有var_decl s;或

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

  3. 在没有优先权声明的情况下(这里没有帮助),bison / yacc总是解决转移/减少冲突,转而支持转移行动。因此,在这种情况下,它会假定FooID,它会启动var_decl,从而导致您注意到的错误消息。

    还应该查看语法产生的减少/减少冲突。它来自method_declmore: method_decl规则,该规则与创建method_declmore的其他可能方式冲突,首先是空method_declmore,然后添加method_decl