1 /*
2 * Copyright (c) 2011-2014, Intel Corporation
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation and/or
13 * other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors
16 * may be used to endorse or promote products derived from this software without
17 * specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 #include "RuleParser.h"
31 #include "CompoundRule.h"
32 #include "SelectionCriterionRule.h"
33 #include <assert.h>
34
35 using std::string;
36
37 // Matches
38 const char* CRuleParser::_acDelimiters[CRuleParser::ENbStatuses] = {
39 "{", // EInit
40 "{} ", // EBeginCompoundRule
41 ",}", // EEndCompoundRule
42 ",}", // ECriterionRule
43 "{ ", // EContinue
44 "" // EDone
45 };
46
CRuleParser(const string & strApplicationRule,const CSelectionCriteriaDefinition * pSelectionCriteriaDefinition)47 CRuleParser::CRuleParser(const string& strApplicationRule, const CSelectionCriteriaDefinition* pSelectionCriteriaDefinition) :
48 _strApplicationRule(strApplicationRule),
49 _pSelectionCriteriaDefinition(pSelectionCriteriaDefinition),
50 _uiCurrentPos(0),
51 _uiCurrentDeepness(0),
52 _eStatus(CRuleParser::EInit),
53 _pRootRule(NULL)
54 {
55 }
56
~CRuleParser()57 CRuleParser::~CRuleParser()
58 {
59 delete _pRootRule;
60 }
61
62 // Parse
parse(CCompoundRule * pParentRule,string & strError)63 bool CRuleParser::parse(CCompoundRule* pParentRule, string& strError)
64 {
65 while (true) {
66 // Iterate till next relevant delimiter
67 if (!iterate(strError)) {
68
69 return false;
70 }
71 switch(_eStatus) {
72 case EBeginCompoundRule: {
73
74 // Create new compound rule
75 CCompoundRule* pCompoundRule = new CCompoundRule;
76
77 // Parse
78 if (!pCompoundRule->parse(*this, strError)) {
79
80 delete pCompoundRule;
81
82 return false;
83 }
84 // Parent rule creation context?
85 if (pParentRule) {
86
87 // Chain
88 pParentRule->addChild(pCompoundRule);
89 } else {
90 // Root rule
91 delete _pRootRule;
92 _pRootRule = pCompoundRule;
93 }
94 // Parse
95 if (!parse(pCompoundRule, strError)) {
96
97 return false;
98 }
99 // Go on
100 break;
101 }
102 case EEndCompoundRule:
103 return true;
104 case EContinue:
105 // Seek for new rule
106 break;
107 case ECriterionRule: {
108 // Create new criterion rule
109 CSelectionCriterionRule* pCriterionRule = new CSelectionCriterionRule;
110
111 // Parse
112 if (!pCriterionRule->parse(*this, strError)) {
113
114 delete pCriterionRule;
115
116 return false;
117 }
118
119 // Chain
120 pParentRule->addChild(pCriterionRule);
121
122 // Go on
123 break;
124 }
125 case EDone: {
126 // If the current state is EDone, check that at least one rule has been found.
127 if (_pRootRule) {
128
129 // At least one rule found
130 return true;
131 } else {
132
133 strError = "Syntax error, no rule found";
134
135 return false;
136 }
137
138 }
139 default:
140 assert(0);
141 return false;
142 }
143 }
144
145 return true;
146 }
147
148 // Iterate
iterate(string & strError)149 bool CRuleParser::iterate(string& strError)
150 {
151 string::size_type delimiter;
152
153 assert(_uiCurrentPos <= _strApplicationRule.length());
154
155 // Consume spaces
156 if ((delimiter = _strApplicationRule.find_first_not_of(" ", _uiCurrentPos)) != string::npos) {
157
158 // New pos
159 _uiCurrentPos = delimiter;
160 }
161
162 // Parse
163 if ((_uiCurrentPos != _strApplicationRule.length()) && ((delimiter = _strApplicationRule.find_first_of(_acDelimiters[_eStatus], _uiCurrentPos)) != string::npos)) {
164
165 switch(_strApplicationRule[delimiter]) {
166
167 case '{':
168 _eStatus = EBeginCompoundRule;
169 // Extract type
170 _strRuleType = _strApplicationRule.substr(_uiCurrentPos, delimiter - _uiCurrentPos);
171 _uiCurrentDeepness++;
172 break;
173 case '}':
174 _eStatus = EEndCompoundRule;
175
176 if (!_uiCurrentDeepness--) {
177
178 strError = "Missing opening brace";
179
180 return false;
181 }
182 break;
183 case ' ':
184 _eStatus = ECriterionRule;
185 // Extract type
186 _strRuleType = _strApplicationRule.substr(_uiCurrentPos, delimiter - _uiCurrentPos);
187 break;
188 case ',':
189 _eStatus = EContinue;
190 break;
191 }
192 // New pos
193 _uiCurrentPos = delimiter + 1;
194 } else {
195
196 if (_uiCurrentDeepness) {
197
198 strError = "Missing closing brace";
199
200 return false;
201 }
202
203 // Remaining characters
204 if (_uiCurrentPos != _strApplicationRule.length()) {
205
206 strError = "Syntax error";
207
208 return false;
209 }
210 // Done
211 _eStatus = EDone;
212 }
213 return true;
214 }
215
216 // Rule type
getType() const217 const string& CRuleParser::getType() const
218 {
219 return _strRuleType;
220 }
221
222 // Criteria defintion
getSelectionCriteriaDefinition() const223 const CSelectionCriteriaDefinition* CRuleParser::getSelectionCriteriaDefinition() const
224 {
225 return _pSelectionCriteriaDefinition;
226 }
227
228 // Root rule
grabRootRule()229 CCompoundRule* CRuleParser::grabRootRule()
230 {
231 CCompoundRule* pRootRule = _pRootRule;
232
233 assert(pRootRule);
234
235 _pRootRule = NULL;
236
237 return pRootRule;
238 }
239
240 // Next word
next(string & strNext,string & strError)241 bool CRuleParser::next(string& strNext, string& strError)
242 {
243 string::size_type delimiter;
244
245 // Consume spaces
246 if ((delimiter = _strApplicationRule.find_first_not_of(" ", _uiCurrentPos)) != string::npos) {
247
248 // New pos
249 _uiCurrentPos = delimiter;
250 }
251
252 if ((delimiter = _strApplicationRule.find_first_of("{} ,", _uiCurrentPos)) == string::npos) {
253
254 strError = "Syntax error";
255
256 return false;
257 }
258
259 strNext = _strApplicationRule.substr(_uiCurrentPos, delimiter - _uiCurrentPos);
260
261 // New pos
262 _uiCurrentPos = delimiter;
263
264 return true;
265 }
266