1

ここ数週間、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".
.....

誰かが親切にこれについて私を助けてくれれば、私は感謝するでしょう。

4

1 に答える 1

2

多くの問題。まず、レクサーが混乱し、引用符で囲まれた文字列とブレースされたものを単一として認識しようとしているだけでなく、やVALUEのような単一の文字を認識しようとしています。引用符の場合、レクサーに文字列全体を認識させることは理にかなっていますが、解析する構造的なもの(ブレースリストなど)の場合、パーサーが解析する単一のトークンを返す必要があります。次に、文字列にスペースを割り当てる場合、NULターミネータにスペースを割り当てていません。最後に、文法が奇妙に見え、Bibtexファイルの何にも対応しないKeyValueのような解析が必要です。"{= VALUE = VALUE

まず、レクサーについてです。引用符で囲まれた文字列と識別子を認識したいが、他のものは単一文字でなければならない:

[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 ',' ;

それはあなたが与える例を解析するはずです。

于 2013-03-09T02:06:19.893 に答える