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 "AlwaysAssert.hpp"
34 #include <assert.h>
35
36 using std::string;
37
38 // Matches
39 const char *CRuleParser::_acDelimiters[CRuleParser::ENbStatuses] = {
40 "{", // EInit
41 "{} ", // EBeginCompoundRule
42 ",}", // EEndCompoundRule
43 ",}", // ECriterionRule
44 "{ ", // EContinue
45 "" // EDone
46 };
47
CRuleParser(const string & strApplicationRule,const CSelectionCriteriaDefinition * pSelectionCriteriaDefinition)48 CRuleParser::CRuleParser(const string &strApplicationRule,
49 const CSelectionCriteriaDefinition *pSelectionCriteriaDefinition)
50 : _strApplicationRule(strApplicationRule),
51 _pSelectionCriteriaDefinition(pSelectionCriteriaDefinition)
52 {
53 }
54
~CRuleParser()55 CRuleParser::~CRuleParser()
56 {
57 delete _pRootRule;
58 }
59
60 // Parse
parse(CCompoundRule * pParentRule,string & strError)61 bool CRuleParser::parse(CCompoundRule *pParentRule, string &strError)
62 {
63 while (true) {
64 // Iterate till next relevant delimiter
65 if (!iterate(strError)) {
66
67 return false;
68 }
69 switch (_eStatus) {
70 case EBeginCompoundRule: {
71
72 // Create new compound rule
73 CCompoundRule *pCompoundRule = new CCompoundRule;
74
75 // Parse
76 if (!pCompoundRule->parse(*this, strError)) {
77
78 delete pCompoundRule;
79
80 return false;
81 }
82 // Parent rule creation context?
83 if (pParentRule) {
84
85 // Chain
86 pParentRule->addChild(pCompoundRule);
87 } else {
88 // Root rule
89 delete _pRootRule;
90 _pRootRule = pCompoundRule;
91 }
92 // Parse
93 if (!parse(pCompoundRule, strError)) {
94
95 return false;
96 }
97 // Go on
98 break;
99 }
100 case EEndCompoundRule:
101 return true;
102 case EContinue:
103 // Seek for new rule
104 break;
105 case ECriterionRule: {
106 // Create new criterion rule
107 CSelectionCriterionRule *pCriterionRule = new CSelectionCriterionRule;
108
109 // Parse
110 if (!pCriterionRule->parse(*this, strError)) {
111
112 delete pCriterionRule;
113
114 return false;
115 }
116
117 ALWAYS_ASSERT(pParentRule != NULL, "Invalid parent rule given to rule parser");
118 // Chain
119 pParentRule->addChild(pCriterionRule);
120
121 // Go on
122 break;
123 }
124 case EDone: {
125 // If the current state is EDone, check that at least one rule has been found.
126 if (_pRootRule) {
127
128 // At least one rule found
129 return true;
130 } else {
131
132 strError = "Syntax error, no rule found";
133
134 return false;
135 }
136 }
137 default:
138 assert(0);
139 return false;
140 }
141 }
142
143 return true;
144 }
145
146 // Iterate
iterate(string & strError)147 bool CRuleParser::iterate(string &strError)
148 {
149 string::size_type delimiter;
150
151 ALWAYS_ASSERT(_uiCurrentPos <= _strApplicationRule.length(), "Current Position outside range");
152
153 // Consume spaces
154 if ((delimiter = _strApplicationRule.find_first_not_of(" ", _uiCurrentPos)) != string::npos) {
155
156 // New pos
157 _uiCurrentPos = delimiter;
158 }
159
160 // Parse
161 if ((_uiCurrentPos != _strApplicationRule.length()) &&
162 ((delimiter = _strApplicationRule.find_first_of(_acDelimiters[_eStatus], _uiCurrentPos)) !=
163 string::npos)) {
164
165 switch (_strApplicationRule[delimiter]) {
166
167 case '{':
168 _eStatus = EBeginCompoundRule;
169 // Extract type
170 _strRuleType = _strApplicationRule.substr(_uiCurrentPos, delimiter - _uiCurrentPos);
171 _currentDeepness++;
172 break;
173 case '}':
174 _eStatus = EEndCompoundRule;
175
176 if (!_currentDeepness--) {
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 (_currentDeepness) {
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