在过去的几周里,我正在尝试使用flex和bison为bibtex(
http://www.bibtex.org/Format/)文件编写解析器.
$cat raw.l %{ #include "raw.tab.h" %} value [\"\{][a-zA-Z0-9 .\t\{\} \"\\]*[\"\}] %% [a-zA-Z]* return(KEY); \" return(QUOTE); \{ return(OBRACE); \} return(EBRACE); ; return(SEMICOLON); [ \t]+ /* ignore whitespace */; {value} { yylval.sval = malloc(strlen(yytext)); strncpy(yylval.sval,yytext,strlen(yytext)); return(VALUE); } $cat raw.y %{ #include <stdio.h> %} //Symbols. %union { char *sval; }; %token <sval> VALUE %token KEY %token OBRACE %token EBRACE %token QUOTE %token SEMICOLON %start Entry %% Entry: '@'KEY OBRACE VALUE ',' KeyVal EBRACE ; KeyVal: /* empty */ | KeyVal '=' VALUE ',' | KeyVal '=' VALUE ; %% int yyerror(char *s) { printf("yyerror : %s\n",s); } int main(void) { yyparse();
}
%%
样本bibtex是:
@Book{a1,author = "a {\"m}ook,Rudra Banerjee",Title="ASR",Publisher="oxf",Year="2010",Add="UK",Edition="1",} @Article{a2,Author="Rudra Banerjee",Title="Fe{\"Ni}Mo",Publisher={P{\"R}B},Issue="12",Page="36690",Year="2011",}
当我试图解析它时,它给出了语法错误.使用GDB,它显示它期望在KEY中声明字段(可能),
Reading symbols from /home/rudra/Programs/lex/Parsing/a.out...done. (gdb) Undefined command: "". Try "help". (gdb) Undefined command: "Author". Try "help". (gdb) Undefined command: "Editor". Try "help". (gdb) Undefined command: "Title". Try "help". .....
如果有人在这方面帮助我,我将不胜感激.
解决方法
很多问题.首先,你的词法分析器很困惑,试图将引用的字符串和支撑的东西识别为单个VALUE,并尝试识别单个字符,如“和{.对于引号,让词法分析器识别整个字符串是有意义的,但对于结构你要解析的东西(比如支撑列表),你需要返回单个标记以供解析器解析.其次,在为字符串分配空间时,你没有为NUL终结符分配空间.最后,你的语法看起来很像奇怪的是,想要解析诸如= VALUE = VALUE之类的东西作为KeyValue,它与bibtex文件中的任何东西都不对应.
首先,对于词法分析者.您想要识别引用的字符串和标识符,但其他内容应该是单个字符:
[A-Za-z][A-Za-z0-9]* { yylval.sval = strdup(yytext); return KEY; } \"([^"\]|\\.)*\" { yylval.sval = strdup(yytext); return VALUE; } [ \t\n] ; /* ignore whitespace */ [{}@=,] { return *yytext; } . { fprintf(stderr,"Unrecognized character %c in input\n",*yytext); }
现在您需要一个解析器来输入:
Input: /* empty */ | Input Entry ; /* input is zero or more entires */ Entry: '@' KEY '{' KEY ',' KeyVals '}' ; KeyVals: /* empty */ | KeyVals KeyVal ; /* zero or more keyvals */ KeyVal: KEY '=' VALUE ',' ;
这应该解析你给出的例子.