GTK+ Forums

Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
It is currently Sat Sep 20, 2014 5:56 am

All times are UTC




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: populate a hashtable from input from flex+bison
PostPosted: Fri Mar 29, 2013 10:04 pm 
Offline
GTK+ Guru

Joined: Sun Jul 08, 2012 3:14 pm
Posts: 107
Location: Coventry, UK
I want to parse a bibtex file using flex and bison, and will display
those data using gtk library(in C). The lexer is
Code:
%{
#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); }
%%

and the parser is:

Code:
%{
#include <stdio.h>
#include <glib.h>
#include <gtk/gtk.h>
#include <string.h>
#include <glib/gstdio.h>
#include <fcntl.h>
enum
{
  COL_BIB_KEY=0,
  COL_BIB_TYPE, COL_BIB_AUTHOR, COL_BIB_YEAR,
  NUM_COLS} ;
#define slen 1024
GHashTable* table;
GtkTreeIter siter;
GtkListStore *store;
%}

// 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, g_strdup("TYPE"), g_strdup($2));
                  g_hash_table_insert(table, g_strdup("ID"), g_strdup($4));
          g_printf("%s:%s\n","KEY=>",g_hash_table_lookup(table,"TYPE"));
//                  g_printf("%s: %s\n", $2, $4);
              }
     KeyVals '}'
     ;
KeyVals:
       /* empty */
       | KeyVals KeyVal ; /* zero or more keyvals */
KeyVal:
      KEY '=' VALUE ',' { g_hash_table_insert(table, g_strdup($1), g_strdup($3));
//                          g_printf("%s: %s\n", $1, $3);
              };

%%

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

int main(int argc, char** argv) {
gtk_init(&argc, &argv);
GtkWidget  *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);   
  GtkWidget *tree=gtk_tree_view_new();
  setup_tree(tree);

gtk_container_add (GTK_CONTAINER (window), tree);
store= gtk_list_store_new (NUM_COLS,
      G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
  table = g_hash_table_new(g_str_hash, g_str_equal);
gint i;
do{
   g_hash_table_remove_all (table);
   yyparse();
   parse_entry (table);
gtk_tree_view_set_model (GTK_TREE_VIEW (tree), GTK_TREE_MODEL (store));
g_object_unref (store);
  }
  while(!EOF);
  g_hash_table_destroy (table);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
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);
//    g_printf("%s:%s\n",keys[i],g_hash_table_lookup(table,keys[i]));
    g_printf("%d=>%s:%s\n",i,keys[i],vals[i]);
    break;
      }
    }
  }
    gtk_list_store_append (store, &siter);
    gtk_list_store_set (store, &siter,
      COL_BIB_TYPE,         vals[COL_BIB_TYPE],
      COL_BIB_KEY,      vals[COL_BIB_KEY],
      COL_BIB_AUTHOR,       vals[COL_BIB_AUTHOR],
      COL_BIB_YEAR,         vals[COL_BIB_YEAR],
      -1);
}

