【发布时间】:2014-08-03 14:35:02
【问题描述】:
Bison 规则是否可以扩大而不是缩小,从而变成更多的标记?换一种方式问:是否可以在解析器输入中的下一个标记之前插入要解析的额外标记?
这是我可能想要的示例:
假设我想要一个能够理解三种标记类型的解析器。数字(为简单起见只是正整数 - INT)、单词(任意数量的字母、大写或小写 STRING)和某种其他符号(让我们无缘无故地使用感叹号 - EXC)
假设我有一个规则,减少一个单词,后跟一个数字,后跟一个感叹号。该规则产生一个整数类型,现在假设它只是将其输入加倍。该规则还允许自己成为它解析的整数。
我还有一个规则可以连续接受任意数量的这些(开始规则)。
Bison 解析器如下所示:(quicktest.y)
%{
#include <stdio.h>
%}
%union {
int INT_VAL;
}
%token STRING EXC
%token <INT_VAL> INT
%type <INT_VAL> somenumber
%%
start: somenumber {printf ("Result: %d\n", $1);}
| start somenumber {printf ("Result: %d\n", $2);}
;
somenumber: STRING INT EXC {$$ = $2 *2;}
| STRING somenumber EXC {$$ = $2 *2;}
;
%%
main(int argc, char ** argv){
yyparse();
}
yyerror(char* s){
fprintf(stderr, "%s\n", s);
}
可以使用弹性词法分析器生成标记,如下所示:(quicktest.l)
%{
#include "quicktest.tab.h"
%}
%%
[A-Za-z]+ {return STRING;}
[1-9]+ {yylval.INT_VAL = atoi(yytext); return INT;}
"!" {return EXC;}
. {}
这可以使用以下命令构建:
bison -d quicktest.y
flex quicktest.l
gcc -o quicktest quicktest.tab.c lex.yy.c -lfl -ggdb
我现在可以输入如下内容:
double double 2 ! !
并得到结果 8
现在,如果我希望用户能够避免在一行上有很多感叹号,就像这样:
a b c d e f 2 ! ! ! ! ! !
我希望能够允许他们输入如下内容:
a b c d e f 2 !*6
所以我可以为这样的标记添加一个 flex 表达式,它可以简单地提取所需的感叹号:
!\*[1-9]+ {
char *number = malloc(sizeof(char) * (strlen(yytext)-1));
strcpy(number, yytext+2);
yylval.INT_VAL = atoi(number);
free(number);
printf("Multiple exclamations: %d\n", yylval.INT_VAL);
return REPEAT_EXC;
}
但是我将如何实现野牛的一面呢?
我可以像这样添加令牌类型:
%token <INT_VAL> REPEAT_EXC
然后也许是某种规则?
repeat_exc: REPEAT_EXC {/*expand into n exclamation marks (EXC tokens)*/}
;
Bison 是否以任何方式支持这一点?
如果没有,我应该如何实现?
我是否应该让词法分析器在收到重复的 exc 表达式时返回 n 次 EXC 令牌? (如果可能的话,我宁愿避免这种情况,因为这需要 flex 代码记录某种状态,它可能处于重复感叹状态或正常状态。词法分析器就不那么容易维护了。)
【问题讨论】:
标签: parsing insert token bison