1// ----------------------------------------------------------------------------
2// Copyright (C) 2002-2006 Marcin Kalicinski
3//
4// Distributed under the Boost Software License, Version 1.0.
5// (See accompanying file LICENSE_1_0.txt or copy at
6// http://www.boost.org/LICENSE_1_0.txt)
7//
8// For more information, see www.boost.org
9// ----------------------------------------------------------------------------
10
11/* This is grammar of INFO file format written in form of boost::spirit rules.
12 For simplicity, it does not parse #include directive. Note that INFO parser
13 included in property_tree library does not use Spirit.
14*/
15
16//#define BOOST_SPIRIT_DEBUG // uncomment to enable debug output
17#include <boost/spirit/include/classic.hpp>
18
19namespace spirit = boost::spirit;
20
21struct info_grammar: public spirit::classic::grammar<info_grammar>
22{
23
24 template<class Scanner>
25 struct definition
26 {
27
28 spirit::classic::rule<typename spirit::classic::lexeme_scanner<Scanner>::type> chr, qchr, escape_seq;
29 spirit::classic::rule<Scanner> string, qstring, cstring, key, value, entry, info;
30
31 definition(const info_grammar & /*self*/)
32 {
33
34 using namespace spirit::classic;
35
36 escape_seq = chset_p(init: "0abfnrtv\"\'\\");
37 chr = (anychar_p - space_p - '\\' - '{' - '}' - '#' - '"') | ('\\' >> escape_seq);
38 qchr = (anychar_p - '"' - '\n' - '\\') | ('\\' >> escape_seq);
39 string = lexeme_d[+chr];
40 qstring = lexeme_d['"' >> *qchr >> '"'];
41 cstring = lexeme_d['"' >> *qchr >> '"' >> '\\'];
42 key = string | qstring;
43 value = string | qstring | (+cstring >> qstring) | eps_p;
44 entry = key >> value >> !('{' >> *entry >> '}');
45 info = *entry >> end_p;
46
47 // Debug nodes
48 BOOST_SPIRIT_DEBUG_NODE(escape_seq);
49 BOOST_SPIRIT_DEBUG_NODE(chr);
50 BOOST_SPIRIT_DEBUG_NODE(qchr);
51 BOOST_SPIRIT_DEBUG_NODE(string);
52 BOOST_SPIRIT_DEBUG_NODE(qstring);
53 BOOST_SPIRIT_DEBUG_NODE(key);
54 BOOST_SPIRIT_DEBUG_NODE(value);
55 BOOST_SPIRIT_DEBUG_NODE(entry);
56 BOOST_SPIRIT_DEBUG_NODE(info);
57
58 }
59
60 const spirit::classic::rule<Scanner> &start() const
61 {
62 return info;
63 }
64
65 };
66};
67
68void info_parse(const char *s)
69{
70
71 using namespace boost::spirit::classic;
72
73 // Parse and display result
74 info_grammar g;
75 parse_info<const char *> pi = parse(str: s, p: g, skip: space_p | comment_p(";"));
76 std::cout << "Parse result: " << (pi.hit ? "Success" : "Failure") << "\n";
77
78}
79
80int main()
81{
82
83 // Sample data 1
84 const char *data1 =
85 "\n"
86 "key1 data1\n"
87 "{\n"
88 "\tkey data\n"
89 "}\n"
90 "key2 \"data2 \" {\n"
91 "\tkey data\n"
92 "}\n"
93 "key3 \"data\"\n"
94 "\t \"3\" {\n"
95 "\tkey data\n"
96 "}\n"
97 "\n"
98 "\"key4\" data4\n"
99 "{\n"
100 "\tkey data\n"
101 "}\n"
102 "\"key.5\" \"data.5\" { \n"
103 "\tkey data \n"
104 "}\n"
105 "\"key6\" \"data\"\n"
106 "\t \"6\" {\n"
107 "\tkey data\n"
108 "}\n"
109 " \n"
110 "key1 data1\n"
111 "{\n"
112 "\tkey data\n"
113 "}\n"
114 "key2 \"data2 \" {\n"
115 "\tkey data\n"
116 "}\n"
117 "key3 \"data\"\n"
118 "\t \"3\" {\n"
119 "\tkey data\n"
120 "}\n"
121 "\n"
122 "\"key4\" data4\n"
123 "{\n"
124 "\tkey data\n"
125 "}\n"
126 "\"key.5\" \"data.5\" {\n"
127 "\tkey data\n"
128 "}\n"
129 "\"key6\" \"data\"\n"
130 "\t \"6\" {\n"
131 "\tkey data\n"
132 "}\n"
133 "\\\\key\\t7 data7\\n\\\"data7\\\"\n"
134 "{\n"
135 "\tkey data\n"
136 "}\n"
137 "\"\\\\key\\t8\" \"data8\\n\\\"data8\\\"\"\n"
138 "{\n"
139 "\tkey data\n"
140 "}\n"
141 "\n";
142
143 // Sample data 2
144 const char *data2 =
145 "key1\n"
146 "key2\n"
147 "key3\n"
148 "key4\n";
149
150 // Parse sample data
151 info_parse(s: data1);
152 info_parse(s: data2);
153
154}
155

source code of boost/libs/property_tree/examples/info_grammar_spirit.cpp