Home | History | Annotate | Download | only in parameter
      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 
     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 
     57 CRuleParser::~CRuleParser()
     58 {
     59     delete _pRootRule;
     60 }
     61 
     62 // Parse
     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
    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
    217 const string& CRuleParser::getType() const
    218 {
    219     return _strRuleType;
    220 }
    221 
    222 // Criteria defintion
    223 const CSelectionCriteriaDefinition* CRuleParser::getSelectionCriteriaDefinition() const
    224 {
    225     return _pSelectionCriteriaDefinition;
    226 }
    227 
    228 // Root rule
    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
    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