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 "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 
     48 CRuleParser::CRuleParser(const string &strApplicationRule,
     49                          const CSelectionCriteriaDefinition *pSelectionCriteriaDefinition)
     50     : _strApplicationRule(strApplicationRule),
     51       _pSelectionCriteriaDefinition(pSelectionCriteriaDefinition)
     52 {
     53 }
     54 
     55 CRuleParser::~CRuleParser()
     56 {
     57     delete _pRootRule;
     58 }
     59 
     60 // Parse
     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
    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
    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