%{ #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 #include #include #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 *predList; QList *argList; khtml::XPath::Step *step; khtml::XPath::LocationPath *locationPath; } %{ %} %left MULOP RELOP EQOP %left PLUS MINUS %left OR AND %token AXISNAME %token NODETYPE PI FUNCTIONNAME LITERAL %token VARIABLEREFERENCE NUMBER %token DOTDOT SLASHSLASH NAMETEST %token ERROR %type LocationPath %type AbsoluteLocationPath %type RelativeLocationPath %type Step %type AxisSpecifier %type DescendantOrSelf %type NodeTest %type Predicate %type PredicateList %type AbbreviatedStep %type Expr %type PrimaryExpr %type FunctionCall %type ArgumentList %type Argument %type UnionExpr %type PathExpr %type FilterExpr %type OrExpr %type AndExpr %type EqualityExpr %type RelationalExpr %type AdditiveExpr %type MultiplicativeExpr %type 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; $$->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; $$->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( $1 ), $3 ); } | FilterExpr DescendantOrSelf RelativeLocationPath { $3->m_steps.prepend( $2 ); $$ = new Path( static_cast( $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;