1 //  Copyright (c) 2005 Carl Barron. Distributed under the Boost
2 //  Software License, Version 1.0. (See accompanying file
3 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4 
5 #ifndef XML_G_H
6 #define XML_G_H
7 #define BOOST_SPIRIT_DEBUG
8 #ifndef BOOST_SPIRIT_CLOSURE_LIMIT
9 #define BOOST_SPIRIT_CLOSURE_LIMIT  10
10 #endif
11 
12 #ifndef PHOENIX_LIMIT
13 #define PHOENIX_LIMIT   10
14 #endif
15 
16 #if BOOST_SPIRIT_CLOSURE_LIMIT < 6
17 #undef BOOST_SPIRIT_CLOSURE_LIMIT
18 #define BOOST_SPIRIT_CLOSURE_LIMIT  6
19 #endif
20 
21 #if PHOENIX_LIMIT < BOOST_SPIRIT_CLOSURE_LIMIT
22 #undef PHOENIX_LIMIT
23 #define PHOENIX_LIMIT BOOST_SPIRIT_CLOSURE_LIMIT
24 #endif
25 
26 #if 0
27 #ifdef BOOST_SPIRIT_DEBUG_FLAGS
28 #undef BOOST_SPIRIT_DEBUG_FLAGS
29 #endif
30 #define BOOST_SPIRIT_DEBUG_FLAGS (BOOST_SPIRIT_DEBUG_FLAGS_MAX - BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES)
31 #endif
32 
33 #include <boost/spirit/include/classic_core.hpp>
34 #include <boost/spirit/include/classic_attribute.hpp>
35 #include <boost/spirit/include/phoenix1.hpp>
36 #include "tag.hpp"
37 #include "actions.hpp"
38 #include <boost/variant.hpp>
39 
40 #include <string>
41 #include <utility>
42 
43 namespace SP = BOOST_SPIRIT_CLASSIC_NS;
44 using phoenix::arg1;
45 using phoenix::arg2;
46 using phoenix::construct_;
47 using phoenix::var;
48 
49 struct str_cls:SP::closure<str_cls,std::string>
50 { member1 value;};
51 
52 struct attrib_cls:SP::closure
53 <
54     attrib_cls,
55     std::pair<std::string,std::string>,
56     std::string,
57     std::string
58 >
59 {
60     member1 value;
61     member2 first;
62     member3 second;
63 };
64 
65 struct tagged_cls:SP::closure
66 <
67     tagged_cls,
68     tag,
69     std::string,
70     std::map<std::string,std::string>,
71     std::list<typename tag::variant_type>
72 >
73 {
74     member1 value;
75     member2 ID;
76     member3 attribs;
77     member4 children;
78 };
79 
80 struct xml_g:SP::grammar<xml_g>
81 {
82     std::list<tag>  &tags;
xml_gxml_g83     xml_g(std::list<tag> &a):tags(a){}
84     template <class Scan>
85     struct definition
86     {
definitionxml_g::definition87         definition(const xml_g &s)
88         {
89             white = +SP::space_p
90                 ;
91 
92             tagged = (start_tag
93                 >> *inner
94                 >> end_tag
95                 | simple_start_tag
96                 )
97                 [store_tag(tagged.value,tagged.ID,tagged.attribs,
98                     tagged.children)]
99                 ;
100 
101             end_tag = SP::str_p("</")
102                 >> SP::f_str_p(tagged.ID)
103                 >> '>'
104                 ;
105 
106             inner = (tagged
107                 | str)  [push_child(tagged.children,arg1)]
108                 ;
109 
110             str = SP::lexeme_d[+(SP::anychar_p - '<')]
111                 [str.value=construct_<std::string>(arg1,arg2)]
112                 ;
113 
114             top = +tagged
115                 [push_back(var(s.tags),arg1)]
116                 ;
117 
118             starter = SP::ch_p('<')
119                 >> SP::lexeme_d[+SP::alpha_p]
120         [tagged.ID = construct_<std::string>(arg1,arg2)]
121                 >> *attrib
122                 [store_in_map(tagged.attribs,arg1)]
123                 >> !white
124                 ;
125             start_tag = starter
126                 >> '>'
127                 ;
128 
129             simple_start_tag = starter
130                 >> "/>"
131                 ;
132 
133             attrib = white
134                 >>SP::lexeme_d[+SP::alpha_p]
135                 [attrib.first = construct_<std::string>(arg1,arg2)]
136                 >> !white
137                 >> '='
138                 >> !white
139                 >> '"'
140                 >> SP::lexeme_d[+(SP::anychar_p - '"')]
141                     [attrib.second = construct_<std::string>(arg1,arg2)]
142                 >> SP::ch_p('"')
143                     [attrib.value = construct_
144                     <
145                         std::pair
146                         <
147                             std::string,
148                             std::string
149                         >
150                     >(attrib.first,attrib.second)]
151                 ;
152         BOOST_SPIRIT_DEBUG_RULE(tagged);
153         BOOST_SPIRIT_DEBUG_RULE(end_tag);
154         BOOST_SPIRIT_DEBUG_RULE(inner);
155         BOOST_SPIRIT_DEBUG_RULE(str);
156         BOOST_SPIRIT_DEBUG_RULE(top);
157         BOOST_SPIRIT_DEBUG_RULE(start_tag);
158         BOOST_SPIRIT_DEBUG_RULE(attrib);
159         BOOST_SPIRIT_DEBUG_RULE(white);
160         BOOST_SPIRIT_DEBUG_RULE(starter);
161         BOOST_SPIRIT_DEBUG_RULE(simple_start_tag);
162         }
163 
164         // actions
165         push_back_f     push_back;
166         push_child_f    push_child;
167         store_in_map_f  store_in_map;
168         store_tag_f     store_tag;
169         // rules
170         SP::rule<Scan,tagged_cls::context_t>    tagged;
171         SP::rule<Scan>                          end_tag;
172         SP::rule<Scan>                          inner;
173         SP::rule<Scan,str_cls::context_t>       str;
174         SP::rule<Scan>                          top;
175         SP::rule<Scan>                          starter;
176         SP::rule<Scan>                          simple_start_tag;
177         SP::rule<Scan>                          start_tag;
178         SP::rule<Scan>                          white;
179         SP::rule<Scan,attrib_cls::context_t>    attrib;
startxml_g::definition180         SP::rule<Scan> const &start() const
181         { return top;}
182     };
183 };
184 
185 #endif
186 
187