%define api.pure full %define api.prefix {kalmia} %locations %define parse.error verbose %param { yyscan_t scanner } %code top { #include } %code requires { typedef void* yyscan_t; } %code { int yylex(YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t scanner); int yyerror(YYLTYPE *yyllocp, yyscan_t unused, const char *msg); } %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 ATTR %token TEXT %token INTEGER %token DOUBLE %token DATE; %% 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: ATTR '=' '"' TEXT '"' { printf("attribute: %s=%s\n", $1, $4); } ; integers: INTEGER { printf("%ld\n", $1); } | integers INTEGER { printf("%ld\n", $2); } ; doubles: DOUBLE { printf("%f\n", $1); } | doubles DOUBLE { printf("%f\n", $2); } ; %% int yyerror(YYLTYPE *yyllocp, yyscan_t unused, const char *msg) { fprintf( stderr, "[%d:%d]: %s\n", yyllocp->first_line, yyllocp->first_column, msg ); return 1; }