You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
266 lines
7.1 KiB
266 lines
7.1 KiB
/*
|
|
* Copyright (c) 2011-2014, Intel Corporation
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without modification,
|
|
* are permitted provided that the following conditions are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
* list of conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation and/or
|
|
* other materials provided with the distribution.
|
|
*
|
|
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software without
|
|
* specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
#include "RuleParser.h"
|
|
#include "CompoundRule.h"
|
|
#include "SelectionCriterionRule.h"
|
|
#include "AlwaysAssert.hpp"
|
|
#include <assert.h>
|
|
|
|
using std::string;
|
|
|
|
// Matches
|
|
const char *CRuleParser::_acDelimiters[CRuleParser::ENbStatuses] = {
|
|
"{", // EInit
|
|
"{} ", // EBeginCompoundRule
|
|
",}", // EEndCompoundRule
|
|
",}", // ECriterionRule
|
|
"{ ", // EContinue
|
|
"" // EDone
|
|
};
|
|
|
|
CRuleParser::CRuleParser(const string &strApplicationRule,
|
|
const CSelectionCriteriaDefinition *pSelectionCriteriaDefinition)
|
|
: _strApplicationRule(strApplicationRule),
|
|
_pSelectionCriteriaDefinition(pSelectionCriteriaDefinition)
|
|
{
|
|
}
|
|
|
|
CRuleParser::~CRuleParser()
|
|
{
|
|
delete _pRootRule;
|
|
}
|
|
|
|
// Parse
|
|
bool CRuleParser::parse(CCompoundRule *pParentRule, string &strError)
|
|
{
|
|
while (true) {
|
|
// Iterate till next relevant delimiter
|
|
if (!iterate(strError)) {
|
|
|
|
return false;
|
|
}
|
|
switch (_eStatus) {
|
|
case EBeginCompoundRule: {
|
|
|
|
// Create new compound rule
|
|
auto pCompoundRule = new CCompoundRule;
|
|
|
|
// Parse
|
|
if (!pCompoundRule->parse(*this, strError)) {
|
|
|
|
delete pCompoundRule;
|
|
|
|
return false;
|
|
}
|
|
// Parent rule creation context?
|
|
if (pParentRule) {
|
|
|
|
// Chain
|
|
pParentRule->addChild(pCompoundRule);
|
|
} else {
|
|
// Root rule
|
|
delete _pRootRule;
|
|
_pRootRule = pCompoundRule;
|
|
}
|
|
// Parse
|
|
if (!parse(pCompoundRule, strError)) {
|
|
|
|
return false;
|
|
}
|
|
// Go on
|
|
break;
|
|
}
|
|
case EEndCompoundRule:
|
|
return true;
|
|
case EContinue:
|
|
// Seek for new rule
|
|
break;
|
|
case ECriterionRule: {
|
|
// Create new criterion rule
|
|
auto pCriterionRule = new CSelectionCriterionRule;
|
|
|
|
// Parse
|
|
if (!pCriterionRule->parse(*this, strError)) {
|
|
|
|
delete pCriterionRule;
|
|
|
|
return false;
|
|
}
|
|
|
|
ALWAYS_ASSERT(pParentRule != nullptr, "Invalid parent rule given to rule parser");
|
|
// Chain
|
|
pParentRule->addChild(pCriterionRule);
|
|
|
|
// Go on
|
|
break;
|
|
}
|
|
case EDone: {
|
|
// If the current state is EDone, check that at least one rule has been found.
|
|
if (_pRootRule) {
|
|
|
|
// At least one rule found
|
|
return true;
|
|
} else {
|
|
|
|
strError = "Syntax error, no rule found";
|
|
|
|
return false;
|
|
}
|
|
}
|
|
default:
|
|
assert(0);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Iterate
|
|
bool CRuleParser::iterate(string &strError)
|
|
{
|
|
string::size_type delimiter;
|
|
|
|
ALWAYS_ASSERT(_uiCurrentPos <= _strApplicationRule.length(), "Current Position outside range");
|
|
|
|
// Consume spaces
|
|
if ((delimiter = _strApplicationRule.find_first_not_of(" ", _uiCurrentPos)) != string::npos) {
|
|
|
|
// New pos
|
|
_uiCurrentPos = delimiter;
|
|
}
|
|
|
|
// Parse
|
|
if ((_uiCurrentPos != _strApplicationRule.length()) &&
|
|
((delimiter = _strApplicationRule.find_first_of(_acDelimiters[_eStatus], _uiCurrentPos)) !=
|
|
string::npos)) {
|
|
|
|
switch (_strApplicationRule[delimiter]) {
|
|
|
|
case '{':
|
|
_eStatus = EBeginCompoundRule;
|
|
// Extract type
|
|
_strRuleType = _strApplicationRule.substr(_uiCurrentPos, delimiter - _uiCurrentPos);
|
|
_currentDeepness++;
|
|
break;
|
|
case '}':
|
|
_eStatus = EEndCompoundRule;
|
|
|
|
if (!_currentDeepness--) {
|
|
|
|
strError = "Missing opening brace";
|
|
|
|
return false;
|
|
}
|
|
break;
|
|
case ' ':
|
|
_eStatus = ECriterionRule;
|
|
// Extract type
|
|
_strRuleType = _strApplicationRule.substr(_uiCurrentPos, delimiter - _uiCurrentPos);
|
|
break;
|
|
case ',':
|
|
_eStatus = EContinue;
|
|
break;
|
|
}
|
|
// New pos
|
|
_uiCurrentPos = delimiter + 1;
|
|
} else {
|
|
|
|
if (_currentDeepness) {
|
|
|
|
strError = "Missing closing brace";
|
|
|
|
return false;
|
|
}
|
|
|
|
// Remaining characters
|
|
if (_uiCurrentPos != _strApplicationRule.length()) {
|
|
|
|
strError = "Syntax error";
|
|
|
|
return false;
|
|
}
|
|
// Done
|
|
_eStatus = EDone;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Rule type
|
|
const string &CRuleParser::getType() const
|
|
{
|
|
return _strRuleType;
|
|
}
|
|
|
|
// Criteria defintion
|
|
const CSelectionCriteriaDefinition *CRuleParser::getSelectionCriteriaDefinition() const
|
|
{
|
|
return _pSelectionCriteriaDefinition;
|
|
}
|
|
|
|
// Root rule
|
|
CCompoundRule *CRuleParser::grabRootRule()
|
|
{
|
|
CCompoundRule *pRootRule = _pRootRule;
|
|
|
|
assert(pRootRule);
|
|
|
|
_pRootRule = nullptr;
|
|
|
|
return pRootRule;
|
|
}
|
|
|
|
// Next word
|
|
bool CRuleParser::next(string &strNext, string &strError)
|
|
{
|
|
string::size_type delimiter;
|
|
|
|
// Consume spaces
|
|
if ((delimiter = _strApplicationRule.find_first_not_of(" ", _uiCurrentPos)) != string::npos) {
|
|
|
|
// New pos
|
|
_uiCurrentPos = delimiter;
|
|
}
|
|
|
|
if ((delimiter = _strApplicationRule.find_first_of("{} ,", _uiCurrentPos)) == string::npos) {
|
|
|
|
strError = "Syntax error";
|
|
|
|
return false;
|
|
}
|
|
|
|
strNext = _strApplicationRule.substr(_uiCurrentPos, delimiter - _uiCurrentPos);
|
|
|
|
// New pos
|
|
_uiCurrentPos = delimiter;
|
|
|
|
return true;
|
|
}
|