%{ // XPath parser // // Author - Piers Haken // // TODO: FUNCTION_CALL should be a QName, not just a NCName // TODO: PROCESSING_INSTRUCTION's optional parameter // TODO: flatten argument/predicate lists in place using System; using System.Xml.XPath; namespace Mono.Xml.XPath { public class XPathParser { internal object yyparseSafe (Tokenizer tok) { return yyparseSafe (tok, null); } internal object yyparseSafe (Tokenizer tok, object yyDebug) { try { return yyparse (tok, yyDebug); } catch (XPathException e) { throw e; } catch (Exception e) { throw new XPathException ("Error during parse", e); } } internal object yyparseDebug (Tokenizer tok) { return yyparseSafe (tok, new yydebug.yyDebugSimple ()); } %} %token ERROR %token EOF %token SLASH "/" %token SLASH2 "//" %token DOT "." %token DOT2 ".." %token COLON ":" %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 NCName %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 ((NodeSet) $1, (NodeSet) $3); } ; PathExpr : RelativeLocationPath | SLASH { $$ = new ExprRoot (); } | SLASH RelativeLocationPath { $$ = new ExprSLASH (new ExprRoot (), (NodeSet) $2); } | SLASH2 RelativeLocationPath { ExprStep exprStep = new ExprStep (new NodeTypeTest (Axes.DescendantOrSelf, XPathNodeType.All)); $$ = new ExprSLASH (new ExprSLASH (new ExprRoot (), exprStep), (NodeSet) $2); } | FilterExpr | FilterExpr SLASH RelativeLocationPath { $$ = new ExprSLASH ((Expression) $1, (NodeSet) $3); } | FilterExpr SLASH2 RelativeLocationPath { ExprStep exprStep = new ExprStep (new NodeTypeTest (Axes.DescendantOrSelf, XPathNodeType.All)); $$ = new ExprSLASH (new ExprSLASH ((Expression) $1, exprStep), (NodeSet) $3); } ; RelativeLocationPath : Step | RelativeLocationPath SLASH Step { $$ = new ExprSLASH ((Expression) $1, (NodeSet) $3); } | RelativeLocationPath SLASH2 Step { ExprStep exprStep = new ExprStep (new NodeTypeTest (Axes.DescendantOrSelf, XPathNodeType.All)); $$ = new ExprSLASH (new ExprSLASH ((Expression) $1, exprStep), (NodeSet) $3); } ; Step : AxisSpecifier QName ZeroOrMorePredicates { $$ = new ExprStep (new NodeNameTest ((Axes) $1, (QName) $2), (ExprPredicates) $3); } | AxisSpecifier ASTERISK ZeroOrMorePredicates { $$ = new ExprStep (new NodeTypeTest ((Axes) $1), (ExprPredicates) $3); } | AxisSpecifier NodeType PAREN_OPEN OptionalLiteral PAREN_CLOSE ZeroOrMorePredicates { $$ = new ExprStep (new NodeTypeTest ((Axes) $1, (XPathNodeType) $2, (String) $4), (ExprPredicates) $6); } | DOT { $$ = new ExprStep (new NodeTypeTest (Axes.Self, XPathNodeType.All)); } | DOT2 { $$ = new ExprStep (new NodeTypeTest (Axes.Parent, XPathNodeType.All)); } ; 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 { $$ = new ExprVariable ((QName) $2); } | PAREN_OPEN Expr PAREN_CLOSE { $$ = $2; } | LITERAL { $$ = new ExprLiteral ((String) $1); } | NUMBER { $$ = new ExprNumber ((double) $1); } | FunctionCall ; FunctionCall : FUNCTION_NAME PAREN_OPEN OptionalArgumentList PAREN_CLOSE { $$ = new ExprFunctionCall ((String) $1, (FunctionArguments) $3); } ; OptionalArgumentList : /* empty */ | Expr OptionalArgumentListTail { $$ = new FunctionArguments ((Expression) $1, (FunctionArguments) $2); } ; OptionalArgumentListTail : /* empty */ | COMMA Expr OptionalArgumentListTail { $$ = new FunctionArguments ((Expression) $2, (FunctionArguments) $3); } ; ZeroOrMorePredicates : /* empty */ | Predicate ZeroOrMorePredicates { $$ = new ExprPredicates ((Expression) $1, (ExprPredicates) $2); } ; 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 ; QName : NCName { $$ = new NCName ((String) $1); } | NCName COLON ASTERISK { $$ = new QName ((String) $1, null); } | NCName COLON NCName { $$ = new QName ((String) $1, (String) $3); } ; %% }