【问题标题】:flex+bison output in a glib's hash containerglib 的哈希容器中的 flex+bison 输出
【发布时间】:2013-03-15 17:40:01
【问题描述】:

我在解析 bib 文件方面取得了相当大的进展,但就我目前的理解水平而言,下一步是相当困难的。 我已经创建了 bison 和 flex 代码,可以正确解析上面的 bib 文件:

%{
#include <stdio.h>
%}

// Symbols.
%union
{
    char    *sval;
};
%token <sval> VALUE
%token <sval> KEY
%token OBRACE
%token EBRACE
%token QUOTE
%token SEMICOLON 

%start Input
%%
Input: 
     /* empty */ 
     | Input Entry ;  /* input is zero or more entires */
Entry: 
     '@' KEY '{' KEY ','{ printf("===========\n%s : %s\n",$2, $4); } 
     KeyVals '}' 
     ;
KeyVals: 
       /* empty */ 
       | KeyVals KeyVal ; /* zero or more keyvals */
KeyVal: 
      KEY '=' VALUE ',' { printf("%s : %s\n",$1, $3); };

%%

int yyerror(char *s) {
  printf("yyerror : %s\n",s);
}

int main(void) {
  yyparse();
}

%{
#include "bib.tab.h"
%}

%%
[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); }
%%

我想将这些值放在一个容器中。在过去的几天里,我阅读了大量的 glib 文档,并提出了最适合我的情况的哈希容器。 下面是一个基本的哈希码,一旦将值放入数组键和 vals 中,它就有正确的哈希值。

#include <glib.h>
#define slen 1024

int main(gint argc, gchar** argv) 
{
  char *keys[] = {"id", "type", "author", "year",NULL};
  char *vals[] = {"one",  "Book",  "RB", "2013", NULL};
  gint i;
  GHashTable* table = g_hash_table_new(g_str_hash, g_str_equal);
  GHashTableIter iter;
  g_hash_table_iter_init (&iter, table);
  for (i= 0; i<=3; i++)
  {
    g_hash_table_insert(table, keys[i],vals[i]);
    g_printf("%d=>%s:%s\n",i,keys[i],g_hash_table_lookup(table,keys[i]));
  }
}

问题是,我如何整合这两个代码,即在 C 代码中使用解析后的数据。 感谢您提供任何帮助。

编辑:解释@UncleO 的回应: @叔叔,

感谢您的评论。我不知道如何更好地解释它。这是一个尝试。 我的代码(野牛)的最近状态是:

%{
#include <stdio.h>
#include <glib.h>
%}

// Symbols.
%union
{
    char    *sval;
};
%token <sval> VALUE
%token <sval> KEY
%token OBRACE
%token EBRACE
%token QUOTE
%token SEMICOLON 

%start Input
%%
Input: 
     /* empty */ 
     | Input Entry ;  /* input is zero or more entires */
Entry: 
     '@' KEY '{' KEY ','{ printf("===========\n%s : %s\n",$2, $4); } 
     KeyVals '}' 
     ;
KeyVals: 
       /* empty */ 
       | KeyVals KeyVal ; /* zero or more keyvals */
KeyVal: 
      KEY '=' VALUE ',' { printf("%s : %s\n",$1, $3); };

%%

int yyerror(char *s) {
  printf("yyerror : %s\n",s);
}

int main(void) {
 GHashTable* table = g_hash_table_new(g_str_hash, g_str_equal);
  char *keys[] = {"id", "type", "author", "year",NULL};
  char *vals[] = {"one",  "Book",  "RB", "2013", NULL};
  gint i;
  yyparse();
  GHashTableIter iter;
  g_hash_table_iter_init (&iter, table);
  for (i= 0; i<=3; i++)
  {
    g_hash_table_insert(table, keys[i],vals[i]);
    g_printf("%d=>%s:%s\n",i,keys[i],g_hash_table_lookup(table,keys[i]));
  }
}

lex 文件不变。数组键和值的元素用于测试目的。 输入文件的示例是

@Booklet{ab19,
    Author="Rudra Banerjee and A. Mookerjee",
    Editor="sm1",
    Title="sm2",
    Publisher="sm3",
    Volume="sm4",
    Issue="sm5",
    Page="sm6",
    Month="sm8",
    Note="sm9",
    Key="sm10",
    Year="1980",
    Add="osm1",
    Edition="osm2",
}

因此,在解析时,代码会正确解析值。我想使用解析输入中的这些值插入哈希表中,每个输入都不同。 所以,我的最终目标是从代码中删除数组键和值;和线

g_hash_table_insert(table, keys[i],vals[i]);

应该被替换为:

g_hash_table_insert(table, <$1 from bison>,<$3 from bison>);

这有意义吗?

编辑:======================================

@Uncle0:这里是更新的代码;可能我的意图很明确。我正在努力解决这个问题,但是虽然从野牛行打印按预期打印内容,但从哈希表(代码的最后一行)打印时并非如此

%{
#include <stdio.h>
#include <glib.h>
#define slen 1024
GHashTable* table;
%}

// Symbols.
%union
{
    char    *sval;
};
%token <sval> VALUE
%token <sval> KEY
%token OBRACE
%token EBRACE
%token QUOTE
%token SEMICOLON 

