%{ // XPath parser // // Author - Piers Haken // using System; using System.Xml; using System.Xml.XPath; namespace Mono.Xml.XPath { public class XPathParser { internal System.Xml.Xsl.IStaticXsltContext Context; public XPathParser () : this (null) {} internal XPathParser (System.Xml.Xsl.IStaticXsltContext context) { Context = context; ErrorOutput = System.IO.TextWriter.Null; } internal Expression Compile (string xpath) { try { Tokenizer tokenizer = new Tokenizer (xpath); return (Expression) yyparse (tokenizer); } catch (XPathException e) { throw e; } catch (Exception e) { throw new XPathException ("Error during parse of " + xpath, e); } } %} %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 %% 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 : PredicatedStep | DOT { $$ = new NodeTypeTest (Axes.Self, XPathNodeType.All); } | DOT2 { $$ = new NodeTypeTest (Axes.Parent, XPathNodeType.All); } ; PredicatedStep : AxisTest | PredicatedStep Predicate { $$ = new ExprFilter ((NodeSet) $1, (Expression) $2); } ; AxisTest : AxisSpecifier QName { $$ = new NodeNameTest ((Axes) $1, (XmlQualifiedName) $2, Context); } | AxisSpecifier ASTERISK { $$ = new NodeTypeTest ((Axes) $1); } | AxisSpecifier NodeType PAREN_OPEN OptionalLiteral PAREN_CLOSE { $$ = new NodeTypeTest ((Axes) $1, (XPathNodeType) $2, (String) $4); } ; AxisSpecifier : /* empty */ { $$ = Axes.Child; } | AT { $$ = Axes.Attribute; } | AxisName COLON2 { $$ = $1; } ; 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 ; %% }