【发布时间】:2011-12-15 21:41:58
【问题描述】:
我正在尝试在 Yacc/Bison 中创建一个 LALR(1) 解析器,它可以接受具有灵活语法的命令。一个例子是通过调整室温(浮点数)、窗户位置(整数)和吊扇(枚举)来控制房子里的环境。示例(所需)语法是:
set kitchen 22.5, den 0 24.0, bathroom fast 25, kitchen slow
我被困在如何处理我在规则中称为“room_arg”的堆积数据。我可以在%union 语句中添加room_arg arg 类型,设置%type <arg> room_arg 并制定“room_arg”规则:
room_arg: TOK_CIELING_FAN { $$.fan = $1; }
| TOK_WINDOW { $$.window_position = $1; }
| TOK_THERMOSTAT { $$.temperature = $1; }
但是当涉及到将“room_arg”规则减少为“room_args”时 - 我必须弄清楚哪些堆栈项是哪些。除此之外,特定房间(示例中的“厨房”)的“room_cmd”不需要在命令中进行分组,这增加了我的挑战。
更改命令的格式会很不错,但是,可惜不可能。
有人可以提出一种实施策略,或者改进解析器逻辑以使事情变得更简单吗?
要批评的语法如下。
%{
typedef enum fan_setting_tag { OFF, SLOW, MEDIUM, FAST } fan_setting;
struct room_arg_tag {
int window_position;
fan_setting fan;
float temperature;
char * room_name;
} room_arg;
%}
%token TOK_ROOM
%token TOK_CIELING_FAN
%token TOK_WINDOW
%token TOK_THERMOSTAT
%token TOK_SET
%type <fan> TOK_CIELING_FAN
%type <window> TOK_WINDOW
%type <tempr> TOK_THERMOSTAT
%type <str> TOK_ROOM
%union {
int window;
float tempr;
fan_setting fan;
}
%%
command: /* empty */ | cmd command
cmd: TOK_SET room_cmds { execute_command( ... ); }
room_cmds: room_cmd
| room_cmd ',' room_cmds
room_cmd: TOK_ROOM room_args
room_args: room_arg
| room_arg room_args
room_arg: TOK_CIELING_FAN
| TOK_WINDOW
| TOK_THERMOSTAT
【问题讨论】: