在上一篇文章中,笔者介绍了Linux/UNIXC语言库Melon的基本功能和框架使用。本文将介绍Melon中的词法分析器组件。Melon的Github仓库为:https://github.com/Water-Melo...Melon中的词法分析器不依赖于自身的框架,因此无需初始化框架即可使用。基础使用我们先来看一个基础示例://lexer.c#include#include"mln_lex.h"MLN_DEFINE_TOKEN_TYPE_AND_STRUCT(static,mln_test,TEST);MLN_DEFINE_TOKEN(mln_test,TEST);intmain(intargc,char*argv[]){if(argc!=2){fprintf(stderr,"Usage:%sfile_path\n",argv[0]);返回-1;}mln_string_t路径;mln_lex_t*lex=NULL;结构mln_lex_attrlattr;mln_test_struct_t*ts;mln_string_nSet(&path,argv[1],strlen(argv[1]));lattr.pool=mln_alloc_init();if(lattr.pool==NULL){fprintf(stderr,"初始化内存池失败\n");返回-1;}lattr.keywords=NULL;lattr.hooks=NULL;lattr.preprocess=0;lattr.padding=0;lattr.type=M_INPUT_T_FILE;lattr.data=&path;mln_lex_initWithHooks(mln_test,lex,&lattr);if(lex==NULL){fprintf(stderr,"lexerinitfailed\n");返回-1;}while(1){ts=mln_test_token(lex);如果(ts==N乌尔||ts->type==TEST_TK_EOF)中断;写入(STDOUT_FILENO,ts->text->data,ts->text->len);printf("line:%utype:%d\n",ts->line,ts->type);}mln_lex_destroy(lex);mln_alloc_destroy(lattr.pool);return0;}这样就可以完成一个词法分析器程序,读取程序参数指定的文件内容,然后解析成语素打印出来。我们执行:$./lexerlexer.c/line:1type:21/line:1type:21lexerline:1type:5。行:1类型:20c行:1类型:5#行:3类型:9include行:3类型:5<行:3类型:24stdio行:3类型:5。line:3type:20hline:3type:5>line:3type:26...如您所见,该程序将我们的示例C程序反汇编为各种词素,例如:/、#、<等。进阶使用上面的例子,我们可以看出,基本词法分析器解析出的语素分得太细了。有时我们也希望解析器支持我们自定义的关键字,自定义格式的数据,甚至一些预处理功能,比如从其他文件导入内容解析词位。然后,我们将修改上面的例子:NULL)};MLN_DEFINE_TOKEN_TYPE_AND_STRUCT(static,mln_test,TEST,TEST_TK_ON,TEST_TK_OFF,TEST_TK_STRING);MLN_DEFINE_TOKEN(mln_test,TEST,{TEST_TK_ON,"TEST_TK_ON"},{TEST_TK_OFF,"TEST_TK_OFF"},"T_STK_TREST};静态内联intmln_get_char(mln_lex_t*lex,charc){if(c=='\\'){charn;如果((n=mln_lex_getAChar(lex))==MLN_ERR)返回-1;switch(n){case'\"':if(mln_lex_putAChar(lex,n)==MLN_ERR)return-1;break;case'\'':if(mln_lex_putAChar(lex,n)==MLN_ERR)return-1;break;case'n':if(mln_lex_putAChar(lex,'\n')==MLN_ERR)return-1;break;case't':if(mln_lex_putAChar(lex,'\t')==MLN_ERR)返回-1;休息;case'b':if(mln_lex_putAChar(lex,'\b')==MLN_ERR)返回-1;休息;case'a':if(mln_lex_putAChar(lex,'\a')==MLN_ERR)返回-1;休息;case'f':if(mln_lex_putAChar(lex,'\f')==MLN_ERR)返回-1;休息;case'r':if(mln_lex_putAChar(lex,'\r')==MLN_ERR)返回-1;休息;case'v':if(mln_lex_putAChar(lex,'\v')==MLN_ERR)返回-1;休息;case'\\':if(mln_lex_putAChar(lex,'\\')==MLN_ERR)return-1;休息;默认值:mln_lex_setError(lex,MLN_LEX_EINVCHAR);返回-1;}}else{if(mln_lex_putAChar(lex,c)==MLN_ERR)返回-1;}return0;}staticmln_test_struct_t*mln_test_dblq_handler(mln_lex_t*lex,void*data){mln_lex_cleanResult(lex);字符c;while(1){c=mln_lex_getAChar(lex);如果(c==MLN_ERR)返回NULL;如果(c==MLN_EOF){mln_lex_setError(lex,MLN_LEX_EINVEOF);返回空值;}if(c=='\"')break;if(mln_get_char(lex,c)<0)returnNULL;}returnmln_test_new(lex,TEST_TK_STRING);}intmain(intargc,char*argv[]){if(argc!=2){fprintf(stderr,"Usage:%sfile_path\n",argv[0]);return-1;}mln_string_t路径;mln_lex_t*lex=NULL;structmln_lex_attrlattr;mln_test_struct_t*ts;mln_lex_hooks_t挂钩;memset(&hooks,0,sizeof(hooks));hooks.dblq_handler=(lex_hook)mln_test_dblq_handler;mln_string_nSet(&path,argv[1],strlen(argv[1]));lattr.pool=mln_alloc_init();if(lattr.pool==NULL){fprintf(stderr,"initpoolfailed\n");return-1;}lattr.keywords=关键词;lattr.hooks=&hooks;lattr.preprocess=1;//支持预处理lattr.padding=0;lattr.type=M_INPUT_T_FILE;lattr.data=&path;mln_lex_initWithHooks(mln_test,lex,&lattr);if(lex==NULL){fprintf(stderr,"lexerinitfailed\n");返回-1;}while(1){ts=mln_test_token(lex);如果(ts==NULL||ts->type==TEST_TK_EOF)中断;写入(STDOUT_FILENO,ts->text->data,ts->text->len);printf("line:%utype:%d\n",ts->line,ts->type);}mln_lex_destroy(lex);mln_alloc_destroy(lattr.pool);return0;}这次我们增加了以下功能:支持关键字on和off,支持将双引号括起来的内容识别为字符串类型增加预处理功能,比如引入其他文件内容生成可执行程序:$cc-oaa.c-I/usr/local/melon/include/-L/usr/local/melon/lib/-lmelon-lpthread创建两个A测试文件:a.ini#include"b.ini"test_mode=onlog_level='debug'proc_num=10b.iniconf_name="b.ini"运行我们的程序看看效果:$./lexera.iniconf_nameline:1type:5=line:1type:25b.iniline:1type:42test_modeline:2type:5=line:2type:25online:2type:40log_levelline:3type:5=line:3type:25'line:3type:13debugline:3type:5'line:3type:13proc_numline:4type:5=line:4type:2510line:4type:2可以看到,写在a.ini中的includepart是解析b.ini文件内容后的语素,on和off都正常解析。并且字符串也正常处理。Melon的Github仓库是:https://github.com/Water-Melo...感谢阅读