494 lines
12 KiB
Plaintext
494 lines
12 KiB
Plaintext
/*
|
|
* Copyright 2005 Frerich Raabe <raabe@kde.org>
|
|
* Copyright (C) 2006, 2013 Apple Inc. All rights reserved.
|
|
* Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
%{
|
|
|
|
#include "config.h"
|
|
|
|
#include "XPathFunctions.h"
|
|
#include "XPathParser.h"
|
|
#include "XPathPath.h"
|
|
#include "XPathStep.h"
|
|
#include "XPathVariableReference.h"
|
|
|
|
#if COMPILER(MSVC)
|
|
// See https://msdn.microsoft.com/en-us/library/1wea5zwe.aspx
|
|
#pragma warning(disable: 4701)
|
|
#endif
|
|
|
|
#define YYMALLOC fastMalloc
|
|
#define YYFREE fastFree
|
|
|
|
#define YYENABLE_NLS 0
|
|
#define YYLTYPE_IS_TRIVIAL 1
|
|
#define YYDEBUG 0
|
|
#define YYMAXDEPTH 10000
|
|
|
|
using namespace WebCore;
|
|
using namespace XPath;
|
|
|
|
%}
|
|
|
|
%pure-parser
|
|
%lex-param { parser }
|
|
%parse-param { Parser& parser }
|
|
|
|
%union {
|
|
NumericOp::Opcode numericOpcode;
|
|
EqTestOp::Opcode equalityTestOpcode;
|
|
StringImpl* string;
|
|
Step::Axis axis;
|
|
LocationPath* locationPath;
|
|
Step::NodeTest* nodeTest;
|
|
Vector<std::unique_ptr<Expression>>* expressionVector;
|
|
Step* step;
|
|
Expression* expression;
|
|
}
|
|
%left <numericOpcode> MULOP
|
|
|
|
%left <equalityTestOpcode> EQOP RELOP
|
|
|
|
%left PLUS MINUS
|
|
|
|
%left OR AND
|
|
|
|
%token <string> FUNCTIONNAME LITERAL NAMETEST NUMBER NODETYPE VARIABLEREFERENCE
|
|
%destructor { if ($$) $$->deref(); } FUNCTIONNAME LITERAL NAMETEST NUMBER NODETYPE VARIABLEREFERENCE
|
|
|
|
%token <axis> AXISNAME
|
|
%type <axis> AxisSpecifier
|
|
|
|
%token COMMENT DOTDOT PI NODE SLASHSLASH TEXT_ XPATH_ERROR
|
|
|
|
%type <locationPath> LocationPath AbsoluteLocationPath RelativeLocationPath
|
|
%destructor { delete $$; } LocationPath AbsoluteLocationPath RelativeLocationPath
|
|
|
|
%type <nodeTest> NodeTest
|
|
%destructor { delete $$; } NodeTest
|
|
|
|
%type <expressionVector> ArgumentList PredicateList OptionalPredicateList
|
|
%destructor { delete $$; } ArgumentList PredicateList OptionalPredicateList
|
|
|
|
%type <step> Step AbbreviatedStep DescendantOrSelf
|
|
%destructor { delete $$; } Step AbbreviatedStep DescendantOrSelf
|
|
|
|
%type <expression> AdditiveExpr AndExpr Argument EqualityExpr Expr FilterExpr FunctionCall MultiplicativeExpr OrExpr PathExpr Predicate PrimaryExpr RelationalExpr UnaryExpr UnionExpr
|
|
%destructor { delete $$; } AdditiveExpr AndExpr Argument EqualityExpr Expr FilterExpr FunctionCall MultiplicativeExpr OrExpr PathExpr Predicate PrimaryExpr RelationalExpr UnaryExpr UnionExpr
|
|
|
|
|
|
|
|
%{
|
|
|
|
static int xpathyylex(YYSTYPE* yylval, Parser& parser) { return parser.lex(*yylval); }
|
|
static void xpathyyerror(Parser&, const char*) { }
|
|
|
|
%}
|
|
|
|
%%
|
|
|
|
Top:
|
|
Expr
|
|
{
|
|
parser.setParseResult(std::unique_ptr<Expression>($1));
|
|
}
|
|
;
|
|
|
|
Expr:
|
|
OrExpr
|
|
;
|
|
|
|
LocationPath:
|
|
AbsoluteLocationPath
|
|
{
|
|
$$ = $1;
|
|
$$->setAbsolute();
|
|
}
|
|
|
|
|
RelativeLocationPath
|
|
;
|
|
|
|
AbsoluteLocationPath:
|
|
'/'
|
|
{
|
|
$$ = new LocationPath;
|
|
}
|
|
|
|
|
'/' RelativeLocationPath
|
|
{
|
|
$$ = $2;
|
|
}
|
|
|
|
|
DescendantOrSelf RelativeLocationPath
|
|
{
|
|
$$ = $2;
|
|
$$->prependStep(std::unique_ptr<Step>($1));
|
|
}
|
|
;
|
|
|
|
RelativeLocationPath:
|
|
Step
|
|
{
|
|
$$ = new LocationPath;
|
|
$$->appendStep(std::unique_ptr<Step>($1));
|
|
}
|
|
|
|
|
RelativeLocationPath '/' Step
|
|
{
|
|
$$ = $1;
|
|
$$->appendStep(std::unique_ptr<Step>($3));
|
|
}
|
|
|
|
|
RelativeLocationPath DescendantOrSelf Step
|
|
{
|
|
$$ = $1;
|
|
$$->appendStep(std::unique_ptr<Step>($2));
|
|
$$->appendStep(std::unique_ptr<Step>($3));
|
|
}
|
|
;
|
|
|
|
Step:
|
|
NodeTest OptionalPredicateList
|
|
{
|
|
std::unique_ptr<Step::NodeTest> nodeTest($1);
|
|
std::unique_ptr<Vector<std::unique_ptr<Expression>>> predicateList($2);
|
|
if (predicateList)
|
|
$$ = new Step(Step::ChildAxis, WTFMove(*nodeTest), WTFMove(*predicateList));
|
|
else
|
|
$$ = new Step(Step::ChildAxis, WTFMove(*nodeTest));
|
|
}
|
|
|
|
|
NAMETEST OptionalPredicateList
|
|
{
|
|
String nametest = adoptRef($1);
|
|
std::unique_ptr<Vector<std::unique_ptr<Expression>>> predicateList($2);
|
|
|
|
String localName;
|
|
String namespaceURI;
|
|
if (!parser.expandQualifiedName(nametest, localName, namespaceURI)) {
|
|
$$ = nullptr;
|
|
YYABORT;
|
|
}
|
|
|
|
if (predicateList)
|
|
$$ = new Step(Step::ChildAxis, Step::NodeTest(Step::NodeTest::NameTest, localName, namespaceURI), WTFMove(*predicateList));
|
|
else
|
|
$$ = new Step(Step::ChildAxis, Step::NodeTest(Step::NodeTest::NameTest, localName, namespaceURI));
|
|
}
|
|
|
|
|
AxisSpecifier NodeTest OptionalPredicateList
|
|
{
|
|
std::unique_ptr<Step::NodeTest> nodeTest($2);
|
|
std::unique_ptr<Vector<std::unique_ptr<Expression>>> predicateList($3);
|
|
|
|
if (predicateList)
|
|
$$ = new Step($1, WTFMove(*nodeTest), WTFMove(*predicateList));
|
|
else
|
|
$$ = new Step($1, WTFMove(*nodeTest));
|
|
}
|
|
|
|
|
AxisSpecifier NAMETEST OptionalPredicateList
|
|
{
|
|
String nametest = adoptRef($2);
|
|
std::unique_ptr<Vector<std::unique_ptr<Expression>>> predicateList($3);
|
|
|
|
String localName;
|
|
String namespaceURI;
|
|
if (!parser.expandQualifiedName(nametest, localName, namespaceURI)) {
|
|
$$ = nullptr;
|
|
YYABORT;
|
|
}
|
|
|
|
if (predicateList)
|
|
$$ = new Step($1, Step::NodeTest(Step::NodeTest::NameTest, localName, namespaceURI), WTFMove(*predicateList));
|
|
else
|
|
$$ = new Step($1, Step::NodeTest(Step::NodeTest::NameTest, localName, namespaceURI));
|
|
}
|
|
|
|
|
AbbreviatedStep
|
|
;
|
|
|
|
AxisSpecifier:
|
|
AXISNAME
|
|
|
|
|
'@'
|
|
{
|
|
$$ = Step::AttributeAxis;
|
|
}
|
|
;
|
|
|
|
NodeTest:
|
|
NODE '(' ')'
|
|
{
|
|
$$ = new Step::NodeTest(Step::NodeTest::AnyNodeTest);
|
|
}
|
|
|
|
|
TEXT_ '(' ')'
|
|
{
|
|
$$ = new Step::NodeTest(Step::NodeTest::TextNodeTest);
|
|
}
|
|
|
|
|
COMMENT '(' ')'
|
|
{
|
|
$$ = new Step::NodeTest(Step::NodeTest::CommentNodeTest);
|
|
}
|
|
|
|
|
PI '(' ')'
|
|
{
|
|
$$ = new Step::NodeTest(Step::NodeTest::ProcessingInstructionNodeTest);
|
|
}
|
|
|
|
|
PI '(' LITERAL ')'
|
|
{
|
|
String literal = adoptRef($3);
|
|
$$ = new Step::NodeTest(Step::NodeTest::ProcessingInstructionNodeTest, literal.stripWhiteSpace());
|
|
}
|
|
;
|
|
|
|
OptionalPredicateList:
|
|
/* empty */
|
|
{
|
|
$$ = nullptr;
|
|
}
|
|
|
|
|
PredicateList
|
|
;
|
|
|
|
PredicateList:
|
|
Predicate
|
|
{
|
|
$$ = new Vector<std::unique_ptr<Expression>>;
|
|
$$->append(std::unique_ptr<Expression>($1));
|
|
}
|
|
|
|
|
PredicateList Predicate
|
|
{
|
|
$$ = $1;
|
|
$$->append(std::unique_ptr<Expression>($2));
|
|
}
|
|
;
|
|
|
|
Predicate:
|
|
'[' Expr ']'
|
|
{
|
|
$$ = $2;
|
|
}
|
|
;
|
|
|
|
DescendantOrSelf:
|
|
SLASHSLASH
|
|
{
|
|
$$ = new Step(Step::DescendantOrSelfAxis, Step::NodeTest(Step::NodeTest::AnyNodeTest));
|
|
}
|
|
;
|
|
|
|
AbbreviatedStep:
|
|
'.'
|
|
{
|
|
$$ = new Step(Step::SelfAxis, Step::NodeTest(Step::NodeTest::AnyNodeTest));
|
|
}
|
|
|
|
|
DOTDOT
|
|
{
|
|
$$ = new Step(Step::ParentAxis, Step::NodeTest(Step::NodeTest::AnyNodeTest));
|
|
}
|
|
;
|
|
|
|
PrimaryExpr:
|
|
VARIABLEREFERENCE
|
|
{
|
|
String name = adoptRef($1);
|
|
$$ = new VariableReference(name);
|
|
}
|
|
|
|
|
'(' Expr ')'
|
|
{
|
|
$$ = $2;
|
|
}
|
|
|
|
|
LITERAL
|
|
{
|
|
String literal = adoptRef($1);
|
|
$$ = new StringExpression(WTFMove(literal));
|
|
}
|
|
|
|
|
NUMBER
|
|
{
|
|
String numeral = adoptRef($1);
|
|
$$ = new Number(numeral.toDouble());
|
|
}
|
|
|
|
|
FunctionCall
|
|
;
|
|
|
|
FunctionCall:
|
|
FUNCTIONNAME '(' ')'
|
|
{
|
|
String name = adoptRef($1);
|
|
$$ = XPath::Function::create(name).release();
|
|
if (!$$)
|
|
YYABORT;
|
|
}
|
|
|
|
|
FUNCTIONNAME '(' ArgumentList ')'
|
|
{
|
|
String name = adoptRef($1);
|
|
std::unique_ptr<Vector<std::unique_ptr<Expression>>> argumentList($3);
|
|
$$ = XPath::Function::create(name, WTFMove(*argumentList)).release();
|
|
if (!$$)
|
|
YYABORT;
|
|
}
|
|
;
|
|
|
|
ArgumentList:
|
|
Argument
|
|
{
|
|
$$ = new Vector<std::unique_ptr<Expression>>;
|
|
$$->append(std::unique_ptr<Expression>($1));
|
|
}
|
|
|
|
|
ArgumentList ',' Argument
|
|
{
|
|
$$ = $1;
|
|
$$->append(std::unique_ptr<Expression>($3));
|
|
}
|
|
;
|
|
|
|
Argument:
|
|
Expr
|
|
;
|
|
|
|
UnionExpr:
|
|
PathExpr
|
|
|
|
|
UnionExpr '|' PathExpr
|
|
{
|
|
$$ = new Union(std::unique_ptr<Expression>($1), std::unique_ptr<Expression>($3));
|
|
}
|
|
;
|
|
|
|
PathExpr:
|
|
LocationPath
|
|
{
|
|
$$ = $1;
|
|
}
|
|
|
|
|
FilterExpr
|
|
|
|
|
FilterExpr '/' RelativeLocationPath
|
|
{
|
|
$3->setAbsolute();
|
|
$$ = new XPath::Path(std::unique_ptr<Expression>($1), std::unique_ptr<LocationPath>($3));
|
|
}
|
|
|
|
|
FilterExpr DescendantOrSelf RelativeLocationPath
|
|
{
|
|
$3->prependStep(std::unique_ptr<Step>($2));
|
|
$3->setAbsolute();
|
|
$$ = new XPath::Path(std::unique_ptr<Expression>($1), std::unique_ptr<LocationPath>($3));
|
|
}
|
|
;
|
|
|
|
FilterExpr:
|
|
PrimaryExpr
|
|
|
|
|
PrimaryExpr PredicateList
|
|
{
|
|
std::unique_ptr<Vector<std::unique_ptr<Expression>>> predicateList($2);
|
|
$$ = new Filter(std::unique_ptr<Expression>($1), WTFMove(*predicateList));
|
|
}
|
|
;
|
|
|
|
OrExpr:
|
|
AndExpr
|
|
|
|
|
OrExpr OR AndExpr
|
|
{
|
|
$$ = new LogicalOp(LogicalOp::OP_Or, std::unique_ptr<Expression>($1), std::unique_ptr<Expression>($3));
|
|
}
|
|
;
|
|
|
|
AndExpr:
|
|
EqualityExpr
|
|
|
|
|
AndExpr AND EqualityExpr
|
|
{
|
|
$$ = new LogicalOp(LogicalOp::OP_And, std::unique_ptr<Expression>($1), std::unique_ptr<Expression>($3));
|
|
}
|
|
;
|
|
|
|
EqualityExpr:
|
|
RelationalExpr
|
|
|
|
|
EqualityExpr EQOP RelationalExpr
|
|
{
|
|
$$ = new EqTestOp($2, std::unique_ptr<Expression>($1), std::unique_ptr<Expression>($3));
|
|
}
|
|
;
|
|
|
|
RelationalExpr:
|
|
AdditiveExpr
|
|
|
|
|
RelationalExpr RELOP AdditiveExpr
|
|
{
|
|
$$ = new EqTestOp($2, std::unique_ptr<Expression>($1), std::unique_ptr<Expression>($3));
|
|
}
|
|
;
|
|
|
|
AdditiveExpr:
|
|
MultiplicativeExpr
|
|
|
|
|
AdditiveExpr PLUS MultiplicativeExpr
|
|
{
|
|
$$ = new NumericOp(NumericOp::OP_Add, std::unique_ptr<Expression>($1), std::unique_ptr<Expression>($3));
|
|
}
|
|
|
|
|
AdditiveExpr MINUS MultiplicativeExpr
|
|
{
|
|
$$ = new NumericOp(NumericOp::OP_Sub, std::unique_ptr<Expression>($1), std::unique_ptr<Expression>($3));
|
|
}
|
|
;
|
|
|
|
MultiplicativeExpr:
|
|
UnaryExpr
|
|
|
|
|
MultiplicativeExpr MULOP UnaryExpr
|
|
{
|
|
$$ = new NumericOp($2, std::unique_ptr<Expression>($1), std::unique_ptr<Expression>($3));
|
|
}
|
|
;
|
|
|
|
UnaryExpr:
|
|
UnionExpr
|
|
|
|
|
MINUS UnaryExpr
|
|
{
|
|
$$ = new Negative(std::unique_ptr<Expression>($2));
|
|
}
|
|
;
|
|
|
|
%%
|