summaryrefslogtreecommitdiff
path: root/cpp/src
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src')
-rw-r--r--cpp/src/Transform/Grammar.y27
-rw-r--r--cpp/src/Transform/GrammarUtil.h16
-rw-r--r--cpp/src/Transform/Node.cpp125
-rw-r--r--cpp/src/Transform/Node.h57
-rw-r--r--cpp/src/Transform/Transformer.cpp147
5 files changed, 272 insertions, 100 deletions
diff --git a/cpp/src/Transform/Grammar.y b/cpp/src/Transform/Grammar.y
index 089d5078f84..11ef1e04220 100644
--- a/cpp/src/Transform/Grammar.y
+++ b/cpp/src/Transform/Grammar.y
@@ -203,11 +203,9 @@ unary
{
$$ = new DataNode(parseDataFactory->createNil(true));
}
-| identifier
+| entity
{
- IdentifierTokPtr listVal = IdentifierTokPtr::dynamicCast($1);
- assert(listVal);
- $$ = new IdentNode(listVal->v);
+ $$ = $1;
}
| constant
{
@@ -218,24 +216,29 @@ unary
;
// ----------------------------------------------------------------------
-identifier
+entity
// ----------------------------------------------------------------------
-: identifier '.' TOK_IDENTIFIER
+: entity TOK_LBRACKET expr TOK_RBRACKET
+{
+ EntityNodePtr entity = EntityNodePtr::dynamicCast($1);
+ assert(entity);
+ entity->append(new ElementNode($3));
+ $$ = $1;
+}
+| entity '.' TOK_IDENTIFIER
{
- IdentifierTokPtr listVal = IdentifierTokPtr::dynamicCast($1);
- assert(listVal);
StringTokPtr stringVal = StringTokPtr::dynamicCast($3);
assert(stringVal);
- listVal->v.push_back(stringVal->v);
+ EntityNodePtr entity = EntityNodePtr::dynamicCast($1);
+ assert(entity);
+ entity->append(new IdentNode(stringVal->v));
$$ = $1;
}
| TOK_IDENTIFIER
{
StringTokPtr stringVal = StringTokPtr::dynamicCast($1);
assert(stringVal);
- IdentifierTokPtr listVal = new IdentifierTok;
- listVal->v.push_back(stringVal->v);
- $$ = listVal;
+ $$ = new IdentNode(stringVal->v);
}
;
diff --git a/cpp/src/Transform/GrammarUtil.h b/cpp/src/Transform/GrammarUtil.h
index 9c0d4389491..8f5bcb02679 100644
--- a/cpp/src/Transform/GrammarUtil.h
+++ b/cpp/src/Transform/GrammarUtil.h
@@ -12,8 +12,8 @@
//
// **********************************************************************
-#ifndef FREEZE_GRAMMAR_UTIL_H
-#define FREEZE_GRAMMAR_UTIL_H
+#ifndef TRANSFORM_GRAMMAR_UTIL_H
+#define TRANSFORM_GRAMMAR_UTIL_H
#include <Transform/Node.h>
#include <Transform/Parser.h>
@@ -67,18 +67,6 @@ public:
};
// ----------------------------------------------------------------------
-// IdentifierTok
-// ----------------------------------------------------------------------
-
-class IdentifierTok : public Token
-{
-public:
-
- IdentifierTok() { }
- Identifier v;
-};
-
-// ----------------------------------------------------------------------
// BoolTok
// ----------------------------------------------------------------------
diff --git a/cpp/src/Transform/Node.cpp b/cpp/src/Transform/Node.cpp
index 0c4948f72dd..57b1f426751 100644
--- a/cpp/src/Transform/Node.cpp
+++ b/cpp/src/Transform/Node.cpp
@@ -16,17 +16,54 @@
using namespace std;
-ostream&
-operator<<(ostream& os, const Transform::Identifier& id)
+namespace Transform
+{
+
+class EntityNodePrinter : public EntityNodeVisitor
{
- for(Transform::Identifier::const_iterator p = id.begin(); p != id.end(); ++p)
+public:
+
+ EntityNodePrinter(ostream& os) :
+ _os(os), _first(true)
{
- if(p != id.begin())
+ }
+
+ virtual void
+ visitIdentifier(const std::string& name)
+ {
+ if(_first)
+ {
+ _first = false;
+ }
+ else
{
- os << '.';
+ _os << '.';
}
- os << *p;
+ _os << name;
+ }
+
+ virtual void
+ visitElement(const NodePtr& value)
+ {
+ assert(!_first);
+ _os << '[';
+ value->print(_os);
+ _os << ']';
}
+
+private:
+
+ ostream& _os;
+ bool _first;
+};
+
+} // End of namespace Transform
+
+ostream&
+operator<<(ostream& os, const Transform::EntityNodePtr& entity)
+{
+ Transform::EntityNodePrinter printer(os);
+ entity->visit(printer);
return os;
}
@@ -406,38 +443,96 @@ Transform::DataNode::print(ostream& os) const
}
//
-// IdentNode
+// EntityNodeVisitor
//
-Transform::IdentNode::IdentNode(const Identifier& value) :
- _value(value)
+Transform::EntityNodeVisitor::~EntityNodeVisitor()
{
}
+//
+// EntityNode
+//
Transform::DataPtr
-Transform::IdentNode::evaluate(SymbolTable& st)
+Transform::EntityNode::evaluate(SymbolTable& st)
{
- DataPtr result = st.getValue(_value);
+ DataPtr result = st.getValue(this);
if(!result)
{
ostringstream ostr;
print(ostr);
- throw EvaluateException(__FILE__, __LINE__, "unknown identifier `" + ostr.str() + "'");
+ throw EvaluateException(__FILE__, __LINE__, "unknown entity `" + ostr.str() + "'");
}
return result;
}
void
-Transform::IdentNode::print(ostream& os) const
+Transform::EntityNode::print(ostream& os) const
+{
+ EntityNodePrinter printer(os);
+ visit(printer);
+}
+
+void
+Transform::EntityNode::append(const EntityNodePtr& next)
+{
+ if(_next)
+ {
+ _next->append(next);
+ }
+ else
+ {
+ _next = next;
+ }
+}
+
+//
+// IdentNode
+//
+Transform::IdentNode::IdentNode(const string& value) :
+ _value(value)
{
- os << _value;
}
-Transform::Identifier
+string
Transform::IdentNode::getValue() const
{
return _value;
}
+void
+Transform::IdentNode::visit(EntityNodeVisitor& visitor) const
+{
+ visitor.visitIdentifier(_value);
+ if(_next)
+ {
+ _next->visit(visitor);
+ }
+}
+
+//
+// ElementNode
+//
+Transform::ElementNode::ElementNode(const NodePtr& value) :
+ _value(value)
+{
+}
+
+Transform::NodePtr
+Transform::ElementNode::getValue() const
+{
+ return _value;
+}
+
+void
+Transform::ElementNode::visit(EntityNodeVisitor& visitor) const
+{
+ visitor.visitElement(_value);
+ if(_next)
+ {
+ _next->visit(visitor);
+ }
+}
+
//
// ConstantNode
//
diff --git a/cpp/src/Transform/Node.h b/cpp/src/Transform/Node.h
index 860448b8017..54d0333eeb7 100644
--- a/cpp/src/Transform/Node.h
+++ b/cpp/src/Transform/Node.h
@@ -23,7 +23,8 @@ namespace Transform
class Node;
typedef IceUtil::Handle<Node> NodePtr;
-typedef std::vector<std::string> Identifier;
+class EntityNode;
+typedef IceUtil::Handle<EntityNode> EntityNodePtr;
class EvaluateException : public IceUtil::Exception
{
@@ -34,6 +35,7 @@ public:
virtual void ice_print(std::ostream&) const;
virtual IceUtil::Exception* ice_clone() const;
virtual void ice_throw() const;
+
std::string reason() const;
private:
@@ -47,7 +49,7 @@ public:
virtual ~SymbolTable();
- virtual DataPtr getValue(const Identifier&) const = 0;
+ virtual DataPtr getValue(const EntityNodePtr&) const = 0;
virtual DataPtr getConstantValue(const std::string&) const = 0;
};
@@ -126,24 +128,65 @@ private:
DataPtr _data;
};
-class IdentNode : public Node
+class EntityNodeVisitor
{
public:
- IdentNode(const Identifier&);
+ virtual ~EntityNodeVisitor();
+
+ virtual void visitIdentifier(const std::string&) = 0;
+ virtual void visitElement(const NodePtr&) = 0;
+};
+
+class EntityNode : public Node
+{
+public:
virtual DataPtr evaluate(SymbolTable&);
virtual void print(std::ostream&) const;
- Identifier getValue() const;
+ virtual void visit(EntityNodeVisitor&) const = 0;
+
+ void append(const EntityNodePtr&);
+
+protected:
+
+ EntityNodePtr _next;
+};
+
+class IdentNode : public EntityNode
+{
+public:
+
+ IdentNode(const std::string&);
+
+ virtual void visit(EntityNodeVisitor&) const;
+
+ std::string getValue() const;
private:
- Identifier _value;
+ std::string _value;
};
typedef IceUtil::Handle<IdentNode> IdentNodePtr;
+class ElementNode : public EntityNode
+{
+public:
+
+ ElementNode(const NodePtr&);
+
+ virtual void visit(EntityNodeVisitor&) const;
+
+ NodePtr getValue() const;
+
+private:
+
+ NodePtr _value;
+};
+typedef IceUtil::Handle<ElementNode> ElementNodePtr;
+
class ConstantNode : public Node
{
public:
@@ -161,6 +204,6 @@ private:
} // End of namespace Transform
-std::ostream& operator<<(std::ostream&, const Transform::Identifier&);
+std::ostream& operator<<(std::ostream&, const Transform::EntityNodePtr&);
#endif
diff --git a/cpp/src/Transform/Transformer.cpp b/cpp/src/Transform/Transformer.cpp
index f6f37a790f2..b0dccba100b 100644
--- a/cpp/src/Transform/Transformer.cpp
+++ b/cpp/src/Transform/Transformer.cpp
@@ -45,14 +45,34 @@ public:
TransformSymbolTable(const DataFactoryPtr&, const Slice::UnitPtr&, const Slice::UnitPtr&, const ErrorReporterPtr&,
TransformSymbolTable* = 0);
- virtual DataPtr getValue(const Identifier&) const;
+ virtual DataPtr getValue(const EntityNodePtr&) const;
virtual DataPtr getConstantValue(const string&) const;
void add(const string&, const DataPtr&);
private:
- DataPtr findValue(const string&);
+ DataPtr findValue(const string&) const;
+
+ class EntityVisitor : public EntityNodeVisitor
+ {
+ public:
+
+ EntityVisitor(TransformSymbolTable*);
+
+ virtual void visitIdentifier(const string&);
+ virtual void visitElement(const NodePtr&);
+
+ DataPtr getCurrent() const;
+
+ private:
+
+ TransformSymbolTable* _table;
+ DataPtr _current;
+ bool _error;
+ };
+
+ friend class EntityVisitor;
DataFactoryPtr _factory;
Slice::UnitPtr _old;
@@ -104,7 +124,7 @@ public:
private:
- IdentNodePtr _target;
+ EntityNodePtr _target;
NodePtr _key;
string _keyStr;
NodePtr _value;
@@ -125,7 +145,7 @@ public:
private:
- IdentNodePtr _target;
+ EntityNodePtr _target;
NodePtr _key;
string _keyStr;
};
@@ -214,7 +234,7 @@ public:
private:
- IdentNodePtr _target;
+ EntityNodePtr _target;
string _key;
string _value;
string _element;
@@ -373,42 +393,16 @@ Transform::TransformSymbolTable::TransformSymbolTable(const DataFactoryPtr& fact
}
Transform::DataPtr
-Transform::TransformSymbolTable::getValue(const Identifier& id) const
+Transform::TransformSymbolTable::getValue(const EntityNodePtr& entity) const
{
- DataPtr result;
-
- Identifier tmpid = id;
- string s = tmpid.front();
- tmpid.erase(tmpid.begin());
-
- DataMap::const_iterator p = _dataMap.find(s);
- if(p != _dataMap.end())
- {
- result = p->second;
- }
-
- if(!result && _parent)
- {
- result = _parent->findValue(s);
- }
-
+ EntityVisitor visitor(const_cast<TransformSymbolTable*>(this));
+ entity->visit(visitor);
+ DataPtr result = visitor.getCurrent();
if(!result)
{
ostringstream ostr;
- ostr << "invalid identifier `" << id << "'";
- throw TransformException(__FILE__, __LINE__, ostr.str());
- }
-
- for(Identifier::const_iterator p = tmpid.begin(); p != tmpid.end(); ++p)
- {
- DataPtr d = result->getMember(*p);
- if(!d)
- {
- ostringstream ostr;
- ostr << "invalid identifier `" << id << "'";
- throw TransformException(__FILE__, __LINE__, ostr.str());
- }
- result = d;
+ ostr << "invalid entity `" << entity << "'";
+ _errorReporter->error(ostr.str());
}
return result;
@@ -572,7 +566,7 @@ Transform::TransformSymbolTable::add(const string& name, const DataPtr& data)
}
Transform::DataPtr
-Transform::TransformSymbolTable::findValue(const string& name)
+Transform::TransformSymbolTable::findValue(const string& name) const
{
DataMap::const_iterator p = _dataMap.find(name);
if(p != _dataMap.end())
@@ -588,6 +582,55 @@ Transform::TransformSymbolTable::findValue(const string& name)
return 0;
}
+Transform::TransformSymbolTable::EntityVisitor::EntityVisitor(TransformSymbolTable* table) :
+ _table(table), _error(false)
+{
+}
+
+void
+Transform::TransformSymbolTable::EntityVisitor::visitIdentifier(const string& name)
+{
+ if(!_error)
+ {
+ if(!_current)
+ {
+ _current = _table->findValue(name);
+ }
+ else
+ {
+ _current = _current->getMember(name);
+ }
+
+ if(!_current)
+ {
+ _error = true;
+ }
+ }
+}
+
+void
+Transform::TransformSymbolTable::EntityVisitor::visitElement(const NodePtr& value)
+{
+ if(!_error)
+ {
+ assert(_current);
+
+ DataPtr val = value->evaluate(*_table);
+ _current = _current->getElement(val);
+
+ if(!_current)
+ {
+ _error = true;
+ }
+ }
+}
+
+Transform::DataPtr
+Transform::TransformSymbolTable::EntityVisitor::getCurrent() const
+{
+ return _current;
+}
+
//
// Descriptor
//
@@ -664,10 +707,10 @@ Transform::SetDescriptor::SetDescriptor(const DescriptorPtr& parent, int line, c
DescriptorErrorContext ctx(errorReporter(), "set", _line);
NodePtr node = parse(target);
- _target = IdentNodePtr::dynamicCast(node);
+ _target = EntityNodePtr::dynamicCast(node);
if(!_target)
{
- errorReporter()->error("`target' attribute is not an identifier: `" + target + "'");
+ errorReporter()->error("`target' attribute is not an entity: `" + target + "'");
}
if(!key.empty())
@@ -698,11 +741,11 @@ Transform::SetDescriptor::execute(TransformSymbolTable& sym, DataInterceptor& in
{
DescriptorErrorContext ctx(errorReporter(), "set", _line);
- DataPtr data = sym.getValue(_target->getValue());
+ DataPtr data = sym.getValue(_target);
if(data->readOnly())
{
ostringstream ostr;
- ostr << _target->getValue();
+ ostr << _target;
errorReporter()->error("target `" + ostr.str() + "' cannot be modified");
}
@@ -757,7 +800,7 @@ Transform::SetDescriptor::execute(TransformSymbolTable& sym, DataInterceptor& in
if(!dict)
{
ostringstream ostr;
- ostr << _target->getValue();
+ ostr << _target;
errorReporter()->error("target `" + ostr.str() + "' is not a dictionary");
}
dict->put(key, value, interceptor, _convert);
@@ -778,10 +821,10 @@ Transform::RemoveDescriptor::RemoveDescriptor(const DescriptorPtr& parent, int l
DescriptorErrorContext ctx(errorReporter(), "remove", _line);
NodePtr node = parse(target);
- _target = IdentNodePtr::dynamicCast(node);
+ _target = EntityNodePtr::dynamicCast(node);
if(!_target)
{
- errorReporter()->error("`target' attribute is not an identifier: `" + target + "'");
+ errorReporter()->error("`target' attribute is not an entity: `" + target + "'");
}
_key = parse(key);
@@ -814,11 +857,11 @@ Transform::RemoveDescriptor::execute(TransformSymbolTable& sym, DataInterceptor&
errorReporter()->error("evaluation of key `" + _keyStr + "' failed:\n" + ex.reason());
}
- DataPtr data = sym.getValue(_target->getValue());
+ DataPtr data = sym.getValue(_target);
if(data->readOnly())
{
ostringstream ostr;
- ostr << _target->getValue();
+ ostr << _target;
errorReporter()->error("target `" + ostr.str() + "' cannot be modified");
}
@@ -826,7 +869,7 @@ Transform::RemoveDescriptor::execute(TransformSymbolTable& sym, DataInterceptor&
if(!dict)
{
ostringstream ostr;
- ostr << _target->getValue();
+ ostr << _target;
errorReporter()->error("target `" + ostr.str() + "' is not a dictionary");
}
dict->remove(key);
@@ -1016,10 +1059,10 @@ Transform::IterateDescriptor::IterateDescriptor(const DescriptorPtr& parent, int
DescriptorErrorContext ctx(errorReporter(), "iterate", _line);
NodePtr node = parse(target);
- _target = IdentNodePtr::dynamicCast(node);
+ _target = EntityNodePtr::dynamicCast(node);
if(!_target)
{
- errorReporter()->error("`target' attribute is not an identifier: `" + target + "'");
+ errorReporter()->error("`target' attribute is not an entity: `" + target + "'");
}
}
@@ -1028,14 +1071,14 @@ Transform::IterateDescriptor::execute(TransformSymbolTable& sym, DataInterceptor
{
DescriptorErrorContext ctx(errorReporter(), "iterate", _line);
- DataPtr data = sym.getValue(_target->getValue());
+ DataPtr data = sym.getValue(_target);
DictionaryDataPtr dict = DictionaryDataPtr::dynamicCast(data);
SequenceDataPtr seq = SequenceDataPtr::dynamicCast(data);
if(!dict && !seq)
{
ostringstream ostr;
- ostr << _target->getValue();
+ ostr << _target;
errorReporter()->error("target `" + ostr.str() + "' is not a dictionary or sequence");
}