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