Bison 中的操作顺序

发布于 2024-11-26 11:48:01 字数 1948 浏览 0 评论 0原文

我正在尝试使用 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;

I'm trying to use Bison to generate a parser, in C++. The grammar is fine, but I'm having some quick trouble with the actions. Here's a simple sample:

statements
: statement
| statements statement;

As far as I know, this is a pretty normal thing to do. The question I have is which is derived first. For example, if I have an input which looks like

statement statement statement statement

does Bison call my actions as

statement (statement (statement (statement))))

or

(((statement) statement) statement) statement

I'm trying to construct a linked list of the rules invoked here, and I want to keep the list in the same order as was input. Right now, I've got

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

Edit: OK, so I could do something like this:

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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

人海汹涌 2024-12-03 11:48:01

它与左侧关联,即

(((statement) statement) statement) statement

您可以看出这是唯一的可能性,因为这可以简化为语句statement,这是您的产品之一。另一个选项

statement (statement (statement (statement))))

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

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

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

It associates to the left, i.e.

(((statement) statement) statement) statement

You can tell that this is the only possibility because this can be reduced to statements statement, which is one of your productions. The other option

statement (statement (statement (statement))))

would have to be reduced to statement statements, which is not one of your productions. However, you can use this if you want right-associativity instead.

Your code will not produce a linked list as-is, because after joining one statement with the other, you return a pointer to the first statement, so when the next statement comes around you're overwriting the Next pointer of the first statement.

Changing the order to right associative should solve this, but note that this will require linear parser stack space in the number of statements. If you expect many statements you should therefore consider building the linked list in reverse.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文