【问题标题】:Actions order in BisonBison 中的操作顺序
【发布时间】:2011-07-26 20:20:09
【问题描述】:

我正在尝试使用 Bison 在 C++ 中生成解析器。语法很好,但我在操作上遇到了一些麻烦。这是一个简单的示例:

statements
: statement
| statements statement;

据我所知,这是一件很正常的事情。我的问题是哪个先派生。例如,如果我的输入看起来像

statement statement statement statement

Bison 是否将我的行为称为

statement (statement (statement (statement))))

(((statement) statement) statement) statement

我正在尝试构建此处调用的规则的链接列表,并且我希望保持列表与输入的顺序相同。现在,我有

statements
: statement
{ 
  $$ = $1; 
}
| statements statement
{ 
  dynamic_cast<ParsedFile::Statement*>($1)->Next = dynamic_cast<ParsedFile::Statement*>($2);
  $$ = $1;
};

编辑:好的,所以我可以这样做:

switch_statement
: SWITCH '(' expression ')'
{ 
  auto Switch = p.Make<ParsedFile::SwitchStatement>();
  Switch->Test = dynamic_cast<ParsedFile::Expression*>($3);
  p.NewScope();
  $$ = Switch;
}
'{' case_statements '}'
{
  auto Switch = dynamic_cast<ParsedFile::SwitchStatement*>($5);
  Switch->Cases = p.statements.top();
  p.PopScope();
  p.AddToCurrentScope(Switch);
};

default_statement
: DEFAULT ':' 
{
  auto Default = p.Make<ParsedFile::DefaultStatement>();
  p.NewScope();
  $$ = Default;
}
statements
{
  auto Default = dynamic_cast<ParsedFile::DefaultStatement*>($3);
  Default->Statements = p.statements.top();
  p.PopScope();
  p.AddToCurrentScope(Default);
};

case_statement
: CASE expression 
{
  auto case = p.Make<ParsedFile::CaseStatement>();
  p->Value = dynamic_cast<ParsedFile::Expression*>($2);
  p.NewScope();
  $$ = case;
}
DOUBLE_COLON statements
{
  auto Case = dynamic_cast<ParsedFile::CaseStatement*>($3);
  Case->Statements = p.statements.top();
  p.PopScope();
  p.AddToCurrentScope(Case); 
};

case_statements
: case_statement
| case_statements case_statement
| case_statements default_statement;

【问题讨论】:

  • @DeadMG:请注意,因为您将$2 附加到$1,然后“返回”$1$$,您将重置相同下一次推导后节点的Next 指针。如果您非常想要一个链表(为什么不是vectordeque?),您必须同时保留指向其头部和尾部的指针。
  • @larsmans:我没有使用向量或双端队列,因为我没有地方可以依赖它来存储它。堆栈中可能有多个statements(C 样式语法),并且 Bison 并没有真正提供保持复杂容器的功能。实际上,想想看,我从来没有想过它们会是一个实际的堆栈,所以我可以将它存储在我的用户提供的参数中,并使用中间规则参数来推送和弹出它。

标签: c++ bison lalr


【解决方案1】:

它关联到左边,即

(((statement) statement) statement) statement

您可以说这是唯一的可能性,因为这可以简化为statements statement,这是您的作品之一。另一种选择

statement (statement (statement (statement))))

必须简化为statement statements,这不是您的作品之一。但是,如果您想要右关联性,则可以使用它。

您的代码不会按原样生成链表,因为在将一个语句与另一个语句连接后,您会返回一个指向 first 语句的指针,因此当下一个语句出现时,您会覆盖第一条语句的Next指针。

将顺序更改为右关联应该可以解决此问题,但请注意,这将需要在语句数中使用线性解析器堆栈空间。如果您期望有很多语句,那么您应该考虑反向构建链表。

【讨论】:

  • 感谢您的意见。我编辑了我的 OP 以反映针对同一问题的不同策略 - 我很感激您的回复。如果没有,那么我将接受您的回答,因为它确实回答了原始问题。
  • @DeadMG:我倾向于避免在动作中编写有状态的代码,因为很难遵循事情的顺序。考虑以$$ = foo($1, $2) 的形式编写您的操作。顺序与您写的foo(foo(foo(bar(first), second), third), fourth) 相同。
  • 我需要那种用于范围的东西,以确定要使用的正确范围。以另一种方式做我认为是不可行的。然而,对于像表达式这样的无范围构造,它们将按功能构建而不是按状态构建。
猜你喜欢
  • 2016-02-15
  • 2015-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-07
相关资源
最近更新 更多