diff options
Diffstat (limited to 'yy/kalmia.y')
-rw-r--r-- | yy/kalmia.y | 50 |
1 files changed, 38 insertions, 12 deletions
diff --git a/yy/kalmia.y b/yy/kalmia.y index 56b15ac..ec806f7 100644 --- a/yy/kalmia.y +++ b/yy/kalmia.y @@ -8,14 +8,11 @@ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> + #include <string.h> } %code requires { typedef void* yyscan_t; - struct kalmia_t { - struct kai_tag_t *tag; - }; - struct kai_attr_t { char *key; char *value; @@ -31,11 +28,21 @@ struct kai_tag_t *next; }; + + void kai_tag_destroy(struct kai_tag_t *tag); } -%parse-param { struct kalmia_t *result } +%parse-param { struct kai_tag_t **document } %code { int yylex(YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t scanner); - int yyerror(YYLTYPE *yyllocp, yyscan_t unused, struct kalmia_t *unused2, const char *msg); + int yyerror(YYLTYPE *yyllocp, yyscan_t unused, struct kai_tag_t **unused2, const char *msg); + + #define TAG_MISMATCH(a, b) \ + do { \ + char buf[1024]; \ + snprintf(buf, 1024, "Tag name mismatch: \"%s\" != \"%s\"", a, b); \ + yyerror(&yylloc, NULL, NULL, (const char*) buf); \ + YYABORT; \ + } while (0) struct kai_attr_t * kai_attr_new(char *key, char *value); struct kai_attr_t * kai_attr_last(struct kai_attr_t *head); @@ -60,6 +67,7 @@ %token <string> CONTENT %type <tag> start_tag +%type <string> end_tag %type <tag> empty_tag %type <tag> tag %type <tag> tags @@ -71,7 +79,7 @@ %% -document: PROLOG tag { result->tag = $2; } +document: PROLOG tag { *document = $2; } tags: @@ -81,9 +89,26 @@ tags: tag: - start_tag end_tag { $$ = $1; } - | start_tag CONTENT end_tag { $$ = $1; $$->content = $2; } - | start_tag tags end_tag { $$ = $1; $$->children = $2; } + start_tag end_tag + { + $$ = $1; + if (strcmp($$->type, $2) != 0) TAG_MISMATCH($$->type, $2); + free($2); + } + | start_tag CONTENT end_tag + { + $$ = $1; + $$->content = $2; + if (strcmp($$->type, $3) != 0) TAG_MISMATCH($$->type, $3); + free($3); + } + | start_tag tags end_tag + { + $$ = $1; + $$->children = $2; + if (strcmp($$->type, $3) != 0) TAG_MISMATCH($$->type, $3); + free($3); + } | empty_tag { $$ = $1; } ; @@ -116,7 +141,7 @@ empty_tag: end_tag: - E_TAG_OPEN NAME TAG_CLOSE + E_TAG_OPEN NAME TAG_CLOSE { $$ = $2; } ; @@ -140,7 +165,7 @@ attribute: int yyerror( YYLTYPE *yyllocp, yyscan_t unused, - struct kalmia_t *unused2, + struct kai_tag_t **unused2, const char *msg) { fprintf( @@ -220,4 +245,5 @@ void kai_tag_destroy(struct kai_tag_t *tag) kai_tag_destroy(tag->children); free(tag->content); kai_tag_destroy(tag->next); + free(tag); } |