其实一直都不了解词法分析和语法分析是干什么的,很偶然的机会,接触到了词法分析和语法分析这个东东。在项目中因为要完成字符串中很多同名的变量到相应值的替换,本来要实现的功能也不是很复杂,但是有人提议说可以用词法分析这个工具来做替换,所以偶就开始调查了。
刚开始也不知道FLEX和BISON到底能干什么,他们之间是什么关系。与我要用它来完成的功能如何实现,其实都不知道。然后上网找找资料,发现BISON MANUAL讲得比较详细。所以就认真的看了,看完后算是有了点基础,知道BISON干什么了,也知道它是如何去做的。
在BISON MANUAL中,关于语法分析器算法(shift/reduce 移进/规约)的了解比较重要,还有就是语法规则的左递归,右递归和相互递归。最后无论如何都要理解分析器,知道分析器的各个状态。状态机在没办法搞清楚GRAMMER RULE如何工作的时候,能够提供非常好的跟踪方式。
下面就从一个修改的例子开始。
地址在:http://www.ibm.com/developerworks/cn/linux/l-flexbison.html
名称:使用 Flex 和 Bison 更好地进行错误处理
1)如何解决输入问题
一个是修改yylex这个函数,默认的yyin是stdin,所以修改了这个函数后就可以让你的输入来自file,也可以来自stdin.
另外一个就是修改YY_INPUT这个MACRO,让你决定buf的内容从哪儿读出.此处是要匹配"policer todo{CT_MEDIA_NUM}"这个字符串中的{CT_MEDIA_NUM}.而且要替换成另外的值.
#undef YY_INPUT
#define YY_INPUT(buf,result,max_size) {\
result = GetNextChar(buf, max_size); \
if ( result <= 0 ) \
result = YY_NULL; \
}
static char tmpbuf[256]="\"policer todo{CT_MEDIA_NUM}\"";
extern
int GetNextChar(char *b, int maxBuffer) {
int frc;
static int cntDummy=0;
if(cntDummy>0)return 0;
strcpy( b, tmpbuf);
cntDummy++;
frc =strlen(b);
printf("out:%s\n",b);
return frc;
}
2)如何解决语法规则
追加一个类型mytype,因为作为一个组被使用的时候,必须是数值类型.
%type
mytype
然后declare 3个token ,分别是{,}和".
%token LCYC
%token RCYC
%token IN
program
: statement SEMICOLON program
| IN mytype IN
| text
;
mytype
: LCYC mytype RCYC
{
$$=$2;
printf("haha,get out:%d\n",$$);
}
| VALUE { $$=$1; printf("VALUE:%d\n",$$); }
| IDENTIFIER { $$=GetCmdVal($1); }
| program mytype ####-####-####--使用了相互递归,解决问题.
;
text:/*empty string match*/
|IDENTIFIER
;
上面的IDENTIFIER ,VALUE 是终止型,而mytype是非终止型.
一个终结符(terminal symbol)(也被称做符号类型(token type)代表了一类从构造上等价的记号.
一个非终结符(noterminal symbol)代表一类从构造上等价的组.
3)如何产生词法分析规则
当在字符中出现如下字符时,返回相应的token.
[0-9]+ {
/* 0-9 number of several */
printf("digital find:%s\n",yytext);
yylval.value = strtol(yytext,NULL,10);
printf("yylval.value =%d\n", yylval.value );
return VALUE;
}
[_a-zA-Z][_a-zA-Z0-9]* {
/*Act_09 number and alpha*/
printf("text find:%s\n",yytext);
yylval.string = malloc(strlen(yytext)+1);
strcpy(yylval.string, yytext);
return IDENTIFIER;
}
"{" {printf("find:%s\n",yytext); return LCYC; }
"}" {printf("find:%s\n",yytext); return RCYC; }
"\"" {printf("find:%s\n",yytext); return IN; }
4)辅助处理的函数和结构
定义一个结构体
typedef struct _CMD_TYPE {
char name[256];
int value;
} CmdType;
声明变量
static CmdType cmdType[2]={{"CT_MEDIA_NUM",4},
{"CB_SR",102}
};
调用函数返回替换的VALUE.
extern
int GetCmdVal( char *varname ){
int i=0;
for(i = 0 ;i< 2;i++)
{
if( 0 == strcmp(varname,cmdType[i].name) )
return cmdType[i].value ;
}
return -1;
}
5)查看输出结果
输出结果默认是stdout,可以修改yyout,让它输出到file.
本实例的输出将变成: policer todo4
附件是修改过的工程文件
|
文件: | ccalc-m.rar |
大小: | 28KB |
下载: | 下载 |
|
阅读(2862) | 评论(0) | 转发(0) |