%define api.pure full %define api.prefix {kalmia} %locations %define parse.error verbose %param { yyscan_t scanner } %code top { #include #include #include } %code requires { typedef void* yyscan_t; struct kalmia_t { void *current; int index; }; struct kai_attr_t { char *key; char *value; struct kai_attr_t *next; }; struct kai_tag_t { char *type; struct kai_attr_t *attrs; struct kai_tag_t *children; char *content; struct kai_tag_t *next; }; } %parse-param { struct kalmia_t *result } %code { int yylex(YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t scanner); int yyerror(YYLTYPE *yyllocp, yyscan_t unused, struct kalmia_t *unused2, const char *msg); struct kai_attr_t * kai_attr_new(char *key, char *value); void kai_attr_destroy(struct kai_attr_t *attr); struct kai_tag_t * kai_tag_new(char *type, struct kai_attr_t *attrs, struct kai_tag_t *children, char *content); void kai_tag_destroy(struct kai_tag_t *tag); } %union { char *string; struct kai_attr_t *attr; struct kai_tag_t *tag; } %token PROLOG %token S_TAG_OPEN E_TAG_OPEN TAG_CLOSE EMPTY_TAG_CLOSE %token NAME %token ATTR %token TEXT %token CONTENT %% document: PROLOG %% int yyerror( YYLTYPE *yyllocp, yyscan_t unused, struct kalmia_t *unused2, const char *msg) { fprintf( stderr, "[%d:%d]: %s\n", yyllocp->first_line, yyllocp->first_column, msg ); return 1; } struct kai_attr_t * kai_attr_new(char *key, char *value) { struct kai_attr_t *attr = malloc(sizeof(struct kai_attr_t)); if (attr == NULL) { return NULL; } attr->key = key; attr->value = value; attr->next = NULL; return attr; } void kai_attr_destroy(struct kai_attr_t *attr) { if (attr == NULL) { return; } kai_attr_destroy(attr->next); free(attr->key); free(attr->value); free(attr); } struct kai_tag_t * kai_tag_new(char *type, struct kai_attr_t *attrs, struct kai_tag_t *children, char *content) { struct kai_tag_t *tag = malloc(sizeof(struct kai_tag_t)); if (tag == NULL) { return NULL; } tag->type = type; tag->attrs = attrs; tag->children = children; tag->content = content; tag->next = NULL; return tag; } void kai_tag_destroy(struct kai_tag_t *tag) { if (tag == NULL) { return; } free(tag->type); kai_attr_destroy(tag->attrs); kai_tag_destroy(tag->children); free(tag->content); kai_tag_destroy(tag->next); }