mirror of
https://github.com/jezhiggins/arabica
synced 2025-01-17 18:12:04 +01:00
parameterised XPath class
This commit is contained in:
parent
65675f5d2f
commit
df816c1b05
11 changed files with 519 additions and 496 deletions
|
@ -233,9 +233,6 @@
|
||||||
<File
|
<File
|
||||||
RelativePath=".\helpers\PropertyNames.h">
|
RelativePath=".\helpers\PropertyNames.h">
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath=".\helpers\StringAdaptor.h">
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath=".\helpers\XMLBaseSupport.h">
|
RelativePath=".\helpers\XMLBaseSupport.h">
|
||||||
</File>
|
</File>
|
||||||
|
@ -377,6 +374,9 @@
|
||||||
<File
|
<File
|
||||||
RelativePath="..\Utils\socket_stream.h">
|
RelativePath="..\Utils\socket_stream.h">
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\Utils\StringAdaptor.h">
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\XML\UnicodeCharacters.h">
|
RelativePath="..\XML\UnicodeCharacters.h">
|
||||||
</File>
|
</File>
|
||||||
|
@ -685,9 +685,6 @@
|
||||||
<File
|
<File
|
||||||
RelativePath="..\Dom\Simple\ProcessingInstructionImpl.h">
|
RelativePath="..\Dom\Simple\ProcessingInstructionImpl.h">
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath="..\Dom\Simple\StringAdaptor.h">
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath="..\Dom\Simple\TextImpl.h">
|
RelativePath="..\Dom\Simple\TextImpl.h">
|
||||||
</File>
|
</File>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
/* To parameterise
|
/* To parameterise
|
||||||
|
|
||||||
DONE - xpath_arithmetic.hpp
|
DONE - xpath_arithmetic.hpp
|
||||||
xpath_ast.hpp
|
DONE - xpath_ast.hpp
|
||||||
DONE - xpath_ast_ids.hpp
|
DONE - xpath_ast_ids.hpp
|
||||||
xpath_axis_enumerator.hpp
|
xpath_axis_enumerator.hpp
|
||||||
xpath_compile_context.hpp
|
xpath_compile_context.hpp
|
||||||
|
@ -34,6 +34,10 @@ xpath_step.hpp
|
||||||
xpath_union.hpp
|
xpath_union.hpp
|
||||||
xpath_value.hpp
|
xpath_value.hpp
|
||||||
xpath_variable.hpp
|
xpath_variable.hpp
|
||||||
xpath_variable_resolver.hpp
|
DONE - xpath_variable_resolver.hpp
|
||||||
|
|
||||||
|
xpath_axis_enumerator.cpp
|
||||||
|
xpath_object.cpp
|
||||||
|
DONE - xpath_parser.cpp
|
||||||
*/
|
*/
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -18,10 +18,6 @@ typedef boost::spirit::tree_parse_info<str_iter_t> tree_info_t;
|
||||||
long getNodeId(node_iter_t const& node);
|
long getNodeId(node_iter_t const& node);
|
||||||
node_iter_t& skipWhitespace(node_iter_t& node);
|
node_iter_t& skipWhitespace(node_iter_t& node);
|
||||||
|
|
||||||
template<class string_type> class XPathExpression;
|
|
||||||
class CompilationContext;
|
|
||||||
XPathExpression<std::string>* compile_expression(node_iter_t const& i, CompilationContext& context);
|
|
||||||
|
|
||||||
} // namespace XPath
|
} // namespace XPath
|
||||||
} // namespace Arabica
|
} // namespace Arabica
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -6,14 +6,15 @@ namespace Arabica
|
||||||
namespace XPath
|
namespace XPath
|
||||||
{
|
{
|
||||||
|
|
||||||
class XPath;
|
template<class string_type, class string_adaptor = Arabica::default_string_adaptor<string_type> > class XPath;
|
||||||
class NamespaceContext;
|
class NamespaceContext;
|
||||||
class FunctionResolver;
|
class FunctionResolver;
|
||||||
|
|
||||||
|
template<class string_type>
|
||||||
class CompilationContext
|
class CompilationContext
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CompilationContext(const XPath& xpathCompiler,
|
CompilationContext(const XPath<string_type>& xpathCompiler,
|
||||||
const NamespaceContext& namespaceContext,
|
const NamespaceContext& namespaceContext,
|
||||||
const FunctionResolver& functionResolver) :
|
const FunctionResolver& functionResolver) :
|
||||||
xpath_(xpathCompiler),
|
xpath_(xpathCompiler),
|
||||||
|
@ -22,12 +23,12 @@ public:
|
||||||
{
|
{
|
||||||
} // CompilationContext
|
} // CompilationContext
|
||||||
|
|
||||||
const XPath& xpath() const { return xpath_; }
|
const XPath<string_type>& xpath() const { return xpath_; }
|
||||||
const NamespaceContext& namespaceContext() const { return namespaceContext_; }
|
const NamespaceContext& namespaceContext() const { return namespaceContext_; }
|
||||||
const FunctionResolver& functionResolver() const { return functionResolver_; }
|
const FunctionResolver& functionResolver() const { return functionResolver_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const XPath& xpath_;
|
const XPath<string_type>& xpath_;
|
||||||
const NamespaceContext& namespaceContext_;
|
const NamespaceContext& namespaceContext_;
|
||||||
const FunctionResolver& functionResolver_;
|
const FunctionResolver& functionResolver_;
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ public:
|
||||||
|
|
||||||
static FunctionHolder* createFunction(const std::string& name,
|
static FunctionHolder* createFunction(const std::string& name,
|
||||||
const std::vector<XPathExpressionPtr<std::string> >& argExprs,
|
const std::vector<XPathExpressionPtr<std::string> >& argExprs,
|
||||||
const CompilationContext& context)
|
const CompilationContext<std::string>& context)
|
||||||
{
|
{
|
||||||
for(const NamedFunction* fn = FunctionLookupTable; fn->name != 0; ++fn)
|
for(const NamedFunction* fn = FunctionLookupTable; fn->name != 0; ++fn)
|
||||||
if(name == fn->name)
|
if(name == fn->name)
|
||||||
|
|
|
@ -5,7 +5,9 @@
|
||||||
#include <boost/spirit/tree/ast.hpp>
|
#include <boost/spirit/tree/ast.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <map>
|
||||||
#include "xpath_object.hpp"
|
#include "xpath_object.hpp"
|
||||||
|
#include "xpath_expression.hpp"
|
||||||
#include "xpath_ast.hpp"
|
#include "xpath_ast.hpp"
|
||||||
#include "xpath_grammar.hpp"
|
#include "xpath_grammar.hpp"
|
||||||
#include "xpath_namespace_context.hpp"
|
#include "xpath_namespace_context.hpp"
|
||||||
|
@ -36,29 +38,59 @@ public:
|
||||||
UnsupportedException(const std::string& thing) : std::runtime_error("Sorry, haven't implemented '" + thing + "' yet") { }
|
UnsupportedException(const std::string& thing) : std::runtime_error("Sorry, haven't implemented '" + thing + "' yet") { }
|
||||||
}; // class UnsupportedException
|
}; // class UnsupportedException
|
||||||
|
|
||||||
class CompilationContext;
|
template<class string_type> class CompilationContext;
|
||||||
|
|
||||||
|
class StepExpression;
|
||||||
|
typedef std::vector<StepExpression*> StepList;
|
||||||
|
|
||||||
|
template<class string_type, class string_adaptor = Arabica::default_string_adaptor<string_type> >
|
||||||
class XPath
|
class XPath
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
XPath();
|
XPath()
|
||||||
~XPath();
|
{
|
||||||
|
resetNamespaceContext();
|
||||||
|
resetVariableResolver();
|
||||||
|
resetFunctionResolver();
|
||||||
|
} // XPath
|
||||||
|
|
||||||
XPathExpressionPtr<std::string> compile(const std::string& xpath) const;
|
~XPath()
|
||||||
XPathExpressionPtr<std::string> compile_expr(const std::string& xpath) const;
|
{
|
||||||
|
} // ~XPath
|
||||||
|
|
||||||
XPathValuePtr<std::string> evaluate(const std::string& xpath, const DOM::Node<std::string>& context) const;
|
XPathExpressionPtr<string_type> compile(const string_type& xpath) const
|
||||||
XPathValuePtr<std::string> evaluate_expr(const std::string& xpath, const DOM::Node<std::string>& context) const;
|
{
|
||||||
|
return do_compile(xpath, &XPath::parse_xpath);
|
||||||
|
} // compile
|
||||||
|
|
||||||
|
XPathExpressionPtr<string_type> compile_expr(const string_type& xpath) const
|
||||||
|
{
|
||||||
|
return do_compile(xpath, &XPath::parse_xpath_expr);
|
||||||
|
} // compile
|
||||||
|
|
||||||
|
XPathValuePtr<string_type> evaluate(const string_type& xpath, const DOM::Node<string_type>& context) const
|
||||||
|
{
|
||||||
|
ExecutionContext executionContext;
|
||||||
|
executionContext.setVariableResolver(getVariableResolver());
|
||||||
|
return compile(xpath)->evaluate(context, executionContext);
|
||||||
|
} // evaluate
|
||||||
|
|
||||||
|
XPathValuePtr<string_type> evaluate_expr(const string_type& xpath, const DOM::Node<string_type>& context) const
|
||||||
|
{
|
||||||
|
ExecutionContext executionContext;
|
||||||
|
executionContext.setVariableResolver(getVariableResolver());
|
||||||
|
return compile_expr(xpath)->evaluate(context, executionContext);
|
||||||
|
} // evaluate_expr
|
||||||
|
|
||||||
void setNamespaceContext(const NamespaceContext& namespaceContext) { namespaceContext_.set(namespaceContext); }
|
void setNamespaceContext(const NamespaceContext& namespaceContext) { namespaceContext_.set(namespaceContext); }
|
||||||
void setNamespaceContext(NamespaceContextPtr namespaceContext) { namespaceContext_.set(namespaceContext); }
|
void setNamespaceContext(NamespaceContextPtr namespaceContext) { namespaceContext_.set(namespaceContext); }
|
||||||
const NamespaceContext& getNamespaceContext() const { return namespaceContext_.get(); }
|
const NamespaceContext& getNamespaceContext() const { return namespaceContext_.get(); }
|
||||||
void resetNamespaceContext() { namespaceContext_.set(NamespaceContextPtr(new NullNamespaceContext())); }
|
void resetNamespaceContext() { namespaceContext_.set(NamespaceContextPtr(new NullNamespaceContext())); }
|
||||||
|
|
||||||
void setVariableResolver(const VariableResolver<std::string>& variableResolver) { variableResolver_.set(variableResolver); }
|
void setVariableResolver(const VariableResolver<string_type>& variableResolver) { variableResolver_.set(variableResolver); }
|
||||||
void setVariableResolver(VariableResolverPtr<std::string> variableResolver) { variableResolver_.set(variableResolver); }
|
void setVariableResolver(VariableResolverPtr<string_type> variableResolver) { variableResolver_.set(variableResolver); }
|
||||||
const VariableResolver<std::string>& getVariableResolver() const { return variableResolver_.get(); }
|
const VariableResolver<string_type>& getVariableResolver() const { return variableResolver_.get(); }
|
||||||
void resetVariableResolver() { variableResolver_.set(VariableResolverPtr<std::string>(new NullVariableResolver<std::string>())); }
|
void resetVariableResolver() { variableResolver_.set(VariableResolverPtr<string_type>(new NullVariableResolver<string_type>())); }
|
||||||
|
|
||||||
void setFunctionResolver(const FunctionResolver& functionResolver) { functionResolver_.set(functionResolver); }
|
void setFunctionResolver(const FunctionResolver& functionResolver) { functionResolver_.set(functionResolver); }
|
||||||
void setFunctionResolver(FunctionResolverPtr functionResolver) { functionResolver_.set(functionResolver); }
|
void setFunctionResolver(FunctionResolverPtr functionResolver) { functionResolver_.set(functionResolver); }
|
||||||
|
@ -66,25 +98,247 @@ public:
|
||||||
void resetFunctionResolver() { functionResolver_.set(FunctionResolverPtr(new NullFunctionResolver())); }
|
void resetFunctionResolver() { functionResolver_.set(FunctionResolverPtr(new NullFunctionResolver())); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
XPathExpressionPtr<std::string> do_compile(const std::string& xpath, tree_info_t(XPath::*fn)(const std::string& str) const) const;
|
XPathExpressionPtr<string_type> do_compile(const string_type& xpath,
|
||||||
tree_info_t parse_xpath(const std::string& str) const;
|
tree_info_t(XPath::*fn)(const string_type& str) const) const
|
||||||
tree_info_t parse_xpath_expr(const std::string& str) const;
|
{
|
||||||
|
tree_info_t ast;
|
||||||
|
try {
|
||||||
|
ast = (this->*fn)(xpath);
|
||||||
|
if(!ast.full)
|
||||||
|
throw SyntaxException(xpath);
|
||||||
|
|
||||||
|
CompilationContext<string_type> context(*this, getNamespaceContext(), getFunctionResolver());
|
||||||
|
return XPathExpressionPtr<std::string>(compile_expression(ast.trees.begin(), context));
|
||||||
|
} // try
|
||||||
|
catch(std::exception& ex)
|
||||||
|
{
|
||||||
|
throw ex;
|
||||||
|
} // catch
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
throw SyntaxException(xpath);
|
||||||
|
} // catch
|
||||||
|
} // do_compile
|
||||||
|
|
||||||
|
tree_info_t parse_xpath(const string_type& str) const
|
||||||
|
{
|
||||||
|
str_iter_t first = str.begin(), last = str.end();
|
||||||
|
return ast_parse(first, last, xpathg_);
|
||||||
|
} // parse_xpath
|
||||||
|
|
||||||
|
tree_info_t parse_xpath_expr(const string_type& str) const
|
||||||
|
{
|
||||||
|
str_iter_t first = str.begin(), last = str.end();
|
||||||
|
return ast_parse(first, last, xpathge_);
|
||||||
|
} // parse_xpath
|
||||||
|
|
||||||
xpath_grammar xpathg_;
|
xpath_grammar xpathg_;
|
||||||
|
xpath_grammar_expr xpathge_;
|
||||||
|
|
||||||
ResolverHolder<const NamespaceContext> namespaceContext_;
|
ResolverHolder<const NamespaceContext> namespaceContext_;
|
||||||
ResolverHolder<const VariableResolver<std::string> > variableResolver_;
|
ResolverHolder<const VariableResolver<string_type> > variableResolver_;
|
||||||
ResolverHolder<const FunctionResolver> functionResolver_;
|
ResolverHolder<const FunctionResolver> functionResolver_;
|
||||||
|
|
||||||
typedef XPathExpression<std::string>* (*compileFn)(node_iter_t const& i, CompilationContext& context);
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
static std::map<int, compileFn> factory_;
|
public:
|
||||||
static std::map<int, std::string> names_;
|
static XPathExpression<string_type>* compile_expression(node_iter_t const& i,
|
||||||
static const std::map<int, compileFn> createFunctions();
|
CompilationContext<string_type>& context)
|
||||||
static const std::map<int, std::string> debugNames();
|
{
|
||||||
static void dump(node_iter_t const& i, int depth);
|
long id = getNodeId(i);
|
||||||
|
|
||||||
friend XPathExpression<std::string>* Arabica::XPath::compile_expression(node_iter_t const& i, CompilationContext& context);
|
if(XPath::factory().find(id) == XPath::factory().end())
|
||||||
|
{
|
||||||
|
XPath::dump(i, 0);
|
||||||
|
throw UnsupportedException(XPath::names()[id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return XPath::factory()[id](i, context);
|
||||||
|
} // compile_expression
|
||||||
|
|
||||||
|
private:
|
||||||
|
static XPathExpression<string_type>* createAbsoluteLocationPath(node_iter_t const& i, CompilationContext<string_type>& context);
|
||||||
|
static XPathExpression<string_type>* createRelativeLocationPath(node_iter_t const& i, CompilationContext<string_type>& context);
|
||||||
|
static XPathExpression<string_type>* createSingleStepRelativeLocationPath(node_iter_t const& i, CompilationContext<string_type>& context);
|
||||||
|
static XPathExpression<string_type>* createExpression(node_iter_t const& i, CompilationContext<string_type>& context);
|
||||||
|
static XPathExpression<string_type>* createFunction(node_iter_t const& i, CompilationContext<string_type>& context);
|
||||||
|
static XPathExpression<string_type>* createBinaryExpression(node_iter_t const& i, CompilationContext<string_type>& context);
|
||||||
|
static XPathExpression<string_type>* createLiteral(node_iter_t const& i, CompilationContext<string_type>& context);
|
||||||
|
static XPathExpression<string_type>* createNumber(node_iter_t const& i, CompilationContext<string_type>& context);
|
||||||
|
static XPathExpression<string_type>* createVariable(node_iter_t const& i, CompilationContext<string_type>& context);
|
||||||
|
static XPathExpression<string_type>* createSingleStepAbsoluteLocationPath(node_iter_t const& i, CompilationContext<string_type>& context);
|
||||||
|
static XPathExpression<string_type>* createUnaryExpression(node_iter_t const& i, CompilationContext<string_type>& context);
|
||||||
|
static XPathExpression<string_type>* createUnaryNegativeExpr(node_iter_t const& i, CompilationContext<string_type>& context);
|
||||||
|
|
||||||
|
static StepList createStepList(node_iter_t const& from, node_iter_t const& to, CompilationContext<string_type>& context);
|
||||||
|
|
||||||
|
typedef XPathExpression<string_type>* (*compileFn)(node_iter_t const& i, CompilationContext<string_type>& context);
|
||||||
|
static std::map<int, compileFn>& factory()
|
||||||
|
{
|
||||||
|
static std::map<int, compileFn> f = init_createFunctions();
|
||||||
|
return f;
|
||||||
|
} // factory
|
||||||
|
|
||||||
|
static std::map<int, string_type>& names()
|
||||||
|
{
|
||||||
|
static std::map<int, string_type> n = init_debugNames();
|
||||||
|
return n;
|
||||||
|
} // names
|
||||||
|
|
||||||
|
static const std::map<int, compileFn> init_createFunctions()
|
||||||
|
{
|
||||||
|
std::map<int, XPath::compileFn> factory;
|
||||||
|
|
||||||
|
factory[impl::AbsoluteLocationPath_id] = createAbsoluteLocationPath;
|
||||||
|
factory[impl::RelativeLocationPath_id] = createRelativeLocationPath;
|
||||||
|
factory[impl::AbbreviatedAbsoluteLocationPath_id] = createAbsoluteLocationPath;
|
||||||
|
factory[impl::Step_id] = createRelativeLocationPath;
|
||||||
|
factory[impl::PathExpr_id] = createRelativeLocationPath;
|
||||||
|
factory[impl::FilterExpr_id] = createRelativeLocationPath;
|
||||||
|
|
||||||
|
factory[impl::PrimaryExpr_id] = createExpression;
|
||||||
|
|
||||||
|
factory[impl::FunctionCall_id] = createFunction;
|
||||||
|
|
||||||
|
factory[impl::AdditiveExpr_id] = createBinaryExpression;
|
||||||
|
factory[impl::MultiplicativeExpr_id] = createBinaryExpression;
|
||||||
|
factory[impl::EqualityExpr_id] = createBinaryExpression;
|
||||||
|
factory[impl::RelationalExpr_id] = createBinaryExpression;
|
||||||
|
factory[impl::OrExpr_id] = createBinaryExpression;
|
||||||
|
factory[impl::AndExpr_id] = createBinaryExpression;
|
||||||
|
factory[impl::UnionExpr_id] = createBinaryExpression;
|
||||||
|
|
||||||
|
factory[impl::Literal_id] = createLiteral;
|
||||||
|
factory[impl::Number_id] = createNumber;
|
||||||
|
factory[impl::Digits_id] = createNumber;
|
||||||
|
|
||||||
|
factory[impl::VariableReference_id] = createVariable;
|
||||||
|
|
||||||
|
factory[impl::NodeTest_id] = createSingleStepRelativeLocationPath;
|
||||||
|
factory[impl::QName_id] = createSingleStepRelativeLocationPath;
|
||||||
|
factory[impl::NCName_id] = createSingleStepRelativeLocationPath;
|
||||||
|
factory[impl::AnyName_id] = createSingleStepRelativeLocationPath;
|
||||||
|
factory[impl::Text_id] = createSingleStepRelativeLocationPath;
|
||||||
|
factory[impl::Comment_id] = createSingleStepRelativeLocationPath;
|
||||||
|
factory[impl::ProcessingInstruction_id] = createSingleStepRelativeLocationPath;
|
||||||
|
factory[impl::Slash_id] = createSingleStepAbsoluteLocationPath;
|
||||||
|
|
||||||
|
factory[impl::SelfSelect_id] = createSingleStepRelativeLocationPath;
|
||||||
|
factory[impl::ParentSelect_id] = createSingleStepRelativeLocationPath;
|
||||||
|
|
||||||
|
factory[impl::UnaryExpr_id] = createUnaryExpression;
|
||||||
|
factory[impl::UnaryMinusOperator_id] = createUnaryNegativeExpr;
|
||||||
|
|
||||||
|
return factory;
|
||||||
|
} // init_createFunctions
|
||||||
|
|
||||||
|
static const std::map<int, string_type> init_debugNames()
|
||||||
|
{
|
||||||
|
std::map<int, std::string> names;
|
||||||
|
|
||||||
|
names[impl::LocationPath_id] = "LocationPath";
|
||||||
|
names[impl::AbsoluteLocationPath_id] = "AbsoluteLocationPath";
|
||||||
|
names[impl::RelativeLocationPath_id] = "RelativeLocationPath";
|
||||||
|
names[impl::Step_id] = "Step";
|
||||||
|
names[impl::AxisSpecifier_id] = "AxisSpecifier";
|
||||||
|
names[impl::NodeTest_id] = "NodeTest";
|
||||||
|
names[impl::Predicate_id] = "Predicate";
|
||||||
|
names[impl::PredicateExpr_id] = "PredicateExpr";
|
||||||
|
names[impl::AbbreviatedAbsoluteLocationPath_id] = "AbbreviatedAbsoluteLocationPath";
|
||||||
|
names[impl::AbbreviatedStep_id] = "AbbreviatedStep";
|
||||||
|
names[impl::AbbreviatedAxisSpecifier_id] = "AbbreviatedAxisSpecifier";
|
||||||
|
names[impl::Expr_id] = "Expr";
|
||||||
|
names[impl::PrimaryExpr_id] = "PrimaryExpr";
|
||||||
|
names[impl::FunctionCall_id] = "FunctionCall";
|
||||||
|
names[impl::Argument_id] = "Argument";
|
||||||
|
names[impl::UnionExpr_id] = "UnionExpr";
|
||||||
|
names[impl::PathExpr_id] = "PathExpr";
|
||||||
|
names[impl::FilterExpr_id] = "FilterExpr";
|
||||||
|
names[impl::OrExpr_id] = "OrExpr";
|
||||||
|
names[impl::AndExpr_id] = "AndExpr";
|
||||||
|
names[impl::EqualityExpr_id] = "EqualityExpr";
|
||||||
|
names[impl::RelationalExpr_id] = "RelationalExpr";
|
||||||
|
names[impl::AdditiveExpr_id] = "AdditiveExpr";
|
||||||
|
names[impl::MultiplicativeExpr_id] = "MultiplicativeExpr";
|
||||||
|
names[impl::UnaryExpr_id] = "UnaryExpr";
|
||||||
|
names[impl::Literal_id] = "Literal";
|
||||||
|
names[impl::Number_id] = "Number";
|
||||||
|
names[impl::Digits_id] = "Digits";
|
||||||
|
names[impl::MultiplyOperator_id] = "MultiplyOperator";
|
||||||
|
names[impl::FunctionName_id] = "FunctionName";
|
||||||
|
names[impl::VariableReference_id] = "VariableReference";
|
||||||
|
names[impl::NameTest_id] = "NameTest";
|
||||||
|
names[impl::S_id] = "S";
|
||||||
|
names[impl::NodeType_id] = "NodeType";
|
||||||
|
names[impl::AxisName_id] = "AxisName";
|
||||||
|
|
||||||
|
names[impl::QName_id] = "QName";
|
||||||
|
names[impl::Prefix_id] = "Prefix";
|
||||||
|
names[impl::LocalPart_id] = "LocalPart";
|
||||||
|
names[impl::NCName_id] = "NCName";
|
||||||
|
names[impl::NCNameChar_id] = "NCNameChar";
|
||||||
|
|
||||||
|
names[impl::Slash_id] = "/";
|
||||||
|
names[impl::SlashSlash_id] = "//";
|
||||||
|
|
||||||
|
names[impl::AncestorOrSelf_id] = "ancestor-or-self::";
|
||||||
|
names[impl::Ancestor_id] = "ancestor::";
|
||||||
|
names[impl::Attribute_id] = "attribute::";
|
||||||
|
names[impl::Child_id] = "child::";
|
||||||
|
names[impl::DescendantOrSelf_id] = "descendant-or-self::";
|
||||||
|
names[impl::Descendant_id] = "descendant::";
|
||||||
|
names[impl::FollowingSibling_id] = "following-sibling::";
|
||||||
|
names[impl::Following_id] = "following::";
|
||||||
|
names[impl::Namespace_id] = "namespace::";
|
||||||
|
names[impl::Parent_id] = "parent::";
|
||||||
|
names[impl::PrecedingSibling_id] = "preceding-sibling::";
|
||||||
|
names[impl::Preceding_id] = "preceding::";
|
||||||
|
names[impl::Self_id] = "self::";
|
||||||
|
|
||||||
|
names[impl::Comment_id] = "comment()";
|
||||||
|
names[impl::Text_id] = "text()";
|
||||||
|
names[impl::ProcessingInstruction_id] = "processing-instruction()";
|
||||||
|
names[impl::Node_id] = "node()";
|
||||||
|
names[impl::AnyName_id] = "AnyName";
|
||||||
|
|
||||||
|
names[impl::SelfSelect_id] = "SelfSelect";
|
||||||
|
names[impl::ParentSelect_id] = "ParentSelect";
|
||||||
|
|
||||||
|
names[impl::LeftSquare_id] = "[";
|
||||||
|
names[impl::RightSquare_id] = "]";
|
||||||
|
|
||||||
|
names[impl::LeftBracket_id] = "(";
|
||||||
|
names[impl::RightBracket_id] = ")";
|
||||||
|
|
||||||
|
names[impl::PlusOperator_id] = "+";
|
||||||
|
names[impl::MinusOperator_id] = "-";
|
||||||
|
names[impl::ModOperator_id] = "mod";
|
||||||
|
names[impl::DivOperator_id] = "div";
|
||||||
|
names[impl::EqualsOperator_id] = "=";
|
||||||
|
names[impl::NotEqualsOperator_id] = "!=";
|
||||||
|
names[impl::LessThanOperator_id] = "<";
|
||||||
|
names[impl::LessThanEqualsOperator_id] = "<=";
|
||||||
|
names[impl::GreaterThanOperator_id] = ">";
|
||||||
|
names[impl::GreaterThanEqualsOperator_id] = ">=";
|
||||||
|
|
||||||
|
names[impl::OrOperator_id] = "or";
|
||||||
|
names[impl::AndOperator_id] = "and";
|
||||||
|
names[impl::UnionOperator_id] = "union";
|
||||||
|
names[impl::UnaryMinusOperator_id] = "minus";
|
||||||
|
|
||||||
|
return names;
|
||||||
|
} // init_debugNames
|
||||||
|
|
||||||
|
static void dump(node_iter_t const& i, int depth)
|
||||||
|
{
|
||||||
|
long id = static_cast<long>(i->value.id().to_long());
|
||||||
|
|
||||||
|
for(int d = 0; d < depth; ++d)
|
||||||
|
std::cerr << ' ';
|
||||||
|
std::cerr << names()[id] << " - " << std::string(i->value.begin(), i->value.end()) << std::endl;
|
||||||
|
|
||||||
|
for(node_iter_t c = i->children.begin(); c != i->children.end(); ++c)
|
||||||
|
dump(c, depth+2);
|
||||||
|
} // dump
|
||||||
|
|
||||||
XPath(const XPath&);
|
XPath(const XPath&);
|
||||||
XPath& operator=(const XPath&);
|
XPath& operator=(const XPath&);
|
||||||
|
@ -95,4 +349,216 @@ private:
|
||||||
|
|
||||||
} // namespace Arabica
|
} // namespace Arabica
|
||||||
|
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
#include "xpath_value.hpp"
|
||||||
|
#include "xpath_arithmetic.hpp"
|
||||||
|
#include "xpath_relational.hpp"
|
||||||
|
#include "xpath_logical.hpp"
|
||||||
|
#include "xpath_step.hpp"
|
||||||
|
#include "xpath_compile_context.hpp"
|
||||||
|
#include "xpath_variable.hpp"
|
||||||
|
#include "xpath_function_holder.hpp"
|
||||||
|
#include "xpath_union.hpp"
|
||||||
|
|
||||||
|
namespace Arabica
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace XPath
|
||||||
|
{
|
||||||
|
|
||||||
|
template<class string_type, class string_adaptor>
|
||||||
|
XPathExpression<string_type>* XPath<string_type, string_adaptor>::createAbsoluteLocationPath(node_iter_t const& i, CompilationContext<string_type>& context)
|
||||||
|
{
|
||||||
|
return new AbsoluteLocationPath(createStepList(i->children.begin(), i->children.end(), context));
|
||||||
|
} // createAbsoluteLocationPath
|
||||||
|
|
||||||
|
template<class string_type, class string_adaptor>
|
||||||
|
XPathExpression<string_type>* XPath<string_type, string_adaptor>::createRelativeLocationPath(node_iter_t const& i, CompilationContext<string_type>& context)
|
||||||
|
{
|
||||||
|
return new RelativeLocationPath(createStepList(i->children.begin(), i->children.end(), context));
|
||||||
|
} // createRelativeLocationPath
|
||||||
|
|
||||||
|
template<class string_type, class string_adaptor>
|
||||||
|
XPathExpression<string_type>* XPath<string_type, string_adaptor>::createSingleStepRelativeLocationPath(node_iter_t const& i, CompilationContext<string_type>& context)
|
||||||
|
{
|
||||||
|
node_iter_t n = i;
|
||||||
|
return new RelativeLocationPath(StepFactory::createStep(n, context));
|
||||||
|
} // createSingleStepRelativeLocationPath
|
||||||
|
|
||||||
|
template<class string_type, class string_adaptor>
|
||||||
|
XPathExpression<string_type>* XPath<string_type, string_adaptor>::createExpression(node_iter_t const& i, CompilationContext<string_type>& context)
|
||||||
|
{
|
||||||
|
node_iter_t c = i->children.begin();
|
||||||
|
skipWhitespace(c);
|
||||||
|
return XPath<string_type, string_adaptor>::compile_expression(c, context);
|
||||||
|
} // createExpression
|
||||||
|
|
||||||
|
template<class string_type, class string_adaptor>
|
||||||
|
XPathExpression<string_type>* XPath<string_type, string_adaptor>::createFunction(node_iter_t const& i, CompilationContext<string_type>& context)
|
||||||
|
{
|
||||||
|
node_iter_t c = i->children.begin();
|
||||||
|
string_type name(c->value.begin(), c->value.end());
|
||||||
|
++c;
|
||||||
|
skipWhitespace(c);
|
||||||
|
assert(getNodeId(c) == impl::LeftBracket_id);
|
||||||
|
++c;
|
||||||
|
skipWhitespace(c);
|
||||||
|
|
||||||
|
std::vector<XPathExpressionPtr<string_type> > args;
|
||||||
|
while(getNodeId(c) != impl::RightBracket_id)
|
||||||
|
{
|
||||||
|
XPathExpressionPtr<string_type> arg(XPath<string_type, string_adaptor>::compile_expression(c++, context));
|
||||||
|
args.push_back(arg);
|
||||||
|
|
||||||
|
skipWhitespace(c);
|
||||||
|
} // while ...
|
||||||
|
// maybe trailing whitespace ...
|
||||||
|
|
||||||
|
return FunctionHolder::createFunction(name, args, context);
|
||||||
|
} // createFunction
|
||||||
|
|
||||||
|
template<class string_type, class string_adaptor>
|
||||||
|
XPathExpression<string_type>* XPath<string_type, string_adaptor>::createBinaryExpression(node_iter_t const& i, CompilationContext<string_type>& context)
|
||||||
|
{
|
||||||
|
node_iter_t c = i->children.begin();
|
||||||
|
XPathExpression<string_type>* p1 = XPath<string_type, string_adaptor>::compile_expression(c, context);
|
||||||
|
++c;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
long op = getNodeId(c);
|
||||||
|
++c;
|
||||||
|
XPathExpression<string_type>* p2 = XPath<string_type, string_adaptor>::compile_expression(c, context);
|
||||||
|
|
||||||
|
switch(op)
|
||||||
|
{
|
||||||
|
case impl::PlusOperator_id:
|
||||||
|
p1 = new PlusOperator<string_type>(p1, p2);
|
||||||
|
break;
|
||||||
|
case impl::MinusOperator_id:
|
||||||
|
p1 = new MinusOperator<string_type>(p1, p2);
|
||||||
|
break;
|
||||||
|
case impl::MultiplyOperator_id:
|
||||||
|
p1 = new MultiplyOperator<string_type>(p1, p2);
|
||||||
|
break;
|
||||||
|
case impl::DivOperator_id:
|
||||||
|
p1 = new DivideOperator<string_type>(p1, p2);
|
||||||
|
break;
|
||||||
|
case impl::ModOperator_id:
|
||||||
|
p1 = new ModOperator<string_type>(p1, p2);
|
||||||
|
break;
|
||||||
|
case impl::EqualsOperator_id:
|
||||||
|
p1 = new EqualsOperator(p1, p2);
|
||||||
|
break;
|
||||||
|
case impl::NotEqualsOperator_id:
|
||||||
|
p1 = new NotEqualsOperator(p1, p2);
|
||||||
|
break;
|
||||||
|
case impl::LessThanOperator_id:
|
||||||
|
p1 = new LessThanOperator(p1, p2);
|
||||||
|
break;
|
||||||
|
case impl::LessThanEqualsOperator_id:
|
||||||
|
p1 = new LessThanEqualsOperator(p1, p2);
|
||||||
|
break;
|
||||||
|
case impl::GreaterThanOperator_id:
|
||||||
|
p1 = new GreaterThanOperator(p1, p2);
|
||||||
|
break;
|
||||||
|
case impl::GreaterThanEqualsOperator_id:
|
||||||
|
p1 = new GreaterThanEqualsOperator(p1, p2);
|
||||||
|
break;
|
||||||
|
case impl::OrOperator_id:
|
||||||
|
p1 = new OrOperator(p1, p2);
|
||||||
|
break;
|
||||||
|
case impl::AndOperator_id:
|
||||||
|
p1 = new AndOperator(p1, p2);
|
||||||
|
break;
|
||||||
|
case impl::UnionOperator_id:
|
||||||
|
p1 = new UnionExpression(p1, p2);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw UnsupportedException(boost::lexical_cast<string_type>(op));
|
||||||
|
} // switch
|
||||||
|
}
|
||||||
|
while(++c != i->children.end());
|
||||||
|
|
||||||
|
return p1;
|
||||||
|
} // createBinaryExpression
|
||||||
|
|
||||||
|
template<class string_type, class string_adaptor>
|
||||||
|
XPathExpression<string_type>* XPath<string_type, string_adaptor>::createLiteral(node_iter_t const& i, CompilationContext<string_type>& context)
|
||||||
|
{
|
||||||
|
string_type str(i->value.begin(), i->value.end());
|
||||||
|
return new StringValue(str);
|
||||||
|
} // createLiteral
|
||||||
|
|
||||||
|
template<class string_type, class string_adaptor>
|
||||||
|
XPathExpression<string_type>* XPath<string_type, string_adaptor>::createNumber(node_iter_t const& i, CompilationContext<string_type>& context)
|
||||||
|
{
|
||||||
|
return new NumericValue(boost::lexical_cast<double>(string_type(i->value.begin(), i->value.end())));
|
||||||
|
} // createNumber
|
||||||
|
|
||||||
|
template<class string_type, class string_adaptor>
|
||||||
|
XPathExpression<string_type>* XPath<string_type, string_adaptor>::createVariable(node_iter_t const& i, CompilationContext<string_type>& context)
|
||||||
|
{
|
||||||
|
return new Variable(string_type(i->value.begin()+1, i->value.end())); // skip $
|
||||||
|
} // createVariable
|
||||||
|
|
||||||
|
template<class string_type, class string_adaptor>
|
||||||
|
XPathExpression<string_type>* XPath<string_type, string_adaptor>::createSingleStepAbsoluteLocationPath(node_iter_t const& i, CompilationContext<string_type>& context)
|
||||||
|
{
|
||||||
|
node_iter_t n = i;
|
||||||
|
return new AbsoluteLocationPath(StepFactory::createStep(n, context));
|
||||||
|
} // createSingleStepAbsoluteLocationPath
|
||||||
|
|
||||||
|
template<class string_type, class string_adaptor>
|
||||||
|
XPathExpression<string_type>* XPath<string_type, string_adaptor>::createUnaryExpression(node_iter_t const& i, CompilationContext<string_type>& context)
|
||||||
|
{
|
||||||
|
return XPath<string_type, string_adaptor>::compile_expression(i->children.begin(), context);
|
||||||
|
} // createUnaryExpression
|
||||||
|
|
||||||
|
template<class string_type, class string_adaptor>
|
||||||
|
XPathExpression<string_type>* XPath<string_type, string_adaptor>::createUnaryNegativeExpr(node_iter_t const& i, CompilationContext<string_type>& context)
|
||||||
|
{
|
||||||
|
return new UnaryNegative<string_type>(XPath<string_type, string_adaptor>::compile_expression(i+1, context));
|
||||||
|
} // createUnaryNegativeExpr
|
||||||
|
|
||||||
|
template<class string_type, class string_adaptor>
|
||||||
|
StepList XPath<string_type, string_adaptor>::createStepList(node_iter_t const& from,
|
||||||
|
node_iter_t const& to,
|
||||||
|
CompilationContext<string_type>& context)
|
||||||
|
{
|
||||||
|
StepList steps;
|
||||||
|
|
||||||
|
node_iter_t c = from;
|
||||||
|
node_iter_t end = to;
|
||||||
|
|
||||||
|
while(c != end)
|
||||||
|
switch(getNodeId(c))
|
||||||
|
{
|
||||||
|
case impl::S_id:
|
||||||
|
case impl::Slash_id:
|
||||||
|
++c; // just drop it
|
||||||
|
break;
|
||||||
|
case impl::RelativeLocationPath_id:
|
||||||
|
// might get here when handling an absolute path
|
||||||
|
end = c->children.end();
|
||||||
|
c = c->children.begin();
|
||||||
|
break;
|
||||||
|
case impl::Step_id:
|
||||||
|
{
|
||||||
|
node_iter_t step = c->children.begin();
|
||||||
|
steps.push_back(StepFactory::createStep(step, c->children.end(), context));
|
||||||
|
++c;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
steps.push_back(StepFactory::createStep(c, end, context));
|
||||||
|
} // switch(getNodeId(c))
|
||||||
|
|
||||||
|
return steps;
|
||||||
|
} // createStepList
|
||||||
|
|
||||||
|
} // namespace XPath
|
||||||
|
|
||||||
|
} // namespace Arabica
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -177,13 +177,13 @@ private:
|
||||||
class StepFactory
|
class StepFactory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static StepExpression* createStep(node_iter_t& node, node_iter_t const& end, CompilationContext& context)
|
static StepExpression* createStep(node_iter_t& node, node_iter_t const& end, CompilationContext<std::string>& context)
|
||||||
{
|
{
|
||||||
Axis axis = getAxis(node);
|
Axis axis = getAxis(node);
|
||||||
NodeTest* test = getTest(node, context.namespaceContext());
|
NodeTest* test = getTest(node, context.namespaceContext());
|
||||||
XPathExpression<std::string>* thing = 0;
|
XPathExpression<std::string>* thing = 0;
|
||||||
if(!test)
|
if(!test)
|
||||||
thing = compile_expression(node++, context);
|
thing = XPath<std::string>::compile_expression(node++, context);
|
||||||
|
|
||||||
std::vector<XPathExpression<std::string>*> preds;
|
std::vector<XPathExpression<std::string>*> preds;
|
||||||
|
|
||||||
|
@ -192,7 +192,7 @@ public:
|
||||||
node_iter_t c = node->children.begin();
|
node_iter_t c = node->children.begin();
|
||||||
assert(getNodeId(c) == impl::LeftSquare_id);
|
assert(getNodeId(c) == impl::LeftSquare_id);
|
||||||
++c;
|
++c;
|
||||||
preds.push_back(compile_expression(c, context));
|
preds.push_back(XPath<std::string>::compile_expression(c, context));
|
||||||
++c;
|
++c;
|
||||||
assert(getNodeId(c) == impl::RightSquare_id);
|
assert(getNodeId(c) == impl::RightSquare_id);
|
||||||
|
|
||||||
|
@ -203,7 +203,7 @@ public:
|
||||||
return new TestStepExpression(axis, test, preds);
|
return new TestStepExpression(axis, test, preds);
|
||||||
} // createStep
|
} // createStep
|
||||||
|
|
||||||
static StepExpression* createStep(node_iter_t& node, CompilationContext& context)
|
static StepExpression* createStep(node_iter_t& node, CompilationContext<std::string>& context)
|
||||||
{
|
{
|
||||||
Axis axis = getAxis(node);
|
Axis axis = getAxis(node);
|
||||||
NodeTest* test = getTest(node, context.namespaceContext());
|
NodeTest* test = getTest(node, context.namespaceContext());
|
||||||
|
@ -366,9 +366,6 @@ private:
|
||||||
|
|
||||||
class RelativeLocationPath : public XPathExpression<std::string>
|
class RelativeLocationPath : public XPathExpression<std::string>
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
typedef std::vector<StepExpression*> StepList;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RelativeLocationPath(StepExpression* step) : steps_() { steps_.push_back(step); }
|
RelativeLocationPath(StepExpression* step) : steps_() { steps_.push_back(step); }
|
||||||
RelativeLocationPath(const StepList& steps) : steps_(steps) { }
|
RelativeLocationPath(const StepList& steps) : steps_(steps) { }
|
||||||
|
@ -401,7 +398,7 @@ class AbsoluteLocationPath : public RelativeLocationPath
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AbsoluteLocationPath(StepExpression* step) : RelativeLocationPath(step) { }
|
AbsoluteLocationPath(StepExpression* step) : RelativeLocationPath(step) { }
|
||||||
AbsoluteLocationPath(const RelativeLocationPath::StepList& steps) : RelativeLocationPath(steps) { }
|
AbsoluteLocationPath(const StepList& steps) : RelativeLocationPath(steps) { }
|
||||||
|
|
||||||
virtual XPathValuePtr<std::string> evaluate(const DOM::Node<std::string>& context, const ExecutionContext& executionContext) const
|
virtual XPathValuePtr<std::string> evaluate(const DOM::Node<std::string>& context, const ExecutionContext& executionContext) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,464 +2,26 @@
|
||||||
#pragma warning(disable:4224 4180 4244)
|
#pragma warning(disable:4224 4180 4244)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <map>
|
|
||||||
#include <boost/lexical_cast.hpp>
|
|
||||||
#include <XPath/impl/xpath_parser.hpp>
|
#include <XPath/impl/xpath_parser.hpp>
|
||||||
#include <XPath/impl/xpath_value.hpp>
|
|
||||||
#include <XPath/impl/xpath_arithmetic.hpp>
|
|
||||||
#include <XPath/impl/xpath_relational.hpp>
|
|
||||||
#include <XPath/impl/xpath_logical.hpp>
|
|
||||||
#include <XPath/impl/xpath_step.hpp>
|
|
||||||
#include <XPath/impl/xpath_compile_context.hpp>
|
|
||||||
#include <XPath/impl/xpath_variable.hpp>
|
|
||||||
#include <XPath/impl/xpath_function_holder.hpp>
|
|
||||||
#include <XPath/impl/xpath_union.hpp>
|
|
||||||
|
|
||||||
using namespace Arabica::XPath;
|
namespace Arabica
|
||||||
|
{
|
||||||
|
namespace XPath
|
||||||
|
{
|
||||||
|
|
||||||
long Arabica::XPath::getNodeId(node_iter_t const& node)
|
long getNodeId(node_iter_t const& node)
|
||||||
{
|
{
|
||||||
return static_cast<long>(node->value.id().to_long());
|
return static_cast<long>(node->value.id().to_long());
|
||||||
} // getNodeId
|
} // getNodeId
|
||||||
|
|
||||||
node_iter_t& Arabica::XPath::skipWhitespace(node_iter_t& node)
|
node_iter_t& skipWhitespace(node_iter_t& node)
|
||||||
{
|
{
|
||||||
while(getNodeId(node) == impl::S_id)
|
while(getNodeId(node) == impl::S_id)
|
||||||
++node;
|
++node;
|
||||||
return node;
|
return node;
|
||||||
} // skipWhitespace
|
} // skipWhitespace
|
||||||
|
|
||||||
XPath::XPath()
|
} // namespace XPath
|
||||||
{
|
|
||||||
resetNamespaceContext();
|
|
||||||
resetVariableResolver();
|
|
||||||
resetFunctionResolver();
|
|
||||||
} // XPath
|
|
||||||
|
|
||||||
XPath::~XPath()
|
|
||||||
{
|
|
||||||
} // ~XPath
|
|
||||||
|
|
||||||
std::map<int, std::string> XPath::names_ = debugNames();
|
|
||||||
std::map<int, XPath::compileFn> XPath::factory_ = createFunctions();
|
|
||||||
|
|
||||||
void XPath::dump(node_iter_t const& i, int depth)
|
|
||||||
{
|
|
||||||
long id = static_cast<long>(i->value.id().to_long());
|
|
||||||
|
|
||||||
for(int d = 0; d < depth; ++d)
|
|
||||||
std::cout << ' ';
|
|
||||||
std::cout << names_[id] << " - " << std::string(i->value.begin(), i->value.end()) << std::endl;
|
|
||||||
|
|
||||||
for(node_iter_t c = i->children.begin(); c != i->children.end(); ++c)
|
|
||||||
dump(c, depth+2);
|
|
||||||
} // dump
|
|
||||||
|
|
||||||
XPathExpression<std::string>* createExpression(node_iter_t const& i, CompilationContext& context)
|
|
||||||
{
|
|
||||||
node_iter_t c = i->children.begin();
|
|
||||||
skipWhitespace(c);
|
|
||||||
return compile_expression(c, context);
|
|
||||||
} // createExpression
|
|
||||||
|
|
||||||
XPathExpression<std::string>* createFunction(node_iter_t const& i, CompilationContext& context)
|
|
||||||
{
|
|
||||||
// dump(i);
|
|
||||||
node_iter_t c = i->children.begin();
|
|
||||||
std::string name(c->value.begin(), c->value.end());
|
|
||||||
++c;
|
|
||||||
skipWhitespace(c);
|
|
||||||
assert(getNodeId(c) == impl::LeftBracket_id);
|
|
||||||
++c;
|
|
||||||
skipWhitespace(c);
|
|
||||||
|
|
||||||
std::vector<XPathExpressionPtr<std::string> > args;
|
|
||||||
while(getNodeId(c) != impl::RightBracket_id)
|
|
||||||
{
|
|
||||||
XPathExpressionPtr<std::string> arg(compile_expression(c++, context));
|
|
||||||
args.push_back(arg);
|
|
||||||
|
|
||||||
skipWhitespace(c);
|
|
||||||
} // while ...
|
|
||||||
// maybe trailing whitespace ...
|
|
||||||
|
|
||||||
return FunctionHolder::createFunction(name, args, context);
|
|
||||||
} // createFunction
|
|
||||||
|
|
||||||
XPathExpression<std::string>* createNumber(node_iter_t const& i, CompilationContext& context)
|
|
||||||
{
|
|
||||||
return new NumericValue(boost::lexical_cast<double>(std::string(i->value.begin(), i->value.end())));
|
|
||||||
} // createNumber
|
|
||||||
|
|
||||||
XPathExpression<std::string>* createVariable(node_iter_t const& i, CompilationContext& context)
|
|
||||||
{
|
|
||||||
return new Variable(std::string(i->value.begin()+1, i->value.end())); // skip $
|
|
||||||
} // createVariable
|
|
||||||
|
|
||||||
XPathExpression<std::string>* createLiteral(node_iter_t const& i, CompilationContext& context)
|
|
||||||
{
|
|
||||||
std::string str(i->value.begin(), i->value.end());
|
|
||||||
return new StringValue(str);
|
|
||||||
} // createLiteral
|
|
||||||
|
|
||||||
XPathExpression<std::string>* createBinaryExpression(node_iter_t const& i, CompilationContext& context)
|
|
||||||
{
|
|
||||||
node_iter_t c = i->children.begin();
|
|
||||||
XPathExpression<std::string>* p1 = compile_expression(c, context);
|
|
||||||
++c;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
long op = getNodeId(c);
|
|
||||||
++c;
|
|
||||||
XPathExpression<std::string>* p2 = compile_expression(c, context);
|
|
||||||
|
|
||||||
switch(op)
|
|
||||||
{
|
|
||||||
case impl::PlusOperator_id:
|
|
||||||
p1 = new PlusOperator<std::string>(p1, p2);
|
|
||||||
break;
|
|
||||||
case impl::MinusOperator_id:
|
|
||||||
p1 = new MinusOperator<std::string>(p1, p2);
|
|
||||||
break;
|
|
||||||
case impl::MultiplyOperator_id:
|
|
||||||
p1 = new MultiplyOperator<std::string>(p1, p2);
|
|
||||||
break;
|
|
||||||
case impl::DivOperator_id:
|
|
||||||
p1 = new DivideOperator<std::string>(p1, p2);
|
|
||||||
break;
|
|
||||||
case impl::ModOperator_id:
|
|
||||||
p1 = new ModOperator<std::string>(p1, p2);
|
|
||||||
break;
|
|
||||||
case impl::EqualsOperator_id:
|
|
||||||
p1 = new EqualsOperator(p1, p2);
|
|
||||||
break;
|
|
||||||
case impl::NotEqualsOperator_id:
|
|
||||||
p1 = new NotEqualsOperator(p1, p2);
|
|
||||||
break;
|
|
||||||
case impl::LessThanOperator_id:
|
|
||||||
p1 = new LessThanOperator(p1, p2);
|
|
||||||
break;
|
|
||||||
case impl::LessThanEqualsOperator_id:
|
|
||||||
p1 = new LessThanEqualsOperator(p1, p2);
|
|
||||||
break;
|
|
||||||
case impl::GreaterThanOperator_id:
|
|
||||||
p1 = new GreaterThanOperator(p1, p2);
|
|
||||||
break;
|
|
||||||
case impl::GreaterThanEqualsOperator_id:
|
|
||||||
p1 = new GreaterThanEqualsOperator(p1, p2);
|
|
||||||
break;
|
|
||||||
case impl::OrOperator_id:
|
|
||||||
p1 = new OrOperator(p1, p2);
|
|
||||||
break;
|
|
||||||
case impl::AndOperator_id:
|
|
||||||
p1 = new AndOperator(p1, p2);
|
|
||||||
break;
|
|
||||||
case impl::UnionOperator_id:
|
|
||||||
p1 = new UnionExpression(p1, p2);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw UnsupportedException(boost::lexical_cast<std::string>(op));
|
|
||||||
} // switch
|
|
||||||
}
|
|
||||||
while(++c != i->children.end());
|
|
||||||
|
|
||||||
return p1;
|
|
||||||
} // createBinaryExpression
|
|
||||||
|
|
||||||
RelativeLocationPath::StepList createStepList(node_iter_t const& from, node_iter_t const& to, CompilationContext& context)
|
|
||||||
{
|
|
||||||
RelativeLocationPath::StepList steps;
|
|
||||||
|
|
||||||
node_iter_t c = from;
|
|
||||||
node_iter_t end = to;
|
|
||||||
|
|
||||||
while(c != end)
|
|
||||||
switch(getNodeId(c))
|
|
||||||
{
|
|
||||||
case impl::S_id:
|
|
||||||
case impl::Slash_id:
|
|
||||||
++c; // just drop it
|
|
||||||
break;
|
|
||||||
case impl::RelativeLocationPath_id:
|
|
||||||
// might get here when handling an absolute path
|
|
||||||
end = c->children.end();
|
|
||||||
c = c->children.begin();
|
|
||||||
break;
|
|
||||||
case impl::Step_id:
|
|
||||||
{
|
|
||||||
node_iter_t step = c->children.begin();
|
|
||||||
steps.push_back(StepFactory::createStep(step, c->children.end(), context));
|
|
||||||
++c;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
steps.push_back(StepFactory::createStep(c, end, context));
|
|
||||||
} // switch(getNodeId(c))
|
|
||||||
|
|
||||||
return steps;
|
|
||||||
} // createStepList
|
|
||||||
|
|
||||||
XPathExpression<std::string>* createAbsoluteLocationPath(node_iter_t const& i, CompilationContext& context)
|
|
||||||
{
|
|
||||||
return new AbsoluteLocationPath(createStepList(i->children.begin(), i->children.end(), context));
|
|
||||||
} // createAbsoluteLocationPath
|
|
||||||
|
|
||||||
XPathExpression<std::string>* createRelativeLocationPath(node_iter_t const& i, CompilationContext& context)
|
|
||||||
{
|
|
||||||
return new RelativeLocationPath(createStepList(i->children.begin(), i->children.end(), context));
|
|
||||||
} // createRelativeLocationPath
|
|
||||||
|
|
||||||
XPathExpression<std::string>* createSingleStepRelativeLocationPath(node_iter_t const& i, CompilationContext& context)
|
|
||||||
{
|
|
||||||
node_iter_t n = i;
|
|
||||||
return new RelativeLocationPath(StepFactory::createStep(n, context));
|
|
||||||
} // createSingleStepRelativeLocationPath
|
|
||||||
|
|
||||||
XPathExpression<std::string>* createSingleStepAbsoluteLocationPath(node_iter_t const& i, CompilationContext& context)
|
|
||||||
{
|
|
||||||
node_iter_t n = i;
|
|
||||||
return new AbsoluteLocationPath(StepFactory::createStep(n, context));
|
|
||||||
} // createSingleStepAbsoluteLocationPath
|
|
||||||
|
|
||||||
XPathExpression<std::string>* createUnaryExpression(node_iter_t const& i, CompilationContext& context)
|
|
||||||
{
|
|
||||||
return compile_expression(i->children.begin(), context);
|
|
||||||
} // createUnaryExpression
|
|
||||||
|
|
||||||
XPathExpression<std::string>* createUnaryNegativeExpr(node_iter_t const& i, CompilationContext& context)
|
|
||||||
{
|
|
||||||
return new UnaryNegative<std::string>(compile_expression(i+1, context));
|
|
||||||
} // createUnaryNegativeExpr
|
|
||||||
|
|
||||||
XPathExpressionPtr<std::string> XPath::compile(const std::string& xpath) const
|
|
||||||
{
|
|
||||||
return do_compile(xpath, &XPath::parse_xpath);
|
|
||||||
} // compile
|
|
||||||
|
|
||||||
XPathExpressionPtr<std::string> XPath::compile_expr(const std::string& xpath) const
|
|
||||||
{
|
|
||||||
return do_compile(xpath, &XPath::parse_xpath_expr);
|
|
||||||
} // compile_expr
|
|
||||||
|
|
||||||
XPathExpressionPtr<std::string> XPath::do_compile(const std::string& xpath, tree_info_t(XPath::*fn)(const std::string& str) const) const
|
|
||||||
{
|
|
||||||
debugNames();
|
|
||||||
createFunctions();
|
|
||||||
tree_info_t ast;
|
|
||||||
try {
|
|
||||||
ast = (this->*fn)(xpath);
|
|
||||||
if(!ast.full)
|
|
||||||
throw SyntaxException(xpath);
|
|
||||||
|
|
||||||
CompilationContext context(*this, getNamespaceContext(), getFunctionResolver());
|
|
||||||
return XPathExpressionPtr<std::string>(compile_expression(ast.trees.begin(), context));
|
|
||||||
} // try
|
|
||||||
catch(std::exception& ex)
|
|
||||||
{
|
|
||||||
//dump(ast.trees.begin());
|
|
||||||
std::cerr << "\n\t'" << xpath << "' threw " << ex.what() << '\n' << std::endl;
|
|
||||||
throw SyntaxException(xpath);
|
|
||||||
}
|
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
std::cerr << "\n\t'" << xpath << "' threw something\n" << std::endl;
|
|
||||||
throw SyntaxException(xpath);
|
|
||||||
}
|
|
||||||
} // compile
|
|
||||||
|
|
||||||
tree_info_t XPath::parse_xpath(const std::string& str) const
|
|
||||||
{
|
|
||||||
str_iter_t first = str.begin();
|
|
||||||
str_iter_t last = str.end();
|
|
||||||
|
|
||||||
return ast_parse(first, last, xpathg_);
|
|
||||||
} // parse_xpath
|
|
||||||
|
|
||||||
tree_info_t XPath::parse_xpath_expr(const std::string& str) const
|
|
||||||
{
|
|
||||||
str_iter_t first = str.begin();
|
|
||||||
str_iter_t last = str.end();
|
|
||||||
|
|
||||||
xpath_grammar_expr xpathg;
|
|
||||||
return ast_parse(first, last, xpathg);
|
|
||||||
} // parse_xpath_expr
|
|
||||||
|
|
||||||
XPathValuePtr<std::string> XPath::evaluate(const std::string& xpath, const DOM::Node<std::string>& context) const
|
|
||||||
{
|
|
||||||
ExecutionContext executionContext;
|
|
||||||
executionContext.setVariableResolver(getVariableResolver());
|
|
||||||
|
|
||||||
return compile(xpath)->evaluate(context, executionContext);
|
|
||||||
} // evaluate
|
|
||||||
|
|
||||||
XPathValuePtr<std::string> XPath::evaluate_expr(const std::string& xpath, const DOM::Node<std::string>& context) const
|
|
||||||
{
|
|
||||||
ExecutionContext executionContext;
|
|
||||||
executionContext.setVariableResolver(getVariableResolver());
|
|
||||||
|
|
||||||
return compile_expr(xpath)->evaluate(context, executionContext);
|
|
||||||
} // evaluate_expr
|
|
||||||
|
|
||||||
XPathExpression<std::string>* Arabica::XPath::compile_expression(node_iter_t const& i, CompilationContext& context)
|
|
||||||
{
|
|
||||||
//dump(i);
|
|
||||||
|
|
||||||
long id = getNodeId(i);
|
|
||||||
|
|
||||||
if(XPath::factory_.find(id) == XPath::factory_.end())
|
|
||||||
{
|
|
||||||
//return XPathExpressionPtr<std::string>();
|
|
||||||
XPath::dump(i, 0);
|
|
||||||
throw UnsupportedException(XPath::names_[id]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return XPath::factory_[id](i, context);
|
|
||||||
} // compile_expression
|
|
||||||
|
|
||||||
const std::map<int, XPath::compileFn> XPath::createFunctions()
|
|
||||||
{
|
|
||||||
std::map<int, XPath::compileFn> factory;
|
|
||||||
|
|
||||||
factory[impl::AbsoluteLocationPath_id] = createAbsoluteLocationPath;
|
|
||||||
factory[impl::RelativeLocationPath_id] = createRelativeLocationPath;
|
|
||||||
factory[impl::AbbreviatedAbsoluteLocationPath_id] = createAbsoluteLocationPath;
|
|
||||||
factory[impl::Step_id] = createRelativeLocationPath;
|
|
||||||
factory[impl::PathExpr_id] = createRelativeLocationPath;
|
|
||||||
factory[impl::FilterExpr_id] = createRelativeLocationPath;
|
|
||||||
|
|
||||||
factory[impl::PrimaryExpr_id] = createExpression;
|
|
||||||
|
|
||||||
factory[impl::FunctionCall_id] = createFunction;
|
|
||||||
|
|
||||||
factory[impl::AdditiveExpr_id] = createBinaryExpression;
|
|
||||||
factory[impl::MultiplicativeExpr_id] = createBinaryExpression;
|
|
||||||
factory[impl::EqualityExpr_id] = createBinaryExpression;
|
|
||||||
factory[impl::RelationalExpr_id] = createBinaryExpression;
|
|
||||||
factory[impl::OrExpr_id] = createBinaryExpression;
|
|
||||||
factory[impl::AndExpr_id] = createBinaryExpression;
|
|
||||||
factory[impl::UnionExpr_id] = createBinaryExpression;
|
|
||||||
|
|
||||||
factory[impl::Literal_id] = createLiteral;
|
|
||||||
factory[impl::Number_id] = createNumber;
|
|
||||||
factory[impl::Digits_id] = createNumber;
|
|
||||||
|
|
||||||
factory[impl::VariableReference_id] = createVariable;
|
|
||||||
|
|
||||||
factory[impl::NodeTest_id] = createSingleStepRelativeLocationPath;
|
|
||||||
factory[impl::QName_id] = createSingleStepRelativeLocationPath;
|
|
||||||
factory[impl::NCName_id] = createSingleStepRelativeLocationPath;
|
|
||||||
factory[impl::AnyName_id] = createSingleStepRelativeLocationPath;
|
|
||||||
factory[impl::Text_id] = createSingleStepRelativeLocationPath;
|
|
||||||
factory[impl::Comment_id] = createSingleStepRelativeLocationPath;
|
|
||||||
factory[impl::ProcessingInstruction_id] = createSingleStepRelativeLocationPath;
|
|
||||||
factory[impl::Slash_id] = createSingleStepAbsoluteLocationPath;
|
|
||||||
|
|
||||||
factory[impl::SelfSelect_id] = createSingleStepRelativeLocationPath;
|
|
||||||
factory[impl::ParentSelect_id] = createSingleStepRelativeLocationPath;
|
|
||||||
|
|
||||||
factory[impl::UnaryExpr_id] = createUnaryExpression;
|
|
||||||
factory[impl::UnaryMinusOperator_id] = createUnaryNegativeExpr;
|
|
||||||
|
|
||||||
return factory;
|
|
||||||
} // createFunctions
|
|
||||||
|
|
||||||
const std::map<int, std::string> XPath::debugNames()
|
|
||||||
{
|
|
||||||
std::map<int, std::string> names;
|
|
||||||
|
|
||||||
names[impl::LocationPath_id] = "LocationPath";
|
|
||||||
names[impl::AbsoluteLocationPath_id] = "AbsoluteLocationPath";
|
|
||||||
names[impl::RelativeLocationPath_id] = "RelativeLocationPath";
|
|
||||||
names[impl::Step_id] = "Step";
|
|
||||||
names[impl::AxisSpecifier_id] = "AxisSpecifier";
|
|
||||||
names[impl::NodeTest_id] = "NodeTest";
|
|
||||||
names[impl::Predicate_id] = "Predicate";
|
|
||||||
names[impl::PredicateExpr_id] = "PredicateExpr";
|
|
||||||
names[impl::AbbreviatedAbsoluteLocationPath_id] = "AbbreviatedAbsoluteLocationPath";
|
|
||||||
names[impl::AbbreviatedStep_id] = "AbbreviatedStep";
|
|
||||||
names[impl::AbbreviatedAxisSpecifier_id] = "AbbreviatedAxisSpecifier";
|
|
||||||
names[impl::Expr_id] = "Expr";
|
|
||||||
names[impl::PrimaryExpr_id] = "PrimaryExpr";
|
|
||||||
names[impl::FunctionCall_id] = "FunctionCall";
|
|
||||||
names[impl::Argument_id] = "Argument";
|
|
||||||
names[impl::UnionExpr_id] = "UnionExpr";
|
|
||||||
names[impl::PathExpr_id] = "PathExpr";
|
|
||||||
names[impl::FilterExpr_id] = "FilterExpr";
|
|
||||||
names[impl::OrExpr_id] = "OrExpr";
|
|
||||||
names[impl::AndExpr_id] = "AndExpr";
|
|
||||||
names[impl::EqualityExpr_id] = "EqualityExpr";
|
|
||||||
names[impl::RelationalExpr_id] = "RelationalExpr";
|
|
||||||
names[impl::AdditiveExpr_id] = "AdditiveExpr";
|
|
||||||
names[impl::MultiplicativeExpr_id] = "MultiplicativeExpr";
|
|
||||||
names[impl::UnaryExpr_id] = "UnaryExpr";
|
|
||||||
names[impl::Literal_id] = "Literal";
|
|
||||||
names[impl::Number_id] = "Number";
|
|
||||||
names[impl::Digits_id] = "Digits";
|
|
||||||
names[impl::MultiplyOperator_id] = "MultiplyOperator";
|
|
||||||
names[impl::FunctionName_id] = "FunctionName";
|
|
||||||
names[impl::VariableReference_id] = "VariableReference";
|
|
||||||
names[impl::NameTest_id] = "NameTest";
|
|
||||||
names[impl::S_id] = "S";
|
|
||||||
names[impl::NodeType_id] = "NodeType";
|
|
||||||
names[impl::AxisName_id] = "AxisName";
|
|
||||||
|
|
||||||
names[impl::QName_id] = "QName";
|
|
||||||
names[impl::Prefix_id] = "Prefix";
|
|
||||||
names[impl::LocalPart_id] = "LocalPart";
|
|
||||||
names[impl::NCName_id] = "NCName";
|
|
||||||
names[impl::NCNameChar_id] = "NCNameChar";
|
|
||||||
|
|
||||||
names[impl::Slash_id] = "/";
|
|
||||||
names[impl::SlashSlash_id] = "//";
|
|
||||||
|
|
||||||
names[impl::AncestorOrSelf_id] = "ancestor-or-self::";
|
|
||||||
names[impl::Ancestor_id] = "ancestor::";
|
|
||||||
names[impl::Attribute_id] = "attribute::";
|
|
||||||
names[impl::Child_id] = "child::";
|
|
||||||
names[impl::DescendantOrSelf_id] = "descendant-or-self::";
|
|
||||||
names[impl::Descendant_id] = "descendant::";
|
|
||||||
names[impl::FollowingSibling_id] = "following-sibling::";
|
|
||||||
names[impl::Following_id] = "following::";
|
|
||||||
names[impl::Namespace_id] = "namespace::";
|
|
||||||
names[impl::Parent_id] = "parent::";
|
|
||||||
names[impl::PrecedingSibling_id] = "preceding-sibling::";
|
|
||||||
names[impl::Preceding_id] = "preceding::";
|
|
||||||
names[impl::Self_id] = "self::";
|
|
||||||
|
|
||||||
names[impl::Comment_id] = "comment()";
|
|
||||||
names[impl::Text_id] = "text()";
|
|
||||||
names[impl::ProcessingInstruction_id] = "processing-instruction()";
|
|
||||||
names[impl::Node_id] = "node()";
|
|
||||||
names[impl::AnyName_id] = "AnyName";
|
|
||||||
|
|
||||||
names[impl::SelfSelect_id] = "SelfSelect";
|
|
||||||
names[impl::ParentSelect_id] = "ParentSelect";
|
|
||||||
|
|
||||||
names[impl::LeftSquare_id] = "[";
|
|
||||||
names[impl::RightSquare_id] = "]";
|
|
||||||
|
|
||||||
names[impl::LeftBracket_id] = "(";
|
|
||||||
names[impl::RightBracket_id] = ")";
|
|
||||||
|
|
||||||
names[impl::PlusOperator_id] = "+";
|
|
||||||
names[impl::MinusOperator_id] = "-";
|
|
||||||
names[impl::ModOperator_id] = "mod";
|
|
||||||
names[impl::DivOperator_id] = "div";
|
|
||||||
names[impl::EqualsOperator_id] = "=";
|
|
||||||
names[impl::NotEqualsOperator_id] = "!=";
|
|
||||||
names[impl::LessThanOperator_id] = "<";
|
|
||||||
names[impl::LessThanEqualsOperator_id] = "<=";
|
|
||||||
names[impl::GreaterThanOperator_id] = ">";
|
|
||||||
names[impl::GreaterThanEqualsOperator_id] = ">=";
|
|
||||||
|
|
||||||
names[impl::OrOperator_id] = "or";
|
|
||||||
names[impl::AndOperator_id] = "and";
|
|
||||||
names[impl::UnionOperator_id] = "union";
|
|
||||||
names[impl::UnaryMinusOperator_id] = "minus";
|
|
||||||
|
|
||||||
return names;
|
|
||||||
} // debugNames
|
|
||||||
|
|
||||||
|
} // namespace Arabica
|
||||||
// end
|
// end
|
||||||
|
|
|
@ -19,7 +19,7 @@ int main(int argc, char* argv[])
|
||||||
return 0;
|
return 0;
|
||||||
} // if(argc < 3)
|
} // if(argc < 3)
|
||||||
|
|
||||||
Arabica::XPath::XPath xpathParser;
|
Arabica::XPath::XPath<std::string> xpathParser;
|
||||||
Arabica::XPath::XPathExpressionPtr<std::string> xpath = xpathParser.compile(argv[1]);
|
Arabica::XPath::XPathExpressionPtr<std::string> xpath = xpathParser.compile(argv[1]);
|
||||||
|
|
||||||
SAX2DOM::Parser<std::string> domParser;
|
SAX2DOM::Parser<std::string> domParser;
|
||||||
|
|
|
@ -79,7 +79,7 @@ public:
|
||||||
|
|
||||||
class ExecuteTest : public TestCase
|
class ExecuteTest : public TestCase
|
||||||
{
|
{
|
||||||
Arabica::XPath::XPath parser;
|
Arabica::XPath::XPath<std::string> parser;
|
||||||
DOM::DOMImplementation<std::string> factory_;
|
DOM::DOMImplementation<std::string> factory_;
|
||||||
DOM::Document<std::string> document_;
|
DOM::Document<std::string> document_;
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
class ParseTest : public TestCase
|
class ParseTest : public TestCase
|
||||||
{
|
{
|
||||||
Arabica::XPath::XPath parser;
|
Arabica::XPath::XPath<std::string> parser;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ParseTest(std::string name) : TestCase(name)
|
ParseTest(std::string name) : TestCase(name)
|
||||||
|
|
Loading…
Reference in a new issue