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