%{ #include #include #include #include "tag.h" int dtdlex(); int dtderror(); %} %union { char *string; DTDObj *dtdobj; DTDName *name; } %token START END OR NEXT OPEN CLOSE PLUS ASTARISK QUESTION CHAR EMPTY PCDATA %token ID %type dtd dtdor dtddat dtdobj %type names name %% all: all line | line ; line: START names CHAR CHAR dtd END { DTDName *p = $2; TagInfo *ti; while (p != NULL) { ti = GetTagInfo(p->name); if (ti) ti->dtd = $5; else fprintf(stderr, "warning: tag [%s] not found\n", p->name); p = p->next; } dtdnamelist_delete($2); }; names: OPEN name CLOSE { $$ = $2; } | ID { $$ = dtdname_new(); $$->name = $1; } name: name OR ID { DTDName *p = dtdname_new(); p->name = $3; p->next = $$; $$ = p; } | ID { $$ = dtdname_new(); $$->name = $1; }; dtd: EMPTY { $$ = NULL; } | dtdor NEXT dtd { DTDObj *p = $1; while (p->next != NULL) { p->end = $3; p = p->next; } p->end = p->next = $3; $$ = $1; } | dtdor {$$ = $1;}; dtdor: dtdor OR dtddat { DTDObj *p = $1; while (p->next != NULL) p = p->next; p->next = $3; }| dtddat {$$ = $1;}; dtddat: dtdobj {$$ = $1;} | dtdobj QUESTION {$1->repeat = DTD_REPEAT_0or1; $$ = $1;} | dtdobj PLUS {$1->repeat = DTD_REPEAT_over1; $$ = $1;} | dtdobj ASTARISK {$1->repeat = DTD_REPEAT_over0; $$ = $1;}; dtdobj: PCDATA { $$ = dtdobj_new(); $$->type = DTD_NORMAL; $$->data = &taginfo_pcdata; } | ID { $$ = dtdobj_new(); $$->type = DTD_NORMAL; if (($$->data = GetTagInfo($1)) == NULL) { fprintf(stderr, "fatal: tag [%s] not found\n", $1); exit(1); } free($1); } | OPEN dtd CLOSE { $$ = dtdobj_new(); $$->type = DTD_KAKKO; $$->data = $2; }; %% int dtd_lineno; extern FILE *dtdin; extern char *dtdtext; int dtdparse(); int dtd_readdtd(FILE *fp) { int ret; dtdin = fp; dtd_lineno = 1; if ((ret = dtdparse())) exit(1); return ret; } int dtderror(char *msg) { fprintf(stderr,"%d: %s at '%s'\n", dtd_lineno, msg, dtdtext); return 0; } int dtdwrap(void) { return 1; }