diff options
author | John Wiegley <johnw@newartisans.com> | 2007-05-19 02:58:48 +0000 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2008-04-13 03:38:53 -0400 |
commit | bf2c8c0f486926b3c86f5f619b1d4e26cdd92188 (patch) | |
tree | 27c1fe7a41191a6c5d738c3c6c197626225e7045 | |
parent | b6ab7deb63d3e3e22ecd4d6c70c6249db2ba558c (diff) | |
download | fork-ledger-bf2c8c0f486926b3c86f5f619b1d4e26cdd92188.tar.gz fork-ledger-bf2c8c0f486926b3c86f5f619b1d4e26cdd92188.tar.bz2 fork-ledger-bf2c8c0f486926b3c86f5f619b1d4e26cdd92188.zip |
Everything is working again except for predicates.
-rw-r--r-- | src/main.cc | 22 | ||||
-rw-r--r-- | src/utils.cc | 4 | ||||
-rw-r--r-- | src/value.cc | 4 | ||||
-rw-r--r-- | src/value.h | 24 | ||||
-rw-r--r-- | src/xpath.cc | 141 | ||||
-rw-r--r-- | src/xpath.h | 113 |
6 files changed, 149 insertions, 159 deletions
diff --git a/src/main.cc b/src/main.cc index bca16cb4..0b29e253 100644 --- a/src/main.cc +++ b/src/main.cc @@ -145,15 +145,27 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[], xml::xpath_t expr(*arg); xml::document_t temp(xml::LEDGER_NODE); - xml::xpath_t::document_scope_t doc_scope(report, temp); + xml::xpath_t::context_scope_t doc_scope(report, temp); IF_INFO() { std::cout << "Value expression tree:" << std::endl; expr.dump(std::cout); std::cout << std::endl; + std::cout << "Value expression parsed was:" << std::endl; expr.print(std::cout, doc_scope); std::cout << std::endl << std::endl; + + expr.compile(doc_scope); + + std::cout << "Value expression after compiling:" << std::endl; + expr.dump(std::cout); + std::cout << std::endl; + + std::cout << "Value expression is now:" << std::endl; + expr.print(std::cout, doc_scope); + std::cout << std::endl << std::endl; + std::cout << "Result of calculation: "; } @@ -248,7 +260,7 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[], // Are we handling the expr commands? Do so now. - xml::xpath_t::document_scope_t doc_scope(report, xml_document); + xml::xpath_t::context_scope_t doc_scope(report, xml_document); if (verb == "expr") { xml::xpath_t expr(*arg); @@ -268,14 +280,13 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[], return 0; } else if (verb == "xpath") { - std::cout << "XPath parsed:" << std::endl; + std::cout << "XPath parsed:"; xml::xpath_t xpath(*arg); xpath.print(*out, doc_scope); *out << std::endl; -#if 0 - foreach (const value_t& value, xpath.find_all(xml_document, report)) { + foreach (const value_t& value, xpath.find_all(doc_scope)) { if (value.is_xml_node()) { value.as_xml_node()->print(std::cout); } else { @@ -283,7 +294,6 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[], } std::cout << std::endl; } -#endif return 0; } diff --git a/src/utils.cc b/src/utils.cc index bcbffdca..e9c41cc9 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -284,7 +284,7 @@ void trace_ctor_func(void * ptr, const char * cls_name, const char * args, std::strcat(name, args); std::strcat(name, ")"); - DEBUG("verify.memory", "TRACE_CTOR " << ptr << " " << name); + DEBUG("memory.debug", "TRACE_CTOR " << ptr << " " << name); live_objects->insert (live_objects_map::value_type(ptr, allocation_pair(cls_name, cls_size))); @@ -303,7 +303,7 @@ void trace_dtor_func(void * ptr, const char * cls_name, std::size_t cls_size) if (! live_objects) return; - DEBUG("ledger.trace.debug", "TRACE_DTOR " << ptr << " " << cls_name); + DEBUG("memory.debug", "TRACE_DTOR " << ptr << " " << cls_name); live_objects_map::iterator i = live_objects->find(ptr); VERIFY(i != live_objects->end()); diff --git a/src/value.cc b/src/value.cc index 908de161..88b8949e 100644 --- a/src/value.cc +++ b/src/value.cc @@ -1371,6 +1371,7 @@ value_t value_t::strip_annotations(const bool keep_price, const bool keep_tag) const { switch (type()) { + case VOID: case BOOLEAN: case INTEGER: case DATETIME: @@ -1551,6 +1552,9 @@ void value_t::print(std::ostream& out, const int first_width, std::ostream& operator<<(std::ostream& out, const value_t& val) { switch (val.type()) { + case value_t::VOID: + out << "VOID"; + break; case value_t::BOOLEAN: out << (val.as_boolean() ? "true" : "false"); break; diff --git a/src/value.h b/src/value.h index c9281121..8fa3f8c9 100644 --- a/src/value.h +++ b/src/value.h @@ -216,12 +216,12 @@ public: TRACE_CTOR(value_t, "const sequence_t&"); set_sequence(val); } - value_t(xml::node_t * xml_node) { + value_t(xml::node_t * item) { TRACE_CTOR(value_t, "xml::node_t *"); - set_xml_node(xml_node); + set_xml_node(item); } template <typename T> - value_t(T * item) { + explicit value_t(T * item) { TRACE_CTOR(value_t, "T *"); set_pointer(item); } @@ -230,9 +230,8 @@ public: } value_t& operator=(const value_t& val) { - if (this == &val || storage == val.storage) - return *this; - storage = val.storage; + if (! (this == &val || storage == val.storage)) + storage = val.storage; return *this; } @@ -537,11 +536,14 @@ public: if (! is_sequence()) in_place_cast(SEQUENCE); - if (! val.is_sequence()) - as_sequence_lval().push_back(val); - else - std::copy(val.as_sequence().begin(), val.as_sequence().end(), - as_sequence_lval().end()); + value_t::sequence_t& seq(as_sequence_lval()); + if (! val.is_sequence()) { + if (! val.is_null()) + seq.push_back(val); + } else { + const value_t::sequence_t& val_seq(val.as_sequence()); + std::copy(val_seq.begin(), val_seq.end(), back_inserter(seq)); + } } } diff --git a/src/xpath.cc b/src/xpath.cc index 5ff5555d..986925e9 100644 --- a/src/xpath.cc +++ b/src/xpath.cc @@ -414,7 +414,6 @@ void xpath_t::symbol_scope_t::define(const string& name, ptr_op_t def) if (! result.second) { symbol_map::iterator i = symbols.find(name); assert(i != symbols.end()); - (*i).second->release(); symbols.erase(i); std::pair<symbol_map::iterator, bool> result2 @@ -423,7 +422,6 @@ void xpath_t::symbol_scope_t::define(const string& name, ptr_op_t def) throw_(compile_error, "Redefinition of '" << name << "' in same scope"); } - def->acquire(); } void xpath_t::scope_t::define(const string& name, const value_t& val) { @@ -432,21 +430,21 @@ void xpath_t::scope_t::define(const string& name, const value_t& val) { value_t xpath_fn_last(xpath_t::call_scope_t& scope) { - xpath_t::context_scope_t& context(FIND_SCOPE(xpath_t::context_scope_t, scope)); + xpath_t::context_scope_t& context(CONTEXT_SCOPE(scope)); return context.size(); } value_t xpath_fn_position(xpath_t::call_scope_t& scope) { - xpath_t::context_scope_t& context(FIND_SCOPE(xpath_t::context_scope_t, scope)); + xpath_t::context_scope_t& context(CONTEXT_SCOPE(scope)); return context.index(); } value_t xpath_fn_text(xpath_t::call_scope_t& scope) { - xpath_t::context_scope_t& context(FIND_SCOPE(xpath_t::context_scope_t, scope)); + xpath_t::context_scope_t& context(CONTEXT_SCOPE(scope)); return value_t(context.xml_node().to_value().to_string(), true); } @@ -971,6 +969,9 @@ xpath_t::ptr_op_t xpath_t::op_t::compile(scope_t& scope) break; } + if (kind < TERMINALS) + return this; + ptr_op_t lhs(left()->compile(scope)); ptr_op_t rhs(right() ? right()->compile(scope) : ptr_op_t()); @@ -987,16 +988,46 @@ xpath_t::ptr_op_t xpath_t::op_t::compile(scope_t& scope) value_t xpath_t::op_t::current_value(scope_t& scope) { - xpath_t::context_scope_t& context(FIND_SCOPE(xpath_t::context_scope_t, scope)); + xpath_t::context_scope_t& context(CONTEXT_SCOPE(scope)); return context.value(); } node_t& xpath_t::op_t::current_xml_node(scope_t& scope) { - xpath_t::context_scope_t& context(FIND_SCOPE(xpath_t::context_scope_t, scope)); + xpath_t::context_scope_t& context(CONTEXT_SCOPE(scope)); return context.xml_node(); } +namespace { + value_t search_nodes(value_t nodes, xpath_t::ptr_op_t find_op, + xpath_t::scope_t& scope, bool recurse) + { + value_t node_sequence = nodes.to_sequence(); + value_t result; + + foreach (value_t& node_value, node_sequence.as_sequence_lval()) { + if (! node_value.is_xml_node()) + throw_(xpath_t::calc_error, + "Application of / operator to non-node value '" + << node_value << "'"); + + node_t& node(*node_value.as_xml_node()); + xpath_t::context_scope_t node_scope(scope, node, node_sequence); + + result.push_back(find_op->calc(node_scope)); + + if (recurse && node.is_parent_node()) { + value_t children; + foreach (node_t * child, node.as_parent_node()) + children.push_back(child); + + result.push_back(search_nodes(children, find_op, scope, recurse)); + } + } + return result; + } +} + value_t xpath_t::op_t::calc(scope_t& scope) { switch (kind) { @@ -1021,7 +1052,8 @@ value_t xpath_t::op_t::calc(scope_t& scope) case O_CALL: { call_scope_t call_args(scope); - call_args.set_args(right()->calc(scope)); + if (right()) + call_args.set_args(right()->calc(scope)); ptr_op_t func = left(); string name; @@ -1045,36 +1077,13 @@ value_t xpath_t::op_t::calc(scope_t& scope) if (as_long() >= 0 && as_long() < args.size()) return args[as_long()]; else - throw_(compile_error, "Reference to a non-existing argument"); + throw_(calc_error, "Reference to a non-existing argument"); break; } case O_FIND: - case O_RFIND: { - value_t result; - - if (value_t items = left()->calc(scope)) { - value_t sequence = items.to_sequence(); - foreach (value_t& item, sequence.as_sequence_lval()) { - if (item.is_xml_node()) { - node_t& node(*item.as_xml_node()); - node_scope_t node_scope(scope, node); - - result.push_back(right()->calc(node_scope)); -#if 0 - // jww (2007-05-17): How do I get it to recurse down? I'll - // have to use a recursive helper function. - if (kind == O_RFIND && node.is_parent_node()) - foreach (node_t * child, node.as_parent_node()) - walk_elements(element->right(), scope, *child, NULL, func); -#endif - } else { - throw_(compile_error, "Application of / operator to non-node value"); - } - } - } - return result; - } + case O_RFIND: + return search_nodes(left()->calc(scope), right(), scope, kind == O_RFIND); case NODE_ID: switch (as_name()) { @@ -1094,7 +1103,7 @@ value_t xpath_t::op_t::calc(scope_t& scope) case document_t::ALL: { node_t& current_node(current_xml_node(scope)); if (! current_node.is_parent_node()) - throw_(compile_error, "Referencing child nodes from a non-parent value"); + throw_(calc_error, "Referencing child nodes from a non-parent value"); value_t result; foreach (node_t * child, current_node.as_parent_node()) @@ -1109,20 +1118,14 @@ value_t xpath_t::op_t::calc(scope_t& scope) case NODE_NAME: { node_t& current_node(current_xml_node(scope)); - if (current_node.is_parent_node()) { bool have_name_id = kind == NODE_ID; value_t result; - foreach (node_t * child, current_node.as_parent_node()) { if (( have_name_id && as_name() == child->name_id()) || (! have_name_id && as_string() == child->name())) result.push_back(child); -#if 0 - else if (recurse) - /* ... */; -#endif } return result; } @@ -1130,30 +1133,36 @@ value_t xpath_t::op_t::calc(scope_t& scope) } case O_PRED: { -#if 0 - predicate_scope_t predicate_scope(scope, right()); - return left()->calc(predicate_scope); -#endif - break; + value_t values = left()->calc(scope).to_sequence(); + value_t result; + + std::size_t index = 0; + foreach (const value_t& value, values.as_sequence()) { + xpath_t::context_scope_t value_scope(scope, value); + + value_t predval = right()->calc(value_scope); + if ((predval.is_long() && + predval.as_long() == (long)index + 1) || + predval.to_boolean()) + result.push_back(value); + + index++; + } + return result; } case ATTR_ID: case ATTR_NAME: { - context_scope_t& context(scope.find_scope<context_scope_t>()); - - if (context.type() != scope_t::NODE_SCOPE) - throw_(calc_error, "Looking up attribute in a non-node context"); - - node_scope_t& node_scope(downcast<node_scope_t>(context)); + node_t& current_node(current_xml_node(scope)); if (optional<const string&> value = - kind == ATTR_ID ? node_scope.xml_node().get_attr(as_long()) : - node_scope.xml_node().get_attr(as_string())) + kind == ATTR_ID ? current_node.get_attr(as_long()) : + current_node.get_attr(as_string())) return value_t(*value, true); else throw_(calc_error, "Attribute '" << (kind == ATTR_ID ? - *node_scope.xml_node().document().lookup_name(as_long()) : + *current_node.document().lookup_name(as_long()) : as_string().c_str()) << "' was not found"); break; @@ -1243,6 +1252,8 @@ bool xpath_t::op_t::print(std::ostream& out, print_context_t& context) const out << "0"; break; case value_t::INTEGER: + out << value; + break; case value_t::AMOUNT: if (! context.relaxed) out << '{'; @@ -1278,16 +1289,9 @@ bool xpath_t::op_t::print(std::ostream& out, print_context_t& context) const out << '@'; // fall through... case NODE_ID: { - context_scope_t& context_scope(context.scope.find_scope<context_scope_t>()); - - if (context_scope.type() != scope_t::NODE_SCOPE) - throw_(calc_error, "Looking up node name in a non-node context"); - - node_scope_t& node_scope(downcast<node_scope_t>(context_scope)); - - optional<const char *> name = - node_scope.xml_node().document().lookup_name(as_name()); - if (name) + context_scope_t& node_scope(CONTEXT_SCOPE(context.scope)); + if (optional<const char *> name = + node_scope.xml_node().document().lookup_name(as_name())) out << *name; else out << '#' << as_name(); @@ -1308,7 +1312,7 @@ bool xpath_t::op_t::print(std::ostream& out, print_context_t& context) const break; case FUNCTION: - out << as_function(); + out << '<FUNCTION>'; break; case ARG_INDEX: @@ -1544,7 +1548,7 @@ void xpath_t::op_t::dump(std::ostream& out, const int depth) const break; case FUNCTION: - out << "FUNCTION - " << as_function(); + out << "FUNCTION"; break; case O_CALL: out << "O_CALL"; break; @@ -1603,8 +1607,7 @@ value_t xml_command(xml::xpath_t::call_scope_t& args) value_t ostream = args.resolve("ostream"); std::ostream& outs(ostream.as_ref_lval<std::ostream>()); - xml::xpath_t::node_scope_t& node_context - (FIND_SCOPE(xml::xpath_t::node_scope_t, args)); + xml::xpath_t::context_scope_t& node_context(CONTEXT_SCOPE(args)); node_context.xml_node().print(outs); return true; diff --git a/src/xpath.h b/src/xpath.h index a34c41d0..d1a94861 100644 --- a/src/xpath.h +++ b/src/xpath.h @@ -69,8 +69,9 @@ public: SYMBOL_SCOPE, CALL_SCOPE, CONTEXT_SCOPE, - NODE_SCOPE, +#if 0 PREDICATE_SCOPE +#endif } type_; explicit scope_t(type_t _type) : type_(_type) { @@ -213,11 +214,30 @@ public: explicit context_scope_t(scope_t& _parent, const value_t& _element, const optional<value_t>& _sequence = none) - : child_scope_t(_parent, CONTEXT_SCOPE), - element(_element), sequence(_sequence) + : child_scope_t(_parent, CONTEXT_SCOPE) { TRACE_CTOR(xpath_t::context_scope_t, "scope_t&, const value_t&, const optional<value_t>&"); + set_context(_element, _sequence); + } + explicit context_scope_t(scope_t& _parent, + node_t& _element, + const optional<value_t>& _sequence = none) + : child_scope_t(_parent, CONTEXT_SCOPE) + { + TRACE_CTOR(xpath_t::context_scope_t, + "scope_t&, const value_t&, const optional<value_t>&"); + set_context(value_t(&_element), _sequence); + } + virtual ~context_scope_t() { + TRACE_DTOR(xpath_t::context_scope_t); + } + + void set_context(const value_t& _element, + const optional<value_t>& _sequence) { + element = _element; + sequence = _sequence; + assert(! element.is_sequence()); if (DO_VERIFY() && sequence) { @@ -230,9 +250,6 @@ public: } } } - virtual ~context_scope_t() { - TRACE_DTOR(xpath_t::context_scope_t); - } const std::size_t index() const { if (! sequence) { @@ -262,21 +279,7 @@ public: } }; - class node_scope_t : public context_scope_t - { - public: - node_scope_t(scope_t& _parent, node_t& _node) - : context_scope_t(_parent, &_node) { - TRACE_CTOR(xpath_t::node_scope_t, "scope_t&, node_t&"); - type_ = NODE_SCOPE; - } - virtual ~node_scope_t() { - TRACE_DTOR(xpath_t::node_scope_t); - } - }; - - typedef node_scope_t document_scope_t; - +#if 0 class predicate_scope_t : public child_scope_t { public: @@ -305,6 +308,7 @@ public: return predicate->calc(context_scope).to_boolean(); } }; +#endif #define XPATH_PARSE_NORMAL 0x00 #define XPATH_PARSE_PARTIAL 0x01 @@ -402,41 +406,27 @@ private: }; public: -#if 0 class path_iterator_t { - typedef NodeType * pointer; - typedef NodeType& reference; + typedef node_t * pointer; + typedef node_t& reference; - path_t path; - node_t& start; + xpath_t& path_expr; scope_t& scope; mutable value_t::sequence_t sequence; mutable bool searched; - struct node_appender_t { - value_t::sequence_t& sequence; - node_appender_t(value_t::sequence_t& _sequence) - : sequence(_sequence) {} - void operator()(const value_t& node) { - sequence.push_back(node); - } - }; - public: typedef value_t::sequence_t::iterator iterator; typedef value_t::sequence_t::const_iterator const_iterator; - path_iterator_t(const xpath_t& path_expr, - node_t& _start, scope_t& _scope) - : path(path_expr), start(_start), scope(_scope), - searched(false) { - } + path_iterator_t(xpath_t& _path_expr, scope_t& _scope) + : path_expr(_path_expr), scope(_scope), searched(false) {} iterator begin() { if (! searched) { - path.visit(start, scope, node_appender_t(sequence)); + sequence = path_expr.calc(scope).to_sequence(); searched = true; } return sequence.begin(); @@ -448,7 +438,6 @@ public: iterator end() { return sequence.end(); } const_iterator end() const { return sequence.end(); } }; -#endif struct op_t : public noncopyable { @@ -857,24 +846,9 @@ public: return xpath_t(_expr).calc(scope); } -#if 0 - path_iterator_t<node_t> - find_all(node_t& start, scope_t& scope) { - return path_iterator_t<node_t>(*this, start, scope); + path_iterator_t find_all(scope_t& scope) { + return path_iterator_t(*this, scope); } - path_iterator_t<const node_t> - find_all(const node_t& start, scope_t& scope) { - return path_iterator_t<const node_t>(*this, start, scope); - } - - void visit(node_t& start, scope_t& scope, const path_t::visitor_t& func) { - path_t(*this).visit(start, scope, func); - } - void visit(const node_t& start, scope_t& scope, const - path_t::visitor_t& func) { - path_t(*this).visit(start, scope, func); - } -#endif void print(std::ostream& out, scope_t& scope) const { op_t::print_context_t context(scope); @@ -890,10 +864,8 @@ public: inline xpath_t::ptr_op_t xpath_t::op_t::new_node(kind_t _kind, ptr_op_t _left, ptr_op_t _right) { ptr_op_t node(new op_t(_kind)); - if (_left) - node->set_left(_left); - if (_right) - node->set_right(_right); + node->set_left(_left); + node->set_right(_right); return node; } @@ -935,17 +907,16 @@ xpath_t::scope_t::find_scope<xpath_t::context_scope_t>(bool skip_this) { return downcast<context_scope_t>(*scope); } -template<> -inline xpath_t::node_scope_t& -xpath_t::scope_t::find_scope<xpath_t::node_scope_t>(bool skip_this) { - optional<scope_t&> scope = find_scope(NODE_SCOPE, skip_this); - assert(scope); - return downcast<node_scope_t>(*scope); -} - #define FIND_SCOPE(scope_type, scope_ref) \ downcast<xml::xpath_t::scope_t>(scope_ref).find_scope<scope_type>() +#define CALL_SCOPE(scope_ref) \ + FIND_SCOPE(xml::xpath_t::call_scope_t, scope_ref) +#define SYMBOL_SCOPE(scope_ref) \ + FIND_SCOPE(xml::xpath_t::symbol_scope_t, scope_ref) +#define CONTEXT_SCOPE(scope_ref) \ + FIND_SCOPE(xml::xpath_t::context_scope_t, scope_ref) + } // namespace xml value_t xml_command(xml::xpath_t::call_scope_t& args); |