过去几周,我正在尝试使用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",
Add="UK",
Edition="1",
}
当我尝试解析它时,它给出了语法错误。使用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".
.....
如果有人帮助我,我将不胜感激。
答案 0 :(得分:2)
很多问题。首先,您的词法分析器很困惑,尝试将引用的字符串和支撑的内容识别为单个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 ',' ;
那应该解析你给出的例子。