Parsing 解析DECF时出现问题(变量声明与构造函数)

Parsing 解析DECF时出现问题(变量声明与构造函数),parsing,bison,yacc,context-free-grammar,bisonc++,Parsing,Bison,Yacc,Context Free Grammar,Bisonc++,我正在使用bison(3.0.4)和lexer来实现Decaf编程语言的(部分)语法。我只是在实现课堂上的东西 因此,我的任务很简单:将每个产生式规则(作为字符串)存储在树中,然后打印出来 例如,如果您有以下代码行作为输入 class Foo{Foo(intarg1){some2a;}} 您(必须)获得以下输出 <ClassDecl> --> class identifier <classBody> <ClassBody>

我正在使用bison(3.0.4)和lexer来实现Decaf编程语言的(部分)语法。我只是在实现课堂上的东西

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

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

class Foo{Foo(intarg1){some2a;}}

您(必须)获得以下输出

<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

下面是完整的.y文件的示例。

基本问题是
constructor\u declmore
可以为空,并且
var\u decl
constructor\u decl
都可以以
ID
开头

这是一个问题,因为在解析器能够识别
构造函数\u decl
之前,它需要减少一个(空的)
构造函数\u declmore
。但它显然无法做到这一点,除非它知道
var_declmore
已经完成

因此,当它看到一个
ID
时,它必须在以下两种操作中选择一种:

  • 减少一个空的
    constructor\u declmore
    ,从而决定不再有
    var\u decl
    s;或

  • 移动
    ID
    ,以开始解析新的
    var\u decl

  • 在没有优先声明的情况下(这在这里没有帮助),bison/yacc总是解决移位/减少冲突,以支持移位操作。因此,在本例中,它假设
    Foo
    是启动
    var_decl
    ID
    ,导致您注意到的错误消息


    还应注意语法产生的reduce/reduce冲突。它来自
    方法declmore:method decl
    规则,它与创建
    方法declmore
    的其他可能方式相冲突,即从空的
    方法declmore
    开始,然后添加
    方法decl

    基本问题是
    构造函数declmore
    可以为空,而且
    var\u decl
    constructor\u decl
    都可以以
    ID
    开头

    这是一个问题,因为在解析器能够识别
    构造函数\u decl
    之前,它需要减少一个(空的)
    构造函数\u declmore
    。但它显然无法做到这一点,除非它知道
    var_declmore
    已经完成

    因此,当它看到一个
    ID
    时,它必须在以下两种操作中选择一种:

  • 减少一个空的
    constructor\u declmore
    ,从而决定不再有
    var\u decl
    s;或

  • 移动
    ID
    ,以开始解析新的
    var\u decl

  • 在没有优先声明的情况下(这在这里没有帮助),bison/yacc总是解决移位/减少冲突,以支持移位操作。因此,在本例中,它假设
    Foo
    是启动
    var_decl
    ID
    ,导致您注意到的错误消息


    还应注意语法产生的reduce/reduce冲突。它来自
    method\u declmore:method\u decl
    规则,它与创建
    method\u declmore
    的另一种可能方式相冲突,即从一个空的
    method\u declmore
    开始,然后添加一个
    method\u decl

    ,我从该文件中得到大量警告。包括两班制,减少冲突;一是减少冲突;还有关于无用规则的警告。顺便说一句,如果你省略了动作,阅读语法会容易得多;你会看到很多警告,因为诸如表达式、名称和new_表达式之类的规则还没有被使用。它们在语句规则中使用,该规则尚未实现,因为我想找出该规则的问题(vardecl和构造函数冲突)。如果只使用适用的规则创建一个语句,您会发现这要容易得多。我从该文件中得到了大量警告。包括两班制,减少冲突;一是减少冲突;还有关于无用规则的警告。顺便说一句,如果你省略了动作,阅读语法会容易得多;你会看到很多警告,因为诸如表达式、名称和new_表达式之类的规则还没有被使用。它们在语句规则中使用,该规则尚未实现,因为我想找出该规则的问题(vardecl和构造函数冲突)。如果您只使用适用的规则创建一个语句,您会发现这要容易得多。没错。但是,当我更改classBody的规则时,现在它尝试匹配构造函数的decl规则,尽管我给出了变量声明。检查编辑。@alwaysone:回答问题后,请不要更改。若你们有一个新问题,单独问它。它并没有解决我关于类主体定义的问题,所以这个问题并没有得到完全的回答。我不会彻底改变它,因为正确声明类主体的问题仍然存在。它回答了您的问题。它并没有解决你语法上的所有问题。无论如何,它解决了一个并不罕见的问题,因此它本可以帮助其他人,但问题不再显示问题,对未来的访问者来说毫无用处。可能有人有相同的规则(语法),但想象一下,如果有人检查了这个答案,但它并没有完全得到回答,因为其中一条规则的问题仍然存在。因此,我改变问题并不重要,因为在这两种情况下它都不起作用,因为它仍然不起作用。你在一个方向上帮了很多忙,而且只在一个更大问题的一个子问题上帮了忙,我至少问了一个方向。简言之,你帮助了一件事,然而,主要问题仍然存在。这是真的。但是,当我更改classBody的规则时,现在它尝试匹配构造函数的decl规则,尽管我给出了变量声明。检查编辑。@alwaysone:回答问题后,请不要更改。如果你
    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
      ;