Bison 中的操作顺序
我正在尝试使用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
它与左侧关联,即
您可以看出这是唯一的可能性,因为这可以简化为
语句statement
,这是您的产品之一。另一个选项必须简化为
statement statements
,这不是您的作品之一。但是,如果您想要右关联性,则可以使用它。您的代码不会按原样生成链表,因为在将一个语句与另一个语句连接后,您将返回一个指向第一个语句的指针,因此当下一个语句出现时,您将覆盖 < code>Next 第一个语句的指针。
将顺序更改为右关联应该可以解决此问题,但请注意,这将需要语句数量的线性解析器堆栈空间。如果您期望有很多语句,那么您应该考虑反向构建链表。
It associates to the left, i.e.
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 optionwould 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.