summaryrefslogtreecommitdiff
path: root/yy/kalmia.y
diff options
context:
space:
mode:
Diffstat (limited to 'yy/kalmia.y')
-rw-r--r--yy/kalmia.y50
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);
}