| %include { |
| |
| /* dtd_parser.lemon |
| * XML dissector for wireshark |
| * XML's DTD grammar |
| * |
| * Copyright 2005, Luis E. Garcia Ontanon <luis.ontanon@gmail.com> |
| * |
| * $Id: dtd_grammar.lemon 20443 2007-01-15 20:14:00Z lego $ |
| * |
| * Wireshark - Network traffic analyzer |
| * By Gerald Combs <gerald@wireshark.org> |
| * Copyright 1998 Gerald Combs |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License |
| * as published by the Free Software Foundation; either version 2 |
| * of the License, or (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| */ |
| |
| #include <stdio.h> |
| #include <glib.h> |
| #include "dtd.h" |
| #include "dtd_parse.h" |
| |
| static dtd_named_list_t* dtd_named_list_new(gchar* name, GPtrArray* list) { |
| dtd_named_list_t* nl = g_malloc(sizeof(dtd_named_list_t)); |
| |
| nl->name = name; |
| nl->list = list; |
| |
| return nl; |
| } |
| |
| static GPtrArray* g_ptr_array_join(GPtrArray* a, GPtrArray* b){ |
| |
| while(b->len > 0) { |
| g_ptr_array_add(a,g_ptr_array_remove_index_fast(b,0)); |
| } |
| |
| g_ptr_array_free(b,TRUE); |
| |
| return a; |
| } |
| |
| } |
| |
| %name DtdParse |
| |
| %extra_argument { dtd_build_data_t *bd } |
| |
| %token_destructor { |
| if ($$) { |
| if ($$->text) g_free($$->text); |
| if ($$->location) g_free($$->location); |
| g_free($$); |
| } |
| } |
| |
| %syntax_error { |
| if (!TOKEN) |
| g_string_sprintfa(bd->error,"syntax error at end of file"); |
| else |
| g_string_sprintfa(bd->error,"syntax error in %s at or before '%s': \n", TOKEN->location,TOKEN->text); |
| } |
| |
| %parse_failure { |
| g_string_sprintfa(bd->error,"DTD parsing failure\n"); |
| } |
| |
| %token_prefix TOKEN_ |
| |
| %token_type { dtd_token_data_t* } |
| |
| dtd ::= doctype. |
| dtd ::= dtd_parts. |
| |
| doctype ::= TAG_START DOCTYPE_KW NAME(Name) OPEN_BRACKET dtd_parts CLOSE_BRACKET TAG_STOP. { |
| dtd_named_list_t* root; |
| GPtrArray* root_elems = g_ptr_array_new(); |
| guint i; |
| |
| if(! bd->proto_name) { |
| bd->proto_name = Name->text; |
| } |
| |
| if(bd->proto_root) |
| g_free(bd->proto_root); |
| |
| bd->proto_root = Name->text; |
| |
| g_strdown(bd->proto_name); |
| |
| for( i = 0; i< bd->elements->len; i++) { |
| dtd_named_list_t* el = g_ptr_array_index(bd->elements,i); |
| |
| g_ptr_array_add(root_elems,g_strdup(el->name)); |
| } |
| |
| root = dtd_named_list_new(g_strdup(Name->text),root_elems); |
| |
| g_ptr_array_add(bd->elements,root); |
| |
| g_free(Name->location); |
| g_free(Name); |
| |
| } |
| |
| dtd_parts ::= dtd_parts element(Element). { g_ptr_array_add(bd->elements,Element); } |
| dtd_parts ::= dtd_parts attlist(Attlist). { g_ptr_array_add(bd->attributes,Attlist); } |
| dtd_parts ::= element(Element). { g_ptr_array_add(bd->elements,Element); } |
| dtd_parts ::= attlist(Attlist). { g_ptr_array_add(bd->attributes,Attlist); } |
| |
| %type attlist { dtd_named_list_t* } |
| attlist(A) ::= TAG_START ATTLIST_KW NAME(B) attrib_list(TheList) TAG_STOP. { |
| g_strdown(B->text); |
| A = dtd_named_list_new(B->text,TheList); |
| g_free(B->location); |
| g_free(B); |
| } |
| |
| %type element { dtd_named_list_t* } |
| element(A) ::= TAG_START ELEMENT_KW NAME(B) sub_elements(C) TAG_STOP. { |
| g_strdown(B->text); |
| A = dtd_named_list_new(B->text,C); |
| g_free(B->location); |
| g_free(B); |
| } |
| |
| %type attrib_list { GPtrArray* } |
| attrib_list(A) ::= attrib_list(B) attrib(C). { g_ptr_array_add(B,C); A = B; } |
| attrib_list(A) ::= attrib(B). { A = g_ptr_array_new(); g_ptr_array_add(A,B); } |
| |
| %type attrib { gchar* } |
| attrib(A) ::= NAME(B) att_type att_default. { |
| A = B->text; |
| g_strdown(A); |
| g_free(B->location); |
| g_free(B); |
| } |
| |
| att_type ::= ATT_TYPE. |
| att_type ::= enumeration. |
| |
| att_default ::= ATT_DEF. |
| att_default ::= ATT_DEF_WITH_VALUE QUOTED. |
| att_default ::= QUOTED. |
| att_default ::= IMPLIED_KW. |
| att_default ::= REQUIRED_KW. |
| |
| enumeration ::= OPEN_PARENS enum_list CLOSE_PARENS. |
| |
| enum_list ::= enum_list PIPE enum_item. |
| enum_list ::= enum_item. |
| enum_list ::= enumeration. |
| enum_list ::= enum_list PIPE enumeration. |
| |
| enum_item ::= NAME. |
| enum_item ::= QUOTED. |
| |
| |
| %type sub_elements { GPtrArray* } |
| sub_elements(A) ::= sub_elements(B) STAR. {A=B;} |
| sub_elements(A) ::= sub_elements(B) PLUS. {A=B;} |
| sub_elements(A) ::= sub_elements(B) QUESTION. {A=B;} |
| sub_elements(A) ::= OPEN_PARENS ELEM_DATA CLOSE_PARENS. { A = g_ptr_array_new(); } |
| sub_elements(A) ::= OPEN_PARENS element_list(B) COMMA ELEM_DATA CLOSE_PARENS. { A = B; } |
| sub_elements(A) ::= OPEN_PARENS element_list(B) PIPE ELEM_DATA CLOSE_PARENS. { A = B; } |
| sub_elements(A) ::= OPEN_PARENS element_list(B) CLOSE_PARENS. { A = B; } |
| sub_elements(A) ::= EMPTY_KW. { A = g_ptr_array_new(); } |
| |
| %type element_list { GPtrArray* } |
| element_list(A) ::= element_list(B) COMMA element_child(C). { g_ptr_array_add(B,C); A = B; } |
| element_list(A) ::= element_list(B) PIPE element_child(C). { g_ptr_array_add(B,C); A = B; } |
| element_list(A) ::= element_child(B). { A = g_ptr_array_new(); g_ptr_array_add(A,B); } |
| element_list(A) ::= sub_elements(B). { A = B; } |
| element_list(A) ::= element_list(B) COMMA sub_elements(C). { A = g_ptr_array_join(B,C); } |
| element_list(A) ::= element_list(B) PIPE sub_elements(C). { A = g_ptr_array_join(B,C); } |
| |
| %type element_child { gchar* } |
| element_child(A) ::= NAME(B). { |
| A = B->text; |
| g_strdown(A); |
| g_free(B->location); |
| g_free(B); |
| } |
| |
| element_child(A) ::= NAME(B) STAR. { |
| A = B->text; |
| g_strdown(A); |
| g_free(B->location); |
| g_free(B); |
| } |
| |
| element_child(A) ::= NAME(B) QUESTION. { |
| A = B->text; |
| g_strdown(A); |
| g_free(B->location); |
| g_free(B); |
| } |
| |
| element_child(A) ::= NAME(B) PLUS. { |
| A = B->text; |
| g_strdown(A); |
| g_free(B->location); |
| g_free(B); |
| } |
| |