%start Input
%%
Input: 
     /* empty */ 
     | Input Entry ;  /* input is zero or more entires */
Entry: 
     '@' KEY '{' KEY ','{ g_hash_table_insert(table, "TYPE", $2);
                  g_hash_table_insert(table, "ID", $4);
              g_printf("%s: %s\n", $2, $4);
              } 
     KeyVals '}' 
     ;
KeyVals: 
       /* empty */ 
       | KeyVals KeyVal ; /* zero or more keyvals */
KeyVal: 
      KEY '=' VALUE ',' { g_hash_table_insert(table, $1, $3);
                          g_printf("%s: %s\n", $1, $3); };

%%

int yyerror(char *s) {
  printf("yyerror : %s\n",s);
}

int main(void) {
  table = g_hash_table_new(g_str_hash, g_str_equal);
gint i;
do{
   g_hash_table_remove_all (table);
   yyparse();
   parse_entry (table);
//  g_printf("%s:%s\n","Author=>",g_hash_table_lookup(table,"Author"));
//  g_printf("%s:%s\n","KEY=>",g_hash_table_lookup(table,"KEY"));
  }
  while(!EOF);
}
void parse_entry (GHashTable *table)
{
  GHashTableIter iter;
  gchar *key, *val;
  char *keys[] = {"id", "type", "author", "year", "title", "publisher", "editor", 
    "volume", "number", "pages", "month", "note", "address", "edition", "journal",
    "series", "book", "chapter", "organization", NULL};
  char *vals[] = {NULL,  NULL,  NULL, NULL, NULL,
    NULL,  NULL,  NULL, NULL, NULL,
    NULL,  NULL,  NULL, NULL, NULL,
    NULL,    NULL,  NULL, NULL, NULL};

  gchar **kiter;
  gint i;
  g_hash_table_iter_init (&iter, table);
  while (g_hash_table_iter_next (&iter, (void **)&key, (void **)&val))
  {
    for (kiter = keys, i = 0; *kiter; kiter++, i++)
    {
      if (!g_ascii_strcasecmp(*kiter, key))
      {
    vals[i] = g_strndup(val,slen);
    break;
      }
    g_printf("%d=>%s:%s\n",i,keys[i],vals[i]);
    }
  }
}

【问题讨论】:

    标签: c hashtable bison glib flex-lexer


    【解决方案1】:

    您还不清楚您想对输入做什么,但这里有一个解释让您开始。

    flex 将获取您的正则表达式文件并生成一个名为 yylex() 的函数。

    bison 将获取您的语法文件并生成一个名为 yyparse() 的函数,该函数重复使用 yylex() 函数来标记字符串。 main() 函数只会调用 yyparse() 一次,每次 yyparse() 函数匹配语法中的某个规则时,都会执行你指定的代码片段。现在,您只是打印值,但您可以执行其他操作,例如插入哈希表或任何您想要的操作。

    grammar.y 文件包含 yyparse() 定义之前的代码和之后的代码部分。如果您愿意,可以将 main() 函数放在此文件的末尾,但最好将其放在另一个文件中并链接两者。通常,main() 函数会执行诸如打开输入以进行读取等操作,然后调用 yyparse() 来执行大部分工作。 yyparse()返回后,main就可以清理了。

    编辑:嗨鲁德拉,

    我看到您想将 main() 保留在语法文件中。没关系。

    您现在需要做的就是更改 sn-ps 中的 printf 语句以插入到表中,table 变量必须在 main() 之外声明,以便 yyparse() 看到它。

    %{
    #include <stdio.h>
    #include <glib.h>
    
    GHashTable* table;
    
    %}
    
    // Symbols.
    %union
    {
        char    *sval;
    };
    %token <sval> VALUE
    %token <sval> KEY
    %token OBRACE
    %token EBRACE
    %token QUOTE
    %token SEMICOLON 
    
    %start Input
    %%
    Input: 
         /* empty */ 
         | Input Entry ;  /* input is zero or more entires */
    Entry: 
         '@' KEY '{' KEY ','{ printf("===========\n%s : %s\n",$2, $4); } 
         KeyVals '}' 
         ;
    KeyVals: 
           /* empty */ 
           | KeyVals KeyVal ; /* zero or more keyvals */
    KeyVal: 
          KEY '=' VALUE ',' { g_hash_table_insert(table, $1, $3); printf("%s : %s\n",$1, $3); };
    
    %%
    
    int yyerror(char *s) {
      printf("yyerror : %s\n",s);
    }
    
    int main(void) {
      table = g_hash_table_new(g_str_hash, g_str_equal);
    
      yyparse();
    }
    

    您确定不想对数据中的第一项进行任何处理吗?看来您没有将它们用于任何事情。

    【讨论】:

    • 感谢您的评论。我不知道如何更好地解释它。这是一个尝试。我的代码(野牛)的最近状态是:
    • 嗨@UncleO,感谢您的回复。是的,我也会以与第二学期相同的方式使用它们:g_hash_table_insert(table, "TYPE", $1) g_hash_table_insert(table, "ID", $3) 让我看看我能走多远,我会在这个线程中回来。再次感谢。
    猜你喜欢
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多