%{ #include int yyerror(const char *); int yylex(); char attr_buf[1024]; int attr_i; %} %union { long lval; double dval; char *sval; char cval; } %token PROLOG %token S_TAG_OPEN E_TAG_OPEN TAG_CLOSE EMPTY_TAG_CLOSE %token NAME %token CHAR %token INTEGER %token DOUBLE %token DATE; %define parse.error verbose %% document: PROLOG element; elements: element | elements element ; element: empty_tag | start_tag end_tag | start_tag content end_tag ; content: elements | integers | doubles | DATE ; empty_tag: S_TAG_OPEN NAME attributes EMPTY_TAG_CLOSE { printf("empty tag: %s\n", $2); } ; start_tag: S_TAG_OPEN NAME attributes TAG_CLOSE { printf("enter tag: %s\n", $2); } ; end_tag: E_TAG_OPEN NAME TAG_CLOSE { printf("exit tag: %s\n", $2); } ; attributes: | attribute | attributes attribute; ; attribute: NAME '=' '"' chars '"' { attr_buf[attr_i] = 0; printf("attribute: %s=%s\n", $1, attr_buf); attr_i = 0; } ; chars: | CHAR { attr_buf[attr_i] = $1; attr_i += 1; } | chars CHAR { attr_buf[attr_i] = $2; attr_i += 1; } ; integers: INTEGER | integers INTEGER ; doubles: DOUBLE | doubles DOUBLE ; %% extern FILE *yyin; extern int line_num; int main() { attr_i = 0; line_num = 0; yyin = fopen("in.xml", "r"); if (yyin == NULL) { fprintf(stderr, "could not open file!\n"); return -1; } do { yyparse(); } while (!feof(yyin)); return 0; } int yyerror(const char *msg) { fprintf(stderr, "parse error on line %d: %s\n", line_num, msg); return 1; }