Put
[metze/wireshark/wip.git] / epan / dtd_grammar.lemon
1 %include {
2
3 /* dtd_parser.lemon
4 * XML dissector for wireshark 
5 * XML's DTD grammar
6 *
7 * Copyright 2005, Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
8 *
9 * $Id$
10 *
11 * Wireshark - Network traffic analyzer
12 * By Gerald Combs <gerald@wireshark.org>
13 * Copyright 1998 Gerald Combs
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23 * GNU General Public License for more details.
24
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 */
29
30 #include <stdio.h>
31 #include <glib.h>
32 #include "dtd.h"
33 #include "dtd_parse.h"
34
35 static dtd_named_list_t* dtd_named_list_new(gchar* name, GPtrArray* list) {
36         dtd_named_list_t* nl = g_malloc(sizeof(dtd_named_list_t));
37
38         nl->name = name;
39         nl->list = list;
40         
41         return nl;
42 }
43
44 static GPtrArray* g_ptr_array_join(GPtrArray* a, GPtrArray* b){
45         
46         while(b->len > 0) {
47                 g_ptr_array_add(a,g_ptr_array_remove_index_fast(b,0));
48         }
49         
50         g_ptr_array_free(b,TRUE);
51
52         return a;
53 }
54
55 }
56
57 %name DtdParse
58
59 %extra_argument { dtd_build_data_t *bd }
60
61 %token_destructor { 
62         if ($$) {
63                 if ($$->text) g_free($$->text);
64                 if ($$->location) g_free($$->location);
65                 g_free($$);
66         }
67 }
68
69 %syntax_error {
70         if (!TOKEN)
71                 g_string_sprintfa(bd->error,"syntax error at end of file");
72         else 
73                 g_string_sprintfa(bd->error,"syntax error in %s at or before '%s': \n", TOKEN->location,TOKEN->text);
74 }
75
76 %parse_failure {
77         g_string_sprintfa(bd->error,"DTD parsing failure\n");
78 }
79
80 %token_prefix TOKEN_
81
82 %token_type { dtd_token_data_t* }
83
84 dtd ::= doctype.
85 dtd ::= dtd_parts.
86
87 doctype ::= TAG_START DOCTYPE_KW NAME(Name) OPEN_BRACKET dtd_parts CLOSE_BRACKET TAG_STOP. {
88     dtd_named_list_t* root;
89     GPtrArray* root_elems = g_ptr_array_new();
90     guint i;
91
92     if(! bd->proto_name) {
93         bd->proto_name = Name->text;
94     }
95
96     if(bd->proto_root)
97         g_free(bd->proto_root);
98
99         bd->proto_root = Name->text;
100     
101         g_strdown(bd->proto_name);
102     
103     for( i = 0; i< bd->elements->len; i++) {
104         dtd_named_list_t* el = g_ptr_array_index(bd->elements,i);
105         
106         g_ptr_array_add(root_elems,g_strdup(el->name));
107     }
108     
109     root = dtd_named_list_new(g_strdup(Name->text),root_elems);
110     
111     g_ptr_array_add(bd->elements,root);
112     
113     g_free(Name->location);
114     g_free(Name);
115
116 }
117
118 dtd_parts ::= dtd_parts element(Element). { g_ptr_array_add(bd->elements,Element); }
119 dtd_parts ::= dtd_parts attlist(Attlist). { g_ptr_array_add(bd->attributes,Attlist); }
120 dtd_parts ::= element(Element). { g_ptr_array_add(bd->elements,Element); }
121 dtd_parts ::= attlist(Attlist). { g_ptr_array_add(bd->attributes,Attlist); }
122
123 %type   attlist                         { dtd_named_list_t* }
124 attlist(A) ::= TAG_START ATTLIST_KW NAME(B) attrib_list(TheList) TAG_STOP. {
125     g_strdown(B->text);
126     A = dtd_named_list_new(B->text,TheList);
127     g_free(B->location);
128     g_free(B);
129 }
130
131 %type element { dtd_named_list_t* }
132 element(A) ::= TAG_START ELEMENT_KW NAME(B) sub_elements(C) TAG_STOP. {
133     g_strdown(B->text);
134     A = dtd_named_list_new(B->text,C);
135     g_free(B->location);
136     g_free(B);
137 }
138
139 %type   attrib_list                     { GPtrArray* }
140 attrib_list(A) ::= attrib_list(B) attrib(C). { g_ptr_array_add(B,C); A = B; }
141 attrib_list(A) ::= attrib(B).  { A = g_ptr_array_new(); g_ptr_array_add(A,B);  }
142
143 %type   attrib                          { gchar* }
144 attrib(A) ::= NAME(B) att_type att_default. {
145         A = B->text;
146         g_strdown(A);
147     g_free(B->location);
148     g_free(B);
149 }
150
151 att_type ::= ATT_TYPE.
152 att_type ::= enumeration.
153
154 att_default ::= ATT_DEF.
155 att_default ::= ATT_DEF_WITH_VALUE QUOTED. 
156 att_default ::= QUOTED.
157 att_default ::= IMPLIED_KW.
158 att_default ::= REQUIRED_KW.
159
160 enumeration ::= OPEN_PARENS enum_list CLOSE_PARENS.
161
162 enum_list ::= enum_list PIPE enum_item.
163 enum_list ::= enum_item.
164 enum_list ::= enumeration.
165 enum_list ::= enum_list PIPE enumeration.
166
167 enum_item ::= NAME.
168 enum_item ::= QUOTED.
169
170
171 %type   sub_elements            { GPtrArray* }
172 sub_elements(A) ::= sub_elements(B) STAR. {A=B;}
173 sub_elements(A) ::= sub_elements(B) PLUS. {A=B;}
174 sub_elements(A) ::= sub_elements(B) QUESTION. {A=B;}
175 sub_elements(A) ::= OPEN_PARENS ELEM_DATA CLOSE_PARENS. { A = g_ptr_array_new(); }
176 sub_elements(A) ::= OPEN_PARENS element_list(B) COMMA ELEM_DATA CLOSE_PARENS.   { A = B; }
177 sub_elements(A) ::= OPEN_PARENS element_list(B) PIPE ELEM_DATA CLOSE_PARENS.    { A = B; }
178 sub_elements(A) ::= OPEN_PARENS element_list(B) CLOSE_PARENS. { A = B; }
179 sub_elements(A) ::= EMPTY_KW. { A = g_ptr_array_new(); }
180
181 %type   element_list    { GPtrArray* }
182 element_list(A) ::= element_list(B) COMMA element_child(C).     { g_ptr_array_add(B,C); A = B; }
183 element_list(A) ::= element_list(B) PIPE element_child(C).      { g_ptr_array_add(B,C); A = B; }
184 element_list(A) ::= element_child(B).                                           { A = g_ptr_array_new(); g_ptr_array_add(A,B); }
185 element_list(A) ::= sub_elements(B).                                            { A = B; }
186 element_list(A) ::= element_list(B) COMMA sub_elements(C).   { A = g_ptr_array_join(B,C); }
187 element_list(A) ::= element_list(B) PIPE sub_elements(C).   { A = g_ptr_array_join(B,C); }
188
189 %type   element_child           { gchar* }
190 element_child(A) ::= NAME(B).                   {
191         A = B->text;
192         g_strdown(A);
193     g_free(B->location);
194     g_free(B);
195 }
196
197 element_child(A) ::= NAME(B) STAR.              {
198         A = B->text;
199         g_strdown(A);
200     g_free(B->location);
201     g_free(B);
202 }
203
204 element_child(A) ::= NAME(B) QUESTION.  {
205         A = B->text;
206         g_strdown(A);
207     g_free(B->location);
208     g_free(B);
209 }
210
211 element_child(A) ::= NAME(B) PLUS.              {
212         A = B->text;
213         g_strdown(A);
214     g_free(B->location);
215     g_free(B);
216 }
217