Fix the reduce/reduce conflicts

refs #7800
This commit is contained in:
Gunnar Beutner 2014-11-23 15:20:51 +01:00
parent 14c94fabde
commit d366dd8e30
6 changed files with 106 additions and 79 deletions

View File

@ -181,6 +181,7 @@ static void MakeRBinaryOp(Expression** result, Expression *left, Expression *rig
%type <csop> combined_set_op
%type <type> type
%type <expr> rterm
%type <expr> rterm_without_indexer
%type <expr> rterm_array
%type <expr> rterm_scope
%type <expr> lterm
@ -505,17 +506,10 @@ identifier_items_inner: /* empty */
}
;
indexer: identifier
{
$$ = new std::vector<Expression *>();
$$->push_back(MakeLiteral($1));
free($1);
}
| identifier indexer_items
indexer: rterm_without_indexer indexer_items
{
$$ = $2;
$$->insert($$->begin(), MakeLiteral($1));
free($1);
$$->insert($$->begin(), $1);
}
;
@ -591,6 +585,16 @@ lterm: T_LOCAL indexer combined_set_op rterm
$$ = new SetExpression(*$1, $2, $3, false, DebugInfoRange(@1, @3));
delete $1;
}
| T_LOCAL identifier combined_set_op rterm
{
$$ = new SetExpression(MakeIndexer($2), $3, $4, true, DebugInfoRange(@1, @4));
free($2);
}
| identifier combined_set_op rterm
{
$$ = new SetExpression(MakeIndexer($1), $2, $3, false, DebugInfoRange(@1, @3));
free($1);
}
| T_INCLUDE rterm
{
VMFrame frame;
@ -735,7 +739,18 @@ rterm_scope: '{' newlines lterm_items newlines '}'
}
;
rterm: T_STRING
rterm: rterm_without_indexer
{
$$ = $1;
}
| indexer
{
$$ = new IndexerExpression(*$1, @1);
delete $1;
}
;
rterm_without_indexer: T_STRING
{
$$ = MakeLiteral($1);
free($1);
@ -748,11 +763,6 @@ rterm: T_STRING
{
$$ = MakeLiteral();
}
| rterm '.' T_IDENTIFIER
{
$$ = new IndexerExpression($1, MakeLiteral($3), DebugInfoRange(@1, @3));
free($3);
}
| rterm '(' rterm_items ')'
{
$$ = new FunctionCallExpression($1, *$3, DebugInfoRange(@1, @4));
@ -771,10 +781,6 @@ rterm: T_STRING
{
$$ = new NegateExpression($2, DebugInfoRange(@1, @2));
}
| rterm '[' rterm ']'
{
$$ = new IndexerExpression($1, $3, DebugInfoRange(@1, @4));
}
| rterm_array
{
$$ = $1;

View File

@ -100,10 +100,7 @@ ConfigItem::Ptr ConfigItemBuilder::Compile(void)
Array::Ptr templateArray = new Array();
templateArray->Add(m_Name);
std::vector<Expression *> indexer;
indexer.push_back(new LiteralExpression("templates"));
exprs.push_back(new SetExpression(indexer, OpSetAdd,
exprs.push_back(new SetExpression(MakeIndexer("templates"), OpSetAdd,
new LiteralExpression(templateArray), false, m_DebugInfo));
DictExpression *dexpr = new DictExpression(m_Expressions, m_DebugInfo);

View File

@ -64,7 +64,7 @@ const DebugInfo& Expression::GetDebugInfo(void) const
std::vector<Expression *> icinga::MakeIndexer(const String& index1)
{
std::vector<Expression *> result;
result.push_back(MakeLiteral(index1));
result.push_back(new VariableExpression(index1));
return result;
}
@ -270,7 +270,20 @@ Value SetExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
for (Array::SizeType i = 0; i < m_Indexer.size(); i++) {
Expression *indexExpr = m_Indexer[i];
String tempindex = indexExpr->Evaluate(frame, dhint);
String tempindex;
if (i == 0) {
VariableExpression *vexpr = dynamic_cast<VariableExpression *>(indexExpr);
if (!vexpr) {
object = indexExpr->Evaluate(frame, dhint);
continue;
}
tempindex = vexpr->GetVariable();
} else
tempindex = indexExpr->Evaluate(frame, dhint);
if (psdhint) {
sdhint = psdhint->GetChild(tempindex);
@ -290,7 +303,7 @@ Value SetExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
break;
}
object = VMOps::Indexer(frame, parent, tempindex);
object = VMOps::GetField(parent, tempindex);
if (i != m_Indexer.size() - 1 && object.IsEmpty()) {
object = new Dictionary();
@ -333,7 +346,7 @@ Value SetExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
Value IndexerExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
{
return VMOps::Indexer(frame, m_Operand1->Evaluate(frame), m_Operand2->Evaluate(frame));
return VMOps::Indexer(frame, m_Indexer);
}
Value ImportExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const

View File

@ -213,6 +213,11 @@ public:
: DebuggableExpression(debugInfo), m_Variable(variable)
{ }
String GetVariable(void) const
{
return m_Variable;
}
protected:
virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
@ -532,15 +537,18 @@ private:
};
class I2_CONFIG_API IndexerExpression : public BinaryExpression
class I2_CONFIG_API IndexerExpression : public DebuggableExpression
{
public:
IndexerExpression(Expression *operand1, Expression *operand2, const DebugInfo& debugInfo = DebugInfo())
: BinaryExpression(operand1, operand2, debugInfo)
IndexerExpression(const std::vector<Expression *>& indexer, const DebugInfo& debugInfo = DebugInfo())
: DebuggableExpression(debugInfo), m_Indexer(indexer)
{ }
protected:
virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
private:
std::vector<Expression *> m_Indexer;
};
class I2_CONFIG_API ImportExpression : public DebuggableExpression

View File

@ -72,32 +72,19 @@ public:
return func->Invoke(arguments);
}
static inline Value Indexer(VMFrame& frame, const Value& value, const String& index)
static inline Value Indexer(VMFrame& frame, const std::vector<Expression *>& indexer)
{
if (value.IsObjectType<Dictionary>()) {
Dictionary::Ptr dict = value;
return dict->Get(index);
} else if (value.IsObjectType<Array>()) {
Array::Ptr arr = value;
return arr->Get(Convert::ToLong(index));
} else if (value.IsObject()) {
Object::Ptr object = value;
Type::Ptr type = object->GetReflectionType();
Value result = indexer[0]->Evaluate(frame);
if (!type)
BOOST_THROW_EXCEPTION(ConfigError("Dot operator applied to object which does not support reflection"));
for (int i = 1; i < indexer.size(); i++) {
if (result.IsEmpty())
return Empty;
int field = type->GetFieldId(index);
if (field == -1)
BOOST_THROW_EXCEPTION(ConfigError("Tried to access invalid property '" + index + "'"));
return object->GetField(field);
} else if (value.IsEmpty()) {
return Empty;
} else {
BOOST_THROW_EXCEPTION(ConfigError("Dot operator cannot be applied to type '" + value.GetTypeName() + "'"));
Value index = indexer[i]->Evaluate(frame);
result = GetField(result, index);
}
return result;
}
static inline Value NewFunction(VMFrame& frame, const String& name, const std::vector<String>& args,
@ -234,45 +221,62 @@ public:
if (dict)
return dict->Get(field);
else {
Type::Ptr type = context->GetReflectionType();
if (!type)
return Empty;
Array::Ptr arr = dynamic_pointer_cast<Array>(context);
int fid = type->GetFieldId(field);
if (fid == -1)
return Empty;
return context->GetField(fid);
if (arr) {
int index = Convert::ToLong(field);
return arr->Get(index);
}
Type::Ptr type = context->GetReflectionType();
if (!type)
return Empty;
int fid = type->GetFieldId(field);
if (fid == -1)
return Empty;
return context->GetField(fid);
}
static inline void SetField(const Object::Ptr& context, const String& field, const Value& value)
{
Dictionary::Ptr dict = dynamic_pointer_cast<Dictionary>(context);
if (dict)
if (dict) {
dict->Set(field, value);
else {
Type::Ptr type = context->GetReflectionType();
return;
}
if (!type)
BOOST_THROW_EXCEPTION(ConfigError("Cannot set field on object."));
Array::Ptr arr = dynamic_pointer_cast<Array>(context);
int fid = type->GetFieldId(field);
if (arr) {
int index = Convert::ToLong(field);
if (index >= arr->GetLength())
arr->Resize(index + 1);
arr->Set(index, value);
return;
}
if (fid == -1)
BOOST_THROW_EXCEPTION(ConfigError("Attribute '" + field + "' does not exist."));
Type::Ptr type = context->GetReflectionType();
try {
context->SetField(fid, value);
} catch (const boost::bad_lexical_cast&) {
BOOST_THROW_EXCEPTION(ConfigError("Attribute '" + field + "' cannot be set to value of type '" + value.GetTypeName() + "'"));
} catch (const std::bad_cast&) {
BOOST_THROW_EXCEPTION(ConfigError("Attribute '" + field + "' cannot be set to value of type '" + value.GetTypeName() + "'"));
}
if (!type)
BOOST_THROW_EXCEPTION(ConfigError("Cannot set field on object."));
int fid = type->GetFieldId(field);
if (fid == -1)
BOOST_THROW_EXCEPTION(ConfigError("Attribute '" + field + "' does not exist."));
try {
context->SetField(fid, value);
} catch (const boost::bad_lexical_cast&) {
BOOST_THROW_EXCEPTION(ConfigError("Attribute '" + field + "' cannot be set to value of type '" + value.GetTypeName() + "'"));
} catch (const std::bad_cast&) {
BOOST_THROW_EXCEPTION(ConfigError("Attribute '" + field + "' cannot be set to value of type '" + value.GetTypeName() + "'"));
}
}

View File

@ -208,10 +208,9 @@ BOOST_AUTO_TEST_CASE(advanced)
BOOST_CHECK(expr->Evaluate(frame) == 3);
delete expr;
/* Uncomment this once #7800 is fixed
expr = ConfigCompiler::CompileText("<test>", "local v = { a = 3}; v.a");
BOOST_CHECK(expr->Evaluate(frame) == 3);
delete expr;*/
delete expr;
expr = ConfigCompiler::CompileText("<test>", "a = 3 b = 3");
BOOST_CHECK(expr == NULL);