Line data Source code
1 : /*
2 : * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 : #define BOOST_SPIRIT_DEBUG
6 : #include "boost/spirit/include/classic.hpp"
7 : #include <boost/config/warning_disable.hpp>
8 : #include <boost/spirit/include/qi.hpp>
9 : #include <boost/spirit/include/phoenix_core.hpp>
10 : #include <boost/spirit/include/phoenix_operator.hpp>
11 : #include <boost/spirit/include/phoenix_stl.hpp>
12 : #include <boost/spirit/include/qi_repeat.hpp>
13 :
14 : #include <boost/assign/list_of.hpp>
15 :
16 : #include <boost/algorithm/string/case_conv.hpp>
17 :
18 : #include <iostream>
19 : #include "base/regex.h"
20 : #include "parser_util.h"
21 :
22 : using contrail::regex;
23 : using contrail::regex_match;
24 : using contrail::regex_search;
25 :
26 : namespace qi = boost::spirit::qi;
27 : namespace ascii = boost::spirit::ascii;
28 : namespace phx = boost::phoenix;
29 : using namespace BOOST_SPIRIT_CLASSIC_NS;
30 :
31 : bool
32 7 : LineParser::GetAtrributes(const pugi::xml_node &node,
33 : LineParser::WordListType *words)
34 : {
35 7 : bool r=true;
36 13 : for (pugi::xml_attribute attr = node.first_attribute(); attr;
37 6 : attr = attr.next_attribute()) {
38 12 : std::string s = MakeSane(boost::algorithm::to_lower_copy(std::string(
39 6 : attr.value())));
40 6 : if (!s.empty()) {
41 6 : r &= ParseDoc(s.begin(), s.end(), words);
42 : }
43 6 : }
44 7 : return r;
45 : }
46 :
47 : bool
48 9 : LineParser::Traverse(const pugi::xml_node &node,
49 : LineParser::WordListType *words, bool check_attr)
50 : {
51 9 : pugi::xml_node_type type = node.type();
52 9 : bool r = true;
53 :
54 9 : if (type == pugi::node_element) {
55 5 : if (check_attr)
56 4 : r &= GetAtrributes(node, words);
57 4 : } else if (type == pugi::node_pcdata || type == pugi::node_cdata) {
58 8 : std::string s = MakeSane(boost::algorithm::to_lower_copy(std::string(
59 4 : node.value())));
60 4 : if (!s.empty()) {
61 4 : r &= ParseDoc(s.begin(), s.end(), words);
62 : }
63 4 : }
64 14 : for (pugi::xml_node s = node.first_child(); s; s = s.next_sibling())
65 5 : r &= Traverse(s, words, check_attr);
66 9 : return r;
67 : }
68 :
69 : bool
70 4 : LineParser::ParseXML(const pugi::xml_node &node,
71 : LineParser::WordListType *words, bool check_attr)
72 : {
73 4 : bool r=true;
74 4 : if (check_attr)
75 3 : r &= GetAtrributes(node, words);
76 8 : for (pugi::xml_node s = node; s; s = s.next_sibling())
77 4 : r &= Traverse(s, words, check_attr);
78 4 : return r;
79 : }
80 :
81 : bool
82 12 : LineParser::Parse(std::string s, LineParser::WordListType *words) {
83 24 : std::string ls = MakeSane(boost::algorithm::to_lower_copy(s));
84 24 : return ParseDoc(ls.begin(), ls.end(), words);
85 12 : }
86 :
87 : template<typename Iterator>
88 : struct msg_skipper : public qi::grammar<Iterator> {
89 22 : msg_skipper() : msg_skipper::base_type(skip, "msgskpr") {
90 44 : skip = ascii::space | qi::char_(".,;:[](){}\t\r");
91 22 : }
92 : qi::rule<Iterator> skip;
93 : };
94 :
95 : template <typename Iterator>
96 : bool
97 22 : LineParser::ParseDoc(Iterator start, Iterator end,
98 : LineParser::WordListType *pv)
99 : {
100 : using ascii::space;
101 : using qi::char_;
102 : using qi::lit;
103 : using qi::_1;
104 : using qi::lexeme;
105 : using qi::debug;
106 : using phx::insert;
107 : using phx::ref;
108 : using boost::spirit::repeat;
109 :
110 : typedef msg_skipper<Iterator> skipper_t;
111 22 : skipper_t skpr;
112 :
113 66 : qi::rule<Iterator, std::string(), skipper_t> num1 =
114 132 : lexeme[ *char_("0-9") >> '.' >> +char_("0-9") ];
115 66 : qi::rule<Iterator, std::string(), skipper_t> num2=
116 110 : lexeme[ +char_("0-9") >> -lit('.') ];
117 66 : qi::rule<Iterator, std::string(), skipper_t> hex1=
118 110 : lexeme[ lit('0') >> lit('x') >> +char_("0-9A-Fa-f") ];
119 66 : qi::rule<Iterator, std::string(), skipper_t> oct1=
120 88 : lexeme[ lit('0') >> +char_("0-7") ];
121 66 : qi::rule<Iterator, std::string(), skipper_t> word =
122 88 : lexeme[ +(char_ - char_(" .,;:[](){}\t\r")) ];
123 44 : qi::rule<Iterator, std::string(), skipper_t> word2 =
124 132 : '\'' >> lexeme[ +(char_ - '\'') ] >> '\'';
125 44 : qi::rule<Iterator, std::string(), skipper_t> word3 =
126 132 : '"' >> lexeme[ +(char_ - '"') ] >> '"';
127 66 : qi::rule<Iterator, std::string(), skipper_t> uuid =
128 66 : lexeme[ repeat(8)[char_("0-9a-fA-F")] >> char_('-') >>
129 132 : repeat(3)[ repeat(4)[char_("0-9a-fA-F")] >> char_('-') ] >>
130 44 : repeat(12)[char_("0-9a-fA-F")] ];
131 66 : qi::rule<Iterator, std::string(), skipper_t> ip =
132 88 : lexeme[ +char_(L'0', L'9') >> char_('.') >> +char_(L'0', L'9')
133 88 : >> +(char_('.') >> +char_(L'0', L'9'))
134 132 : >> -(char_('/') >> +char_(L'0', L'9'))];
135 66 : qi::rule<Iterator, std::string(), skipper_t> ipv6 =
136 66 : lexeme[ +char_("0-9a-fA-F") >> +(+ char_(':')
137 110 : >> +char_("0-9a-fA-F")) >> -(char_('/')
138 88 : >> +char_(L'0', L'9'))];
139 66 : qi::rule<Iterator, std::string(), skipper_t> stats =
140 154 : lexeme[ +char_(L'0', L'9') >> +(char_('/') >> +char_(L'0', L'9'))];
141 :
142 44 : qi::symbols<char, bool> stop_words;
143 : stop_words.add
144 22 : ("via", true)("or", true)("of", true)
145 22 : ("string", true)("sandesh", true)("client", true)
146 22 : ("the", true)("that", true)("and", true);
147 44 : qi::rule<Iterator, std::string(), skipper_t> aw =
148 22 : +( *( lit(":")
149 44 : | lit(",")
150 44 : | lit(".")
151 44 : | lit(";")
152 44 : | lit("&")
153 22 : ) >>
154 : ( stop_words
155 66 : | stats [insert(boost::phoenix::ref(*pv), _1)]
156 66 : | word2 [insert(boost::phoenix::ref(*pv), _1)]
157 66 : | word3 [insert(boost::phoenix::ref(*pv), _1)]
158 66 : | uuid [insert(boost::phoenix::ref(*pv), _1)]
159 66 : | ip [insert(boost::phoenix::ref(*pv), _1)]
160 66 : | ipv6 [insert(boost::phoenix::ref(*pv), _1)]
161 22 : | hex1
162 22 : | oct1
163 22 : | num1
164 22 : | num2
165 88 : | word [insert(boost::phoenix::ref(*pv), _1)]
166 : )
167 : );
168 :
169 44 : bool r = qi::phrase_parse(start, end,
170 : // Begin grammer
171 22 : *aw
172 : // end grammer
173 : , skpr);
174 198 : BOOST_SPIRIT_DEBUG_NODES((word)(num1)(aw)(word2));
175 66 : BOOST_SPIRIT_DEBUG_RULE(word);
176 66 : BOOST_SPIRIT_DEBUG_RULE(word2);
177 66 : BOOST_SPIRIT_DEBUG_RULE(aw);
178 44 : return ((start == end) && r);
179 22 : }
180 :
181 : std::string
182 22 : LineParser::MakeSane(const std::string &text) {
183 22 : std::ostringstream s;
184 1725 : for (std::string::const_iterator it = text.begin(); it != text.end();
185 1703 : ++it) {
186 1703 : if (0x80 & *it)
187 0 : s << "&#" << (int)((uint8_t)*it) << ";";
188 : else
189 1703 : s << *it;
190 : }
191 44 : return s.str();
192 22 : }
193 :
194 : std::string
195 0 : LineParser::GetXmlString(const pugi::xml_node node) {
196 0 : std::ostringstream sstream;
197 0 : if (node.attribute("type").value() == std::string("string"))
198 0 : sstream << " " << LineParser::MakeSane(node.child_value());
199 0 : for (pugi::xml_node child = node.first_child(); child; child =
200 0 : child.next_sibling())
201 0 : sstream << LineParser::GetXmlString(child);
202 0 : return sstream.str();
203 0 : }
204 :
205 : unsigned int
206 7 : LineParser::SearchPattern(const regex &exp, std::string text)
207 : {
208 7 : unsigned int cnt = 0;
209 :
210 7 : boost::match_results<std::string::const_iterator> what;
211 7 : boost::match_flag_type flags = boost::match_default;
212 7 : std::string::const_iterator start = text.begin(), end = text.end();
213 15 : while(regex_search(start, end, what, exp, flags)) {
214 8 : cnt++;
215 : //start looking for next match after this one
216 8 : start = what[0].second;
217 : // update flags:
218 8 : flags |= boost::match_prev_avail;
219 8 : flags |= boost::match_not_bob;
220 : //#define SYSLGDEBUG
221 : #ifdef SYSLGDEBUG
222 : std::cout << "Text: \"" << text << "\"\n";
223 : std::cout << "<String 5> \""
224 : << std::string(what[5].first, what[5].second)
225 : << "\" + <string 6> \"" << std::string(what[6].first, what[6].second)
226 : << "\" = " << what[5].first - text.begin();
227 : std::cout << "\n what.size = " << what.size()
228 : << "\n====================\n";
229 : for(unsigned int i = 0; i < what.size(); ++i)
230 : {
231 : std::cout << " $" << i << " = {";
232 : std::cout << std::string(what[i].first, what[i].second);
233 : std::cout << "}\n";
234 : }
235 : #endif
236 : }
237 7 : return cnt;
238 7 : }
239 :
240 :
241 : // generate a method for the template(required for static template function
242 : void
243 0 : TemplateGen() {
244 0 : std::string s("hello");
245 0 : LineParser::WordListType words;
246 0 : LineParser::Parse(s, &words);
247 0 : std::cout << "result length: " << words.size() << std::endl;
248 0 : }
249 :
|