void setup_tree(GtkWidget *tree){
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;

renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes
("Type", renderer, "text",COL_BIB_TYPE , NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes
("Author", renderer, "text", COL_BIB_AUTHOR, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes
("Year", renderer, "text",COL_BIB_YEAR, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
g_printf("HIIIIIIIIIi");
}


The problem is on populating the hash table, and not the listview(I
enclosed the list store so that people can see my final goal and suggest
improvements.)
If we put the line

Code:
g_printf("%s:%s\n",$1,g_hash_table_lookup(table,$1));


at line number 50, it prints the hash table's content correctly, but if
we want the content by uncommenting line number 105, then only the last
entry is parsed. So, my guess is I am not processing the hash file
correctly (line no 97-107 may be?)

The makefile is:

Code:
CC=gcc -g
FLEX=flex
BISON=bison
LIBS=lfl
PROG=parse

${PROG}:bib.y bib.l
    ${BISON} -d bib.y
    ${FLEX} -i bib.l
    ${CC} lex.yy.c bib.tab.c `pkg-config --cflags --libs glib-2.0``pkg-config --cflags --libs gtk+-3.0` -${LIBS} -o $@

clean:
    rm -f lex.yy.c bib.tab.c ${PROG}
    touch bib.l bib.y


and a sample bibtex file is:

Code:
@Book{a1,
    Title="ASR",
    Publisher="oxf",
    author = "a {\"m}ook, Rudra Banerjee",
    Year="2010",
    Address="UK",
    Edition="1",
}
@Booklet{ab19,
    Author="Rudra Banerjee and A. Mookerjee",
    Title="Fe{\"Ni}Mo",
    Editor="sm1",
    Title="sm2",
    Publisher="sm3",
    Volume="sm4",
    Number="sm5",
    Pages="sm6",
    Month="sm8",
    Note="sm9",
    Key="sm10",
    Year="1980",
    Address="osm1",
    Edition="osm2",
}


I will be grateful if someone shows me some way to populate the
hashtable correctly. Please help.


Top
 Profile  
 
 Post subject: Re: populate a hashtable from input from flex+bison
PostPosted: Mon Apr 01, 2013 1:34 pm 
Offline
GTK+ Guru

Joined: Sun Jul 08, 2012 3:14 pm
Posts: 107
Location: Coventry, UK
No guru's around? or its too silly question to ask?


Top
 Profile  
 
 Post subject: Re: populate a hashtable from input from flex+bison
PostPosted: Wed Apr 03, 2013 7:59 am 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 745
Location: UK
Hi,

I am not sure that you understand what a Hash Table is.

A Hash Table is a key - value storage system using a lookup table to speed up the search for the "key" and the "value" based on the value of the "key". Therefore you can only have unique keys.

If I have a key called "Author" and a value "Bill" and store that in the Hash Table then I would have in the Hash Table

"Author" - "Bill"

Now if I take the key "Author" and a value "Bryson" and store that in the Hash Table the old value would be replaced as we can only have unique keys with one value. So the result for the Hash Table would be

"Author" - "Bryson"


This is basically what you are doing in your code.

Also because you are allocating memory for your strings before storing them in the Hash Table and never freeing the allocated memory when they get replaced there are many places where memory is leaking from.

As I am not sure what your intended purpose is for storing additional data it is not possible to proceed further at this point.

_________________
E.


Top
 Profile  
 
 Post subject: Re: populate a hashtable from input from flex+bison
PostPosted: Wed Apr 03, 2013 1:23 pm 
Offline
GTK+ Guru

Joined: Sun Jul 08, 2012 3:14 pm
Posts: 107
Location: Coventry, UK
Hello Errol,
Thanks for your reply.
Let me explain the code again:
If I have the main function as:

Code:
int main (int    argc,
      char **argv)
{
      yyparse ();
}


It prints the results correctly.

Now, I want to view them in list view, that is my final goal. So, I was using hash-table as a intermediate storage
(I can't do a list_store_set directly as it complains about wrong column number without -1 as the last argument).
Yes, I realized I am overwriting the hash-table everytime; but my goal was to
1. create a hash table for one set of data ->2. store the hash-table in a list-store->3. remove and create a new has table for the next set.
But this plan seems not working.
I also tried to use a struct, populate the struct and push the struct to the list store, but cant do this, as it may not have all the keys (elements of keys[] for each set).


Top
 Profile  
 
 Post subject: Re: populate a hashtable from input from flex+bison
PostPosted: Sun Apr 07, 2013 4:23 pm 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 745
Location: UK
With how you have the lexer and parser set up it will parse the whole bibtex file storing what it finds in the hash table. Since a hash table is just a key, value data storage system any repeated keys will get over written.

To correct your problem will require modification of you parser and how it processes data. This is not really within the scope of GTK/Glib.

PM if you want further help.

_________________
E.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC


Who is online

Users browsing this forum: Google [Bot] and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group