• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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