【问题标题】:Problems with parsing decaf (variable declaration versus constructor)解析 decaf 的问题(变量声明与构造函数)
【发布时间】:2017-11-03 02:19:29
【问题描述】:

我正在使用 bison (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 文件的gist

【问题讨论】:

  • 我从该文件中收到了大量警告。包括两个班次减少冲突;一个reduce-reduce冲突;以及关于无用规则的警告。顺便说一句,如果你省略了动作,阅读语法会容易得多;见minimal reproducible example
  • 您会收到很多警告,因为还没有使用 expressionnamenew_expression 等规则。它们用于 statement 规则中,该规则尚未实现,因为我想弄清楚该规则的问题(vardecl 和构造函数冲突)。
  • 如果您创建一个仅包含适用规则的minimal reproducible example,您会发现这会容易得多。

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


【解决方案1】:

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

这是一个问题,因为在解析器能够识别constructor_decl 之前,它需要减少一个(空的)constructor_declmore。但除非它知道var_declmore 已完成,否则它显然无法进行这种缩减。

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

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

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

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

语法产生的reduce/reduce冲突也应该看看。它来自method_declmore: method_decl 规则,该规则与创建method_declmore 的其他可能方式相冲突,该方式以空method_declmore 开头,然后添加method_decl

【讨论】:

  • 确实如此。但是,当我更改了 classBody 的规则时,现在它尝试匹配 constructor_decl 规则,尽管我给出了变量声明。检查编辑。
  • @alwaysone:请不要在回答后更改问题。如果您有新问题,请单独提出。
  • 它没有解决我的 classBody 定义问题,因此问题没有得到完全回答。我没有彻底改变它,因为正确声明 classBody 的问题仍然存在。
  • 它回答了您的问题按要求。它并没有解决您的语法问题。无论如何,它解决了一个并不少见的问题,因此它本可以帮助其他人,只是问题不再显示问题,使其对未来的访问者毫无用处。
  • 有人可能有相同的规则集(语法),但想象一下,如果有人检查了这个答案并且它没有完全回答,因为其中一个规则的问题仍然存在。因此,我改变问题并不重要,因为在这两种情况下它都不起作用,因为它仍然不起作用。你在一个方向上帮助了很多,并且只帮助了一个更大问题的子问题,我至少问了一个方向。简而言之,你帮助了一件事,然而,主要问题仍然存在。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-14
  • 2011-10-29
  • 2020-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-15
相关资源
最近更新 更多