我在解析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文档,并提出了最适合我的情况的哈希容器。 下面是一个基本的哈希码,一旦将值放入数组键和值中,它就会正确地具有哈希值。
#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的回复: @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文件不变。数组键和val的元素用于测试目的。 输入文件的一个例子是
@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]);
}
}
}
答案 0 :(得分:1)
您还没清楚要对输入做什么,但这是一个让您入门的解释。
flex将获取正则表达式文件,并生成一个名为yylex()的函数。
bison将获取你的语法文件并生成一个名为yyparse()的函数,该函数重复使用yylex()函数来标记字符串。 main()函数只调用yyparse()一次,每次yyparse()函数匹配语法中的规则时,它都会执行你指定的代码片段。现在,您只是打印值,但您可以执行其他操作,例如插入哈希表或任何您想要的内容。
grammar.y文件包含在yyparse()定义和之后的代码之前的代码部分。如果你愿意,可以将main()函数放在这个文件的末尾,但最好把它放在另一个文件中,将它们放在两个链接上。通常,main()函数会执行诸如打开输入以进行读取等操作,然后调用yyparse()来执行大部分工作。在yyparse()返回后,main可以清理。
编辑:嗨Rudra,我看到你想在语法文件中保留main()。没关系。
您现在需要做的就是更改片段中的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();
}
您确定不想对数据中的第一个条款做任何事情吗?看起来你并没有将它们用于任何事情。