%{ #include "trans.h" #define obstack_chunk_alloc malloc #define obstack_chunk_free free #include struct obstack stk; struct descr *make_descr(enum descr_type type, u_char *value); static int _register_topic(void *item, void *data); %} %token NODE POS END MEANING ALIAS ANT TOPIC FORMS XREF %token STRING %type string pos forms %type
nodehdr alias %type descr %type list aliases descrlist header %type item %union { u_char *string; struct header *header; struct descr *descr; RAD_LIST *list; struct gram_item item; }; %% input : list { node_list = $1; } ; list : item { $$ = list_create(); switch ($1.type) { case item_node: list_append($$, $1.v.node); break; case item_list: list_concat($$, $1.v.list); list_destroy(&$1.v.list, NULL, NULL); } } | list item { switch ($2.type) { case item_node: list_append($1, $2.v.node); break; case item_list: list_concat($1, $2.v.list); list_destroy(&$2.v.list, NULL, NULL); } $$ = $1; } ; item : header descrlist end { $$.type = item_node; $$.v.node = create_node($1, $2); } | TOPIC string list end { $$.type = item_list; $$.v.list = $3; list_iterate($3, _register_topic, make_descr(descr_topic, $2)); } ; end : END ; header : nodehdr { $$ = list_create(); list_append($$, $1); } | nodehdr aliases { list_prepend($2, $1); $$ = $2; } ; nodehdr : NODE string pos forms { $$ = emalloc(sizeof(*$$)); $$->key = $2; $$->pos = $3; $$->forms = $4; } ; pos : /* empty */ { $$ = NULL; } | POS string { $$ = $2; } ; forms : /* empty */ { $$ = NULL; } | FORMS string { $$ = $2; } ; aliases : alias { $$ = list_create(); list_append($$, $1); } | aliases alias { list_append($1, $2); $$ = $1; } ; alias : ALIAS string pos forms { $$ = emalloc(sizeof(*$$)); $$->key = $2; $$->pos = $3; $$->forms = $4; } ; descrlist: descr { $$ = list_create(); list_append($$, $1); } | descrlist descr { list_append($1, $2); $$ = $1; } ; descr : TOPIC string { $$ = make_descr(descr_topic, $2); } | MEANING string { $$ = make_descr(descr_meaning, $2); } | ANT string { $$ = make_descr(descr_antonym, $2); } | XREF string { $$ = make_descr(descr_xref, $2); } ; string : mstring { obstack_1grow(&stk, 0); $$ = obstack_finish(&stk); } ; mstring : STRING { obstack_grow(&stk, $1, strlen($1)); } | mstring STRING { obstack_1grow(&stk, '\n'); obstack_grow(&stk, $2, strlen($2)); } ; %% yyerror(char *s) { fprintf (stderr, "%s:%d: %s\n", file_name, input_line, s); } int parse(char *name) { if (name) open_input(name); obstack_init(&stk); return yyparse(); } struct descr * make_descr(enum descr_type type, u_char *value) { struct descr *p = emalloc(sizeof(*p)); p->type = type; p->value = value; return p; } static int _register_topic(void *item, void *data) { struct node *node = item; list_append(node->descr, data); return 0; }