%{ #include #include #include #include #include "error.h" #include "malloc.h" #include "domnode-xml.h" /* Generated by bison(1) */ #include "domnode-xml-parser.h" /* Generated by flex(1) */ #define YY_HEADER_NO_UNDEFS 1 #include "domnode-xml-scanner.h" #define YYPARSE_PARAM __a_maker #define a_maker ((struct __sd_domnode_xml_maker*) YYPARSE_PARAM) #define YYLEX_PARAM (a_maker->scanner) #ifdef strdup # undef strdup #endif #define strdup sd_strdup #ifdef malloc # undef malloc #endif #define malloc sd_malloc #ifdef calloc # undef calloc #endif #define calloc sd_calloc #ifdef realloc # undef realloc #endif #define realloc sd_realloc #ifdef yyerror # undef yyerror #endif #define yyerror sd_error static void domnode_attribute(struct __sd_domnode_xml_maker*, const char*, const char*); %} %name-prefix="__sd_domnode_xml_" %pure_parser %debug %defines %output="domnode-xml-parser.c" %union { char *s; } %token ENDDEF EQ SLASH CLOSE END %token NAME VALUE DATA COMMENT START %type name %% document : misc element misc ; misc : misc comment | /* empty */ ; comment : COMMENT { sd_domnode_t* node = sd_stack_peek(a_maker->elements); if (node) { sd_debug("COMMENT: add comment '%s' to node '%s'\n", $1, node->name); sd_list_append(node->children, __sd_domnode_new("#comment", $1, 0)); /* $1 was obtain with strdup() */ free($1); } } ; element : START { sd_domnode_t* parent = sd_stack_peek(a_maker->elements); sd_domnode_t* node = __sd_domnode_new($1, 0, 1); #ifdef __SD_DEBUG__ { static void* __debug = 0; if (! __debug) { __debug = getenv("SD_DEBUG"); if (__debug) yydebug = 1; else __debug = (void*) 0x1; } } #endif if (parent) { sd_debug("START: add child '%s' to node '%s'\n", $1, parent->name); sd_list_append(parent->children, node); } else { sd_debug("START: add root'%s'\n", $1); a_maker->root = node; } sd_stack_push(a_maker->elements, node); free($1); } attribute_seq_opt empty_or_content ; empty_or_content : SLASH CLOSE { sd_domnode_t* node = sd_stack_peek(a_maker->elements); assert(node != 0); sd_debug("END: simple node '%s'\n", node->name); sd_stack_pop(a_maker->elements); } | CLOSE content END name CLOSE { sd_domnode_t* node = sd_stack_peek(a_maker->elements); assert(node != 0); sd_debug("END: node '%s'\n", $4); if (strcmp(node->name, $4)) { yyerror("got instead of \n", $4, node->name); YYERROR; } /* $4 was obtain with strdup() */ free($4); sd_stack_pop(a_maker->elements); } ; content : content DATA { sd_domnode_t* node = sd_stack_peek(a_maker->elements); assert(node != 0); sd_debug("CONTENT: add cvalue '%s' to node '%s'\n", $2, node->name); /* $2 was obtain with strdup() */ node->value = $2; } | content element | content comment | /*empty*/ ; name : NAME { $$ = $1; } ; attribute_seq_opt : attribute_seq_opt attribute | /*empty*/ ; attribute : NAME { domnode_attribute(a_maker, $1, ""); /* $1 was obtain with strdup() */ free($1); } | NAME EQ VALUE { domnode_attribute(a_maker, $1, $3); /* $1 was obtain with strdup() */ free($1); /* $3 was obtain with strdup() */ free($3); } ; %% #undef a_maker /******************************************************************************/ static void domnode_attribute(struct __sd_domnode_xml_maker* a_maker, const char* a_name, const char* a_value) { sd_domnode_t* node = sd_stack_peek(a_maker->elements); assert(node != 0); sd_debug("ATTR: add atrribute '%s'='%s' to node '%s'\n", a_name, a_value, node->name); sd_list_append(node->attrs, __sd_domnode_new(a_name, a_value, 0)); }