diff options
Diffstat (limited to 'cpp/src')
-rw-r--r-- | cpp/src/Transform/Grammar.y | 27 | ||||
-rw-r--r-- | cpp/src/Transform/GrammarUtil.h | 16 | ||||
-rw-r--r-- | cpp/src/Transform/Node.cpp | 125 | ||||
-rw-r--r-- | cpp/src/Transform/Node.h | 57 | ||||
-rw-r--r-- | cpp/src/Transform/Transformer.cpp | 147 |
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"); } |