mirror of
https://bitbucket.org/smil3y/kdelibs.git
synced 2025-02-25 11:22:50 +00:00
474 lines
7.1 KiB
Text
474 lines
7.1 KiB
Text
%{
|
|
#include "functions.h"
|
|
#include "path.h"
|
|
#include "predicate.h"
|
|
#include "util.h"
|
|
#include "tokenizer.h"
|
|
|
|
#include "expression.h"
|
|
#include "util.h"
|
|
#include "variablereference.h"
|
|
|
|
#include "dom/dom_string.h"
|
|
#include "dom/dom_exception.h"
|
|
#include "dom/dom3_xpath.h"
|
|
#include "xml/dom_stringimpl.h"
|
|
#include "xml/dom3_xpathimpl.h"
|
|
|
|
using namespace DOM;
|
|
using namespace DOM::XPath;
|
|
using namespace khtml;
|
|
using namespace khtml::XPath;
|
|
|
|
|
|
|
|
#include <QList>
|
|
#include <QPair>
|
|
#include <QDebug>
|
|
|
|
#ifndef NDEBUG
|
|
#define YYDEBUG 1
|
|
#endif
|
|
|
|
Expression * khtmlParseXPathStatement( const DOM::DOMString &statement, int& ec );
|
|
|
|
static Expression *_topExpr;
|
|
static int xpathParseException;
|
|
|
|
%}
|
|
|
|
%union
|
|
{
|
|
khtml::XPath::Step::AxisType axisType;
|
|
int num;
|
|
DOM::DOMString *str; // we use this and not DOMStringImpl*, so the
|
|
// memory management for this is entirely manual,
|
|
// and not an RC/manual hybrid
|
|
khtml::XPath::Expression *expr;
|
|
QList<khtml::XPath::Predicate *> *predList;
|
|
QList<khtml::XPath::Expression *> *argList;
|
|
khtml::XPath::Step *step;
|
|
khtml::XPath::LocationPath *locationPath;
|
|
}
|
|
|
|
%{
|
|
%}
|
|
|
|
%left <num> MULOP RELOP EQOP
|
|
%left <str> PLUS MINUS
|
|
%left <str> OR AND
|
|
%token <axisType> AXISNAME
|
|
%token <str> NODETYPE PI FUNCTIONNAME LITERAL
|
|
%token <str> VARIABLEREFERENCE NUMBER
|
|
%token <str> DOTDOT SLASHSLASH NAMETEST
|
|
%token ERROR
|
|
|
|
%type <locationPath> LocationPath
|
|
%type <locationPath> AbsoluteLocationPath
|
|
%type <locationPath> RelativeLocationPath
|
|
%type <step> Step
|
|
%type <axisType> AxisSpecifier
|
|
%type <step> DescendantOrSelf
|
|
%type <str> NodeTest
|
|
%type <expr> Predicate
|
|
%type <predList> PredicateList
|
|
%type <step> AbbreviatedStep
|
|
%type <expr> Expr
|
|
%type <expr> PrimaryExpr
|
|
%type <expr> FunctionCall
|
|
%type <argList> ArgumentList
|
|
%type <expr> Argument
|
|
%type <expr> UnionExpr
|
|
%type <expr> PathExpr
|
|
%type <expr> FilterExpr
|
|
%type <expr> OrExpr
|
|
%type <expr> AndExpr
|
|
%type <expr> EqualityExpr
|
|
%type <expr> RelationalExpr
|
|
%type <expr> AdditiveExpr
|
|
%type <expr> MultiplicativeExpr
|
|
%type <expr> UnaryExpr
|
|
|
|
%%
|
|
|
|
Expr:
|
|
OrExpr
|
|
{
|
|
_topExpr = $1;
|
|
}
|
|
;
|
|
|
|
LocationPath:
|
|
RelativeLocationPath
|
|
{
|
|
$$->m_absolute = false;
|
|
}
|
|
|
|
|
AbsoluteLocationPath
|
|
{
|
|
$$->m_absolute = true;
|
|
}
|
|
;
|
|
|
|
AbsoluteLocationPath:
|
|
'/'
|
|
{
|
|
$$ = new LocationPath;
|
|
}
|
|
|
|
|
'/' RelativeLocationPath
|
|
{
|
|
$$ = $2;
|
|
}
|
|
|
|
|
DescendantOrSelf RelativeLocationPath
|
|
{
|
|
$$ = $2;
|
|
$$->m_steps.prepend( $1 );
|
|
}
|
|
;
|
|
|
|
RelativeLocationPath:
|
|
Step
|
|
{
|
|
$$ = new LocationPath;
|
|
$$->m_steps.append( $1 );
|
|
}
|
|
|
|
|
RelativeLocationPath '/' Step
|
|
{
|
|
$$->m_steps.append( $3 );
|
|
}
|
|
|
|
|
RelativeLocationPath DescendantOrSelf Step
|
|
{
|
|
$$->m_steps.append( $2 );
|
|
$$->m_steps.append( $3 );
|
|
}
|
|
;
|
|
|
|
Step:
|
|
NodeTest
|
|
{
|
|
$$ = new Step( Step::ChildAxis, *$1 );
|
|
delete $1;
|
|
}
|
|
|
|
|
NodeTest PredicateList
|
|
{
|
|
$$ = new Step( Step::ChildAxis, *$1, *$2 );
|
|
delete $1;
|
|
delete $2;
|
|
}
|
|
|
|
|
AxisSpecifier NodeTest
|
|
{
|
|
$$ = new Step( $1, *$2 );
|
|
delete $2;
|
|
}
|
|
|
|
|
AxisSpecifier NodeTest PredicateList
|
|
{
|
|
$$ = new Step( $1, *$2, *$3 );
|
|
delete $2;
|
|
delete $3;
|
|
}
|
|
|
|
|
AbbreviatedStep
|
|
;
|
|
|
|
AxisSpecifier:
|
|
AXISNAME
|
|
|
|
|
'@'
|
|
{
|
|
$$ = Step::AttributeAxis;
|
|
}
|
|
;
|
|
|
|
NodeTest:
|
|
NAMETEST
|
|
{
|
|
const int colon = $1->find( ':' );
|
|
if ( colon > -1 ) {
|
|
DOMString prefix( $1->substring( 0, colon ) );
|
|
XPathNSResolverImpl *resolver = Expression::evaluationContext().resolver;
|
|
if ( !resolver || resolver->lookupNamespaceURI( prefix ).isNull() ) {
|
|
kWarning(6011) << "Found unknown namespace prefix " << prefix.string();
|
|
xpathParseException = DOMException::NAMESPACE_ERR;
|
|
YYABORT;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
NODETYPE '(' ')'
|
|
{
|
|
$$ = new DOMString( *$1 + DOMString("()") );
|
|
}
|
|
|
|
|
PI '(' ')'
|
|
|
|
|
PI '(' LITERAL ')'
|
|
{
|
|
QString s = $1->string() + QLatin1Char(' ') + $3->string();
|
|
s = s.trimmed();
|
|
$$ = new DOMString( s );
|
|
delete $1;
|
|
delete $3;
|
|
}
|
|
;
|
|
|
|
PredicateList:
|
|
Predicate
|
|
{
|
|
$$ = new QList<Predicate *>;
|
|
$$->append( new Predicate( $1 ) );
|
|
}
|
|
|
|
|
PredicateList Predicate
|
|
{
|
|
$$->append( new Predicate( $2 ) );
|
|
}
|
|
;
|
|
|
|
Predicate:
|
|
'[' Expr ']'
|
|
{
|
|
$$ = $2;
|
|
}
|
|
;
|
|
|
|
DescendantOrSelf:
|
|
SLASHSLASH
|
|
{
|
|
$$ = new Step( Step::DescendantOrSelfAxis, "node()" );
|
|
}
|
|
;
|
|
|
|
AbbreviatedStep:
|
|
'.'
|
|
{
|
|
$$ = new Step( Step::SelfAxis, "node()" );
|
|
}
|
|
|
|
|
DOTDOT
|
|
{
|
|
$$ = new Step( Step::ParentAxis, "node()" );
|
|
}
|
|
;
|
|
|
|
PrimaryExpr:
|
|
VARIABLEREFERENCE
|
|
{
|
|
$$ = new VariableReference( *$1 );
|
|
delete $1;
|
|
}
|
|
|
|
|
'(' Expr ')'
|
|
{
|
|
$$ = $2;
|
|
}
|
|
|
|
|
LITERAL
|
|
{
|
|
$$ = new String( *$1 );
|
|
delete $1;
|
|
}
|
|
|
|
|
NUMBER
|
|
{
|
|
$$ = new Number( $1->toFloat() );
|
|
delete $1;
|
|
}
|
|
|
|
|
FunctionCall
|
|
;
|
|
|
|
FunctionCall:
|
|
FUNCTIONNAME '(' ')'
|
|
{
|
|
Function* f = FunctionLibrary::self().getFunction( *$1 );
|
|
delete $1;
|
|
if (!f) {
|
|
xpathParseException = XPathException::toCode(INVALID_EXPRESSION_ERR);
|
|
YYABORT;
|
|
}
|
|
|
|
$$ = f;
|
|
}
|
|
|
|
|
FUNCTIONNAME '(' ArgumentList ')'
|
|
{
|
|
Function* f = FunctionLibrary::self().getFunction( *$1, *$3 );
|
|
delete $1;
|
|
delete $3;
|
|
if (!f) {
|
|
xpathParseException = XPathException::toCode(INVALID_EXPRESSION_ERR);
|
|
YYABORT;
|
|
}
|
|
$$ = f;
|
|
}
|
|
;
|
|
|
|
ArgumentList:
|
|
Argument
|
|
{
|
|
$$ = new QList<Expression *>;
|
|
$$->append( $1 );
|
|
}
|
|
|
|
|
ArgumentList ',' Argument
|
|
{
|
|
$$->append( $3 );
|
|
}
|
|
;
|
|
|
|
Argument:
|
|
Expr
|
|
;
|
|
|
|
|
|
UnionExpr:
|
|
PathExpr
|
|
|
|
|
UnionExpr '|' PathExpr
|
|
{
|
|
$$ = new Union;
|
|
$$->addSubExpression( $1 );
|
|
$$->addSubExpression( $3 );
|
|
}
|
|
;
|
|
|
|
PathExpr:
|
|
LocationPath
|
|
{
|
|
$$ = $1;
|
|
}
|
|
|
|
|
FilterExpr
|
|
{
|
|
$$ = $1;
|
|
}
|
|
|
|
|
FilterExpr '/' RelativeLocationPath
|
|
{
|
|
$$ = new Path( static_cast<Filter *>( $1 ), $3 );
|
|
}
|
|
|
|
|
FilterExpr DescendantOrSelf RelativeLocationPath
|
|
{
|
|
$3->m_steps.prepend( $2 );
|
|
$$ = new Path( static_cast<Filter *>( $1 ), $3 );
|
|
}
|
|
;
|
|
|
|
FilterExpr:
|
|
PrimaryExpr
|
|
{
|
|
$$ = $1;
|
|
}
|
|
|
|
|
PrimaryExpr PredicateList
|
|
{
|
|
$$ = new Filter( $1, *$2 );
|
|
}
|
|
;
|
|
|
|
OrExpr:
|
|
AndExpr
|
|
|
|
|
OrExpr OR AndExpr
|
|
{
|
|
$$ = new LogicalOp( LogicalOp::OP_Or, $1, $3 );
|
|
}
|
|
;
|
|
|
|
AndExpr:
|
|
EqualityExpr
|
|
|
|
|
AndExpr AND EqualityExpr
|
|
{
|
|
$$ = new LogicalOp( LogicalOp::OP_And, $1, $3 );
|
|
}
|
|
;
|
|
|
|
EqualityExpr:
|
|
RelationalExpr
|
|
|
|
|
EqualityExpr EQOP RelationalExpr
|
|
{
|
|
$$ = new RelationOp( $2, $1, $3 );
|
|
}
|
|
;
|
|
|
|
RelationalExpr:
|
|
AdditiveExpr
|
|
|
|
|
RelationalExpr RELOP AdditiveExpr
|
|
{
|
|
$$ = new RelationOp( $2, $1, $3 );
|
|
}
|
|
;
|
|
|
|
AdditiveExpr:
|
|
MultiplicativeExpr
|
|
|
|
|
AdditiveExpr PLUS MultiplicativeExpr
|
|
{
|
|
$$ = new NumericOp( NumericOp::OP_Add, $1, $3 );
|
|
}
|
|
|
|
|
AdditiveExpr MINUS MultiplicativeExpr
|
|
{
|
|
$$ = new NumericOp( NumericOp::OP_Sub, $1, $3 );
|
|
}
|
|
;
|
|
|
|
MultiplicativeExpr:
|
|
UnaryExpr
|
|
|
|
|
MultiplicativeExpr MULOP UnaryExpr
|
|
{
|
|
$$ = new NumericOp( $2, $1, $3 );
|
|
}
|
|
;
|
|
|
|
UnaryExpr:
|
|
UnionExpr
|
|
|
|
|
MINUS UnaryExpr
|
|
{
|
|
$$ = new Negative;
|
|
$$->addSubExpression( $2 );
|
|
}
|
|
;
|
|
|
|
%%
|
|
|
|
namespace khtml {
|
|
namespace XPath {
|
|
|
|
Expression *khtmlParseXPathStatement( const DOM::DOMString &statement, int& ec )
|
|
{
|
|
// qDebug() << "Parsing " << statement;
|
|
xpathParseException = 0;
|
|
_topExpr = 0;
|
|
initTokenizer( statement );
|
|
yyparse();
|
|
|
|
if (xpathParseException)
|
|
ec = xpathParseException;
|
|
return _topExpr;
|
|
}
|
|
|
|
void khtmlxpathyyerror(const char *str)
|
|
{
|
|
// XXX Clean xpathyylval.str up to avoid leaking it.
|
|
fprintf(stderr, "error: %s\n", str);
|
|
xpathParseException = XPathException::toCode(INVALID_EXPRESSION_ERR);
|
|
}
|
|
|
|
} // namespace XPath
|
|
} // namespace khtml
|
|
|
|
// kate: indent-width 4; replace-tabs off; tab-width 4; space-indent off;
|