背景
闲来无聊,抽空写篇博客对flex,bison这两个小工具进行介绍一下。工具本身的用途我不在此赘述。由于自己曾经做过配置文件的解析的工作,深知其中的艰辛与痛苦。flex,bion的出现,为自己解决这类问题打开了另外一扇门。当然,如果拿flex,bison来解析我用到的这些配置文件,有点小题大做了。所以,这个地方,我选择了解析json文本。选择解析json文本的原因是大家在平时做应用层工作时候肯定会用得到,而且,json文本本身的格式并不是太复杂。
本文在协作的过程中,最初参考了costaxu的这篇文章()。在此表示感谢。由于是作为探索性的尝试,并没有完全实现对json的解析,以及封装成为可供上层调用的库。但整个框架已经能够应用到实际的项目中。
分词
分词使用的是flex工具,其脚本如下:(文件名为json.fl)
%{
#include "stdio.h"
#include "json.tab.h"
int yywrap(void) //自定义此函数,是应用程序完全脱离对flex库的依赖
{
return 1; //返回默认值1
}
%}
VALUE_INT [-]?[1-9]+[0-9]*
VALUE_FLOAT [-]?[1-9]+[0-9]\.[0-9]+
VALUE_STRING [_a-zA-Z]+[_a-zA-Z0-9]+
IGNORE [ \t\r\n]
%%
\" return QUOTE;
\, return COMMA;
\[ return BRACE_LEFT;
\] return BRACE_RIGHT;
\{ return BRACEETS_LEFT;
\} return BRACEETS_RIGHT;
\: return COLON;
{VALUE_STRING} yylval = strdup(yytext); return VALUE_STRING;
{VALUE_FLOAT} return VALUE_FLOAT;
{VALUE_INT} return VALUE_INT;
{IGNORE}
%%
目前,只对三种数据类型,int,float,string类型作了处理,而且string的正则表达式也有待改进。
词法分析
词法分析使用的是bison工具,其内容如下(文件名为json.y)
%{
#include <stdio.h>
#include <string.h>
void yyerror(const char* s)
{
printf("ERROR:%s\n",s);
}
int main()
{
FILE * infp = NULL;
infp = fopen("config.file","r");
yyrestart(infp);
yyparse();
fclose(infp);
return 0;
}
%}
%token QUOTE COMMA BRACE_LEFT BRACE_RIGHT BRACEETS_LEFT BRACEETS_RIGHT COLON VALUE_STRING VALUE_FLOAT VALUE_INT
%%
root:
|
BRACEETS_LEFT items BRACEETS_RIGHT
;
items:
|
items COMMA item
|
item
;
item:
item_int
|
item_float
|
item_string
|
item_item
;
item_int: QUOTE VALUE_STRING QUOTE COLON VALUE_INT
{
printf("Model item_int![Name:%s]\n",$2);
}
;
item_float: QUOTE VALUE_STRING QUOTE COLON VALUE_FLOAT
{
printf("Model item_float![Name:%s]\n",$2);
}
;
item_string: QUOTE VALUE_STRING QUOTE COLON QUOTE VALUE_STRING QUOTE
{
printf("Model item_string![Name:%s]\n",$2);
}
;
roots:
|
roots COMMA root
|
root
;
item_item: QUOTE VALUE_STRING QUOTE COLON BRACE_LEFT roots BRACE_RIGHT
{
printf("Model item_item![Name:%s]\n",$2);
}
;
备注,上面仅仅是对json文件进行语法分析,再此仅将json对的名字进行简单的打印。
后记
依次使用如下命令即可完成对项目的编译工作。
flex json.fl
bison -d json.y
gcc -o lex.exe json.tab.c lex.yy.c
{
"people": [
{ "firstName": "Brett", "lastName":"McLaughlin", "email": "aaaa" },
{ "firstName": "Jason", "lastName":"Hunter", "email": "bbbb"},
{ "firstName": "Elliotte", "lastName":"Harold", "email": "cccc" }
]
}
然后,即可对此json文档进行解析。