a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
595 lines
11 KiB
Plaintext
595 lines
11 KiB
Plaintext
%{
|
|
// XPath/XSLT Pattern parser
|
|
//
|
|
// Author: Piers Haken <piersh@friskit.com>
|
|
// Atsushi Enomoto <atsushi@ximian.com>
|
|
//
|
|
// IMPORTANT:
|
|
// Do not edit "PatternParser.jay". It is autogenerated from
|
|
// Parser.jay. It will be overwritten!
|
|
//
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.Xml;
|
|
using System.Xml.XPath;
|
|
|
|
#if XSLT_PATTERN
|
|
namespace Mono.Xml.Xsl
|
|
#else
|
|
namespace Mono.Xml.XPath
|
|
#endif
|
|
{
|
|
#if XSLT_PATTERN
|
|
internal class XsltPatternParser
|
|
#else
|
|
internal class XPathParser
|
|
#endif
|
|
{
|
|
|
|
internal System.Xml.Xsl.IStaticXsltContext Context;
|
|
|
|
#if XSLT_PATTERN
|
|
public XsltPatternParser () : this (null) {}
|
|
internal XsltPatternParser (System.Xml.Xsl.IStaticXsltContext context)
|
|
#else
|
|
public XPathParser () : this (null) {}
|
|
internal XPathParser (System.Xml.Xsl.IStaticXsltContext context)
|
|
#endif
|
|
{
|
|
Context = context;
|
|
ErrorOutput = System.IO.TextWriter.Null;
|
|
// debug = new yydebug.yyDebugSimple ();
|
|
}
|
|
|
|
internal Expression Compile (string xpath)
|
|
{
|
|
try {
|
|
Tokenizer tokenizer = new Tokenizer (xpath);
|
|
return (Expression) yyparse (tokenizer);
|
|
} catch (XPathException) {
|
|
throw;
|
|
} catch (Exception e) {
|
|
throw new XPathException ("Error during parse of " + xpath, e);
|
|
}
|
|
}
|
|
|
|
#pragma warning disable 649
|
|
static readonly int yacc_verbose_flag;
|
|
#pragma warning restore 649
|
|
|
|
private NodeSet CreateNodeTest (Axes axis, object nodeTest, ArrayList plist)
|
|
{
|
|
NodeSet test = CreateNodeTest (axis, nodeTest);
|
|
if (plist != null) {
|
|
for (int i = 0; i < plist.Count; i++)
|
|
test = new ExprFilter (test,
|
|
(Expression) plist [i]);
|
|
}
|
|
return test;
|
|
}
|
|
|
|
private NodeTest CreateNodeTest (Axes axis, object test)
|
|
{
|
|
if (test is XPathNodeType)
|
|
return new NodeTypeTest (axis,
|
|
(XPathNodeType) test, null);
|
|
else if (test is string || test == null)
|
|
return new NodeTypeTest (axis,
|
|
XPathNodeType.ProcessingInstruction,
|
|
(string) test);
|
|
XmlQualifiedName q = (XmlQualifiedName) test;
|
|
if (q == XmlQualifiedName.Empty)
|
|
return new NodeTypeTest (axis);
|
|
else
|
|
return new NodeNameTest (axis, q, Context);
|
|
}
|
|
%}
|
|
|
|
%token ERROR
|
|
%token EOF
|
|
|
|
%token SLASH "/"
|
|
%token SLASH2 "//"
|
|
%token DOT "."
|
|
%token DOT2 ".."
|
|
%token COLON2 "::"
|
|
%token COMMA ","
|
|
%token AT "@"
|
|
|
|
%token FUNCTION_NAME
|
|
|
|
%token BRACKET_OPEN "["
|
|
%token BRACKET_CLOSE "]"
|
|
%token PAREN_OPEN "("
|
|
%token PAREN_CLOSE ")"
|
|
|
|
%token AND "and"
|
|
%token OR "or"
|
|
%token DIV "div"
|
|
%token MOD "mod"
|
|
%token PLUS "+"
|
|
%token MINUS "-"
|
|
%token ASTERISK "*"
|
|
%token DOLLAR "$"
|
|
%token BAR "|"
|
|
%token EQ "="
|
|
%token NE "!="
|
|
%token LE "<="
|
|
%token GE ">="
|
|
%token LT "<"
|
|
%token GT ">"
|
|
|
|
%token ANCESTOR "ancestor"
|
|
%token ANCESTOR_OR_SELF "ancstor-or-self"
|
|
%token ATTRIBUTE "attribute"
|
|
%token CHILD "child"
|
|
%token DESCENDANT "descendant"
|
|
%token DESCENDANT_OR_SELF "descendant-or-self"
|
|
%token FOLLOWING "following"
|
|
%token FOLLOWING_SIBLING "sibling"
|
|
%token NAMESPACE "NameSpace"
|
|
%token PARENT "parent"
|
|
%token PRECEDING "preceding"
|
|
%token PRECEDING_SIBLING "preceding-sibling"
|
|
%token SELF "self"
|
|
|
|
%token COMMENT "comment"
|
|
%token TEXT "text"
|
|
%token PROCESSING_INSTRUCTION "processing-instruction"
|
|
%token NODE "node"
|
|
|
|
%token MULTIPLY "*"
|
|
|
|
%token NUMBER
|
|
%token LITERAL
|
|
%token QName
|
|
|
|
|
|
%start Expr
|
|
|
|
|
|
%left AND
|
|
%left OR
|
|
%left EQ
|
|
%left NE
|
|
%left LE
|
|
%left GE
|
|
%left LT
|
|
%left GT
|
|
|
|
%left DIV
|
|
%left MOD
|
|
%left PLUS
|
|
%left MINUS
|
|
|
|
%%
|
|
|
|
/* XSLT Pattern */
|
|
|
|
Pattern
|
|
: LocationPathPattern
|
|
| Pattern BAR LocationPathPattern
|
|
{
|
|
$$ = new ExprUNION ((NodeSet) $1, (NodeSet) $3);
|
|
}
|
|
;
|
|
|
|
LocationPathPattern
|
|
: SLASH
|
|
{
|
|
$$ = new ExprRoot ();
|
|
}
|
|
| SLASH RelativePathPattern
|
|
{
|
|
$$ = new ExprSLASH (new ExprRoot (), (NodeSet) $2);
|
|
}
|
|
| IdKeyPattern
|
|
| IdKeyPattern SLASH RelativePathPattern
|
|
{
|
|
$$ = new ExprSLASH ((Expression) $1, (NodeSet) $3);
|
|
}
|
|
| IdKeyPattern SLASH2 RelativePathPattern
|
|
{
|
|
$$ = new ExprSLASH2 ((Expression) $1, (NodeSet) $3);
|
|
}
|
|
| SLASH2 RelativePathPattern
|
|
{
|
|
$$ = new ExprSLASH2 (new ExprRoot (), (NodeSet) $2);
|
|
}
|
|
| RelativePathPattern
|
|
;
|
|
|
|
// to avoid context-sensitive tokenizer, I just reuse FUNCTION_NAME
|
|
IdKeyPattern
|
|
: FUNCTION_NAME PAREN_OPEN LITERAL PAREN_CLOSE
|
|
{
|
|
XmlQualifiedName name = (XmlQualifiedName) $1;
|
|
if (name.Name != "id" || name.Namespace != String.Empty)
|
|
throw new XPathException (String.Format ("Expected 'id' but got '{0}'", name));
|
|
$$ = ExprFunctionCall.Factory (name,
|
|
new FunctionArguments (
|
|
new ExprLiteral ((string) $3),
|
|
null),
|
|
Context);
|
|
}
|
|
| FUNCTION_NAME PAREN_OPEN LITERAL COMMA LITERAL PAREN_CLOSE
|
|
{
|
|
XmlQualifiedName name = (XmlQualifiedName) $1;
|
|
if (name.Name != "key" || name.Namespace != String.Empty)
|
|
throw new XPathException (String.Format ("Expected 'key' but got '{0}'", name));
|
|
$$ = Context.TryGetFunction (name,
|
|
new FunctionArguments (
|
|
new ExprLiteral ((string) $3),
|
|
new FunctionArguments (
|
|
new ExprLiteral ((string) $5),
|
|
null)));
|
|
}
|
|
;
|
|
|
|
RelativePathPattern
|
|
: StepPattern
|
|
| RelativePathPattern SLASH StepPattern
|
|
{
|
|
$$ = new ExprSLASH ((Expression) $1, (NodeSet) $3);
|
|
}
|
|
| RelativePathPattern SLASH2 StepPattern
|
|
{
|
|
$$ = new ExprSLASH2 ((Expression) $1, (NodeSet) $3);
|
|
}
|
|
;
|
|
|
|
StepPattern
|
|
: ChildOrAttributeAxisSpecifier NodeTest Predicates
|
|
{
|
|
$$ = CreateNodeTest ((Axes) $1, $2, (ArrayList) $3);
|
|
}
|
|
;
|
|
|
|
ChildOrAttributeAxisSpecifier
|
|
: AbbreviatedAxisSpecifier
|
|
| CHILD COLON2
|
|
{
|
|
$$ = Axes.Child;
|
|
}
|
|
| ATTRIBUTE COLON2
|
|
{
|
|
$$ = Axes.Attribute;
|
|
}
|
|
;
|
|
|
|
Predicates
|
|
: // empty
|
|
{
|
|
$$ = null;
|
|
}
|
|
| Predicates Predicate
|
|
{
|
|
ArrayList al = (ArrayList) $1;
|
|
if (al == null)
|
|
al = new ArrayList ();
|
|
al.Add ((Expression) $2);
|
|
$$ = al;
|
|
}
|
|
;
|
|
|
|
/* ---- end of XSLT Pattern ---- */
|
|
|
|
|
|
Expr
|
|
: OrExpr
|
|
;
|
|
|
|
OrExpr
|
|
: AndExpr
|
|
| OrExpr OR AndExpr
|
|
{
|
|
$$ = new ExprOR ((Expression) $1, (Expression) $3);
|
|
}
|
|
;
|
|
|
|
AndExpr
|
|
: EqualityExpr
|
|
| AndExpr AND EqualityExpr
|
|
{
|
|
$$ = new ExprAND ((Expression) $1, (Expression) $3);
|
|
}
|
|
;
|
|
|
|
EqualityExpr
|
|
: RelationalExpr
|
|
| EqualityExpr EQ RelationalExpr
|
|
{
|
|
$$ = new ExprEQ ((Expression) $1, (Expression) $3);
|
|
}
|
|
| EqualityExpr NE RelationalExpr
|
|
{
|
|
$$ = new ExprNE ((Expression) $1, (Expression) $3);
|
|
}
|
|
;
|
|
|
|
RelationalExpr
|
|
: AdditiveExpr
|
|
| RelationalExpr LT AdditiveExpr
|
|
{
|
|
$$ = new ExprLT ((Expression) $1, (Expression) $3);
|
|
}
|
|
| RelationalExpr GT AdditiveExpr
|
|
{
|
|
$$ = new ExprGT ((Expression) $1, (Expression) $3);
|
|
}
|
|
| RelationalExpr LE AdditiveExpr
|
|
{
|
|
$$ = new ExprLE ((Expression) $1, (Expression) $3);
|
|
}
|
|
| RelationalExpr GE AdditiveExpr
|
|
{
|
|
$$ = new ExprGE ((Expression) $1, (Expression) $3);
|
|
}
|
|
;
|
|
|
|
AdditiveExpr
|
|
: MultiplicativeExpr
|
|
| AdditiveExpr PLUS MultiplicativeExpr
|
|
{
|
|
$$ = new ExprPLUS ((Expression) $1, (Expression) $3);
|
|
}
|
|
| AdditiveExpr MINUS MultiplicativeExpr
|
|
{
|
|
$$ = new ExprMINUS ((Expression) $1, (Expression) $3);
|
|
}
|
|
;
|
|
|
|
MultiplicativeExpr
|
|
: UnaryExpr
|
|
| MultiplicativeExpr MULTIPLY UnaryExpr
|
|
{
|
|
$$ = new ExprMULT ((Expression) $1, (Expression) $3);
|
|
}
|
|
| MultiplicativeExpr DIV UnaryExpr
|
|
{
|
|
$$ = new ExprDIV ((Expression) $1, (Expression) $3);
|
|
}
|
|
| MultiplicativeExpr MOD UnaryExpr
|
|
{
|
|
$$ = new ExprMOD ((Expression) $1, (Expression) $3);
|
|
}
|
|
;
|
|
|
|
UnaryExpr
|
|
: UnionExpr
|
|
| MINUS UnaryExpr
|
|
{
|
|
$$ = new ExprNEG ((Expression) $2);
|
|
}
|
|
;
|
|
|
|
UnionExpr
|
|
: PathExpr
|
|
| UnionExpr BAR PathExpr
|
|
{
|
|
$$ = new ExprUNION ((Expression) $1, (Expression) $3);
|
|
}
|
|
;
|
|
|
|
PathExpr
|
|
: LocationPath
|
|
| FilterExpr
|
|
| FilterExpr SLASH RelativeLocationPath
|
|
{
|
|
$$ = new ExprSLASH ((Expression) $1, (NodeSet) $3);
|
|
}
|
|
| FilterExpr SLASH2 RelativeLocationPath
|
|
{
|
|
$$ = new ExprSLASH2 ((Expression) $1, (NodeSet) $3);
|
|
}
|
|
;
|
|
|
|
LocationPath
|
|
: RelativeLocationPath
|
|
| AbsoluteLocationPath
|
|
;
|
|
|
|
AbsoluteLocationPath
|
|
: SLASH
|
|
{
|
|
$$ = new ExprRoot ();
|
|
}
|
|
| SLASH RelativeLocationPath
|
|
{
|
|
$$ = new ExprSLASH (new ExprRoot (), (NodeSet) $2);
|
|
}
|
|
| SLASH2 RelativeLocationPath
|
|
{
|
|
$$ = new ExprSLASH2 (new ExprRoot (), (NodeSet) $2);
|
|
}
|
|
;
|
|
|
|
RelativeLocationPath
|
|
: Step
|
|
| RelativeLocationPath SLASH Step
|
|
{
|
|
$$ = new ExprSLASH ((NodeSet) $1, (NodeSet) $3);
|
|
}
|
|
| RelativeLocationPath SLASH2 Step
|
|
{
|
|
$$ = new ExprSLASH2 ((NodeSet) $1, (NodeSet) $3);
|
|
}
|
|
;
|
|
|
|
Step
|
|
: AxisSpecifier NodeTest Predicates
|
|
{
|
|
$$ = CreateNodeTest ((Axes) $1, $2, (ArrayList) $3);
|
|
}
|
|
| AbbreviatedStep
|
|
;
|
|
|
|
NodeTest // QName, XPathNodeType or string
|
|
: NameTest
|
|
| NodeType PAREN_OPEN PAREN_CLOSE
|
|
{
|
|
$$ = (XPathNodeType) $1;
|
|
}
|
|
| PROCESSING_INSTRUCTION PAREN_OPEN OptionalLiteral PAREN_CLOSE
|
|
{
|
|
$$ = (string) $3;
|
|
}
|
|
;
|
|
|
|
NameTest
|
|
: ASTERISK
|
|
{
|
|
$$ = XmlQualifiedName.Empty;
|
|
}
|
|
| QName // token QName also contains "blah:*"
|
|
;
|
|
|
|
AbbreviatedStep
|
|
: DOT
|
|
{
|
|
$$ = new NodeTypeTest (Axes.Self, XPathNodeType.All);
|
|
}
|
|
| DOT2
|
|
{
|
|
$$ = new NodeTypeTest (Axes.Parent, XPathNodeType.All);
|
|
}
|
|
;
|
|
|
|
Predicates
|
|
: /* empty */
|
|
{
|
|
$$ = null;
|
|
}
|
|
| Predicates Predicate
|
|
{
|
|
ArrayList al = (ArrayList) $1;
|
|
if (al == null)
|
|
al = new ArrayList ();
|
|
al.Add ($2);
|
|
$$ = al;
|
|
}
|
|
;
|
|
|
|
AxisSpecifier
|
|
: AxisName COLON2
|
|
{
|
|
$$ = $1;
|
|
}
|
|
| AbbreviatedAxisSpecifier
|
|
;
|
|
|
|
AbbreviatedAxisSpecifier
|
|
: /* empty */
|
|
{
|
|
$$ = Axes.Child;
|
|
}
|
|
| AT
|
|
{
|
|
$$ = Axes.Attribute;
|
|
}
|
|
;
|
|
|
|
NodeType
|
|
: COMMENT { $$ = XPathNodeType.Comment; }
|
|
| TEXT { $$ = XPathNodeType.Text; }
|
|
| PROCESSING_INSTRUCTION { $$ = XPathNodeType.ProcessingInstruction; }
|
|
| NODE { $$ = XPathNodeType.All; }
|
|
;
|
|
|
|
|
|
FilterExpr
|
|
: PrimaryExpr
|
|
| FilterExpr Predicate
|
|
{
|
|
$$ = new ExprFilter ((Expression) $1, (Expression) $2);
|
|
}
|
|
;
|
|
|
|
PrimaryExpr
|
|
: DOLLAR QName
|
|
{
|
|
Expression ret = null;
|
|
if (Context != null)
|
|
ret = Context.TryGetVariable (((XmlQualifiedName) $2).ToString ());
|
|
|
|
if (ret == null)
|
|
ret = new ExprVariable ((XmlQualifiedName) $2, Context);
|
|
|
|
$$ = ret;
|
|
}
|
|
| PAREN_OPEN Expr PAREN_CLOSE
|
|
{
|
|
$$ = new ExprParens ((Expression) $2);
|
|
}
|
|
| LITERAL
|
|
{
|
|
$$ = new ExprLiteral ((String) $1);
|
|
}
|
|
| NUMBER
|
|
{
|
|
$$ = new ExprNumber ((double) $1);
|
|
}
|
|
| FunctionCall
|
|
;
|
|
|
|
FunctionCall
|
|
: FUNCTION_NAME PAREN_OPEN OptionalArgumentList PAREN_CLOSE
|
|
{
|
|
Expression ret = null;
|
|
if (Context != null)
|
|
ret = Context.TryGetFunction ((XmlQualifiedName) $1, (FunctionArguments) $3);
|
|
if (ret == null)
|
|
ret = ExprFunctionCall.Factory ((XmlQualifiedName) $1, (FunctionArguments) $3, Context);
|
|
|
|
$$ = ret;
|
|
}
|
|
;
|
|
|
|
OptionalArgumentList
|
|
: /* empty */
|
|
| Expr OptionalArgumentListTail
|
|
{
|
|
$$ = new FunctionArguments ((Expression) $1, (FunctionArguments) $2);
|
|
}
|
|
;
|
|
|
|
OptionalArgumentListTail
|
|
: /* empty */
|
|
| COMMA Expr OptionalArgumentListTail
|
|
{
|
|
$$ = new FunctionArguments ((Expression) $2, (FunctionArguments) $3);
|
|
}
|
|
;
|
|
|
|
Predicate
|
|
: BRACKET_OPEN Expr BRACKET_CLOSE
|
|
{
|
|
$$ = $2;
|
|
}
|
|
;
|
|
|
|
AxisName
|
|
: ANCESTOR { $$ = Axes.Ancestor; }
|
|
| ANCESTOR_OR_SELF { $$ = Axes.AncestorOrSelf; }
|
|
| ATTRIBUTE { $$ = Axes.Attribute; }
|
|
| CHILD { $$ = Axes.Child; }
|
|
| DESCENDANT { $$ = Axes.Descendant; }
|
|
| DESCENDANT_OR_SELF { $$ = Axes.DescendantOrSelf; }
|
|
| FOLLOWING { $$ = Axes.Following; }
|
|
| FOLLOWING_SIBLING { $$ = Axes.FollowingSibling; }
|
|
| NAMESPACE { $$ = Axes.Namespace; }
|
|
| PARENT { $$ = Axes.Parent; }
|
|
| PRECEDING { $$ = Axes.Preceding; }
|
|
| PRECEDING_SIBLING { $$ = Axes.PrecedingSibling; }
|
|
| SELF { $$ = Axes.Self; }
|
|
;
|
|
|
|
OptionalLiteral
|
|
: /* empty */
|
|
| LITERAL
|
|
;
|
|
|
|
%%
|
|
}
|