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

View File

@ -100,10 +100,7 @@ ConfigItem::Ptr ConfigItemBuilder::Compile(void)
Array::Ptr templateArray = new Array(); Array::Ptr templateArray = new Array();
templateArray->Add(m_Name); templateArray->Add(m_Name);
std::vector<Expression *> indexer; exprs.push_back(new SetExpression(MakeIndexer("templates"), OpSetAdd,
indexer.push_back(new LiteralExpression("templates"));
exprs.push_back(new SetExpression(indexer, OpSetAdd,
new LiteralExpression(templateArray), false, m_DebugInfo)); new LiteralExpression(templateArray), false, m_DebugInfo));
DictExpression *dexpr = new DictExpression(m_Expressions, 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 *> icinga::MakeIndexer(const String& index1)
{ {
std::vector<Expression *> result; std::vector<Expression *> result;
result.push_back(MakeLiteral(index1)); result.push_back(new VariableExpression(index1));
return result; return result;
} }
@ -270,7 +270,20 @@ Value SetExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
for (Array::SizeType i = 0; i < m_Indexer.size(); i++) { for (Array::SizeType i = 0; i < m_Indexer.size(); i++) {
Expression *indexExpr = m_Indexer[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) { if (psdhint) {
sdhint = psdhint->GetChild(tempindex); sdhint = psdhint->GetChild(tempindex);
@ -290,7 +303,7 @@ Value SetExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
break; break;
} }
object = VMOps::Indexer(frame, parent, tempindex); object = VMOps::GetField(parent, tempindex);
if (i != m_Indexer.size() - 1 && object.IsEmpty()) { if (i != m_Indexer.size() - 1 && object.IsEmpty()) {
object = new Dictionary(); object = new Dictionary();
@ -333,7 +346,7 @@ Value SetExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
Value IndexerExpression::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 Value ImportExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const

View File

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

View File

@ -72,32 +72,19 @@ public:
return func->Invoke(arguments); 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>()) { Value result = indexer[0]->Evaluate(frame);
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();
if (!type) for (int i = 1; i < indexer.size(); i++) {
BOOST_THROW_EXCEPTION(ConfigError("Dot operator applied to object which does not support reflection")); if (result.IsEmpty())
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; 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, static inline Value NewFunction(VMFrame& frame, const String& name, const std::vector<String>& args,
@ -234,7 +221,14 @@ public:
if (dict) if (dict)
return dict->Get(field); return dict->Get(field);
else {
Array::Ptr arr = dynamic_pointer_cast<Array>(context);
if (arr) {
int index = Convert::ToLong(field);
return arr->Get(index);
}
Type::Ptr type = context->GetReflectionType(); Type::Ptr type = context->GetReflectionType();
if (!type) if (!type)
@ -247,15 +241,26 @@ public:
return context->GetField(fid); return context->GetField(fid);
} }
}
static inline void SetField(const Object::Ptr& context, const String& field, const Value& value) static inline void SetField(const Object::Ptr& context, const String& field, const Value& value)
{ {
Dictionary::Ptr dict = dynamic_pointer_cast<Dictionary>(context); Dictionary::Ptr dict = dynamic_pointer_cast<Dictionary>(context);
if (dict) if (dict) {
dict->Set(field, value); dict->Set(field, value);
else { return;
}
Array::Ptr arr = dynamic_pointer_cast<Array>(context);
if (arr) {
int index = Convert::ToLong(field);
if (index >= arr->GetLength())
arr->Resize(index + 1);
arr->Set(index, value);
return;
}
Type::Ptr type = context->GetReflectionType(); Type::Ptr type = context->GetReflectionType();
if (!type) if (!type)
@ -274,7 +279,6 @@ public:
BOOST_THROW_EXCEPTION(ConfigError("Attribute '" + field + "' cannot be set to value of type '" + value.GetTypeName() + "'")); BOOST_THROW_EXCEPTION(ConfigError("Attribute '" + field + "' cannot be set to value of type '" + value.GetTypeName() + "'"));
} }
} }
}
private: private:
static inline Value FunctionWrapper(const std::vector<Value>& arguments, static inline Value FunctionWrapper(const std::vector<Value>& arguments,

View File

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