Gitweb: http://git.fedorahosted.org/git/augeas.git?p=augeas.git;a=commitdiff;h=f6f483a84bd1831cfa7b8d1c4d8904b449668b65 Commit: f6f483a84bd1831cfa7b8d1c4d8904b449668b65 Parent: e80494a61f11cf67bb38a3a45e6db27d47159e71 Author: David Lutterkort <[email protected]> AuthorDate: Sun Jan 11 22:10:10 2009 -0800 Committer: David Lutterkort <[email protected]> CommitterDate: Fri Jan 30 16:54:44 2009 -0800
Notes on new XPath grammar --- doc/xpath.txt | 488 +++++++++++++++++++++++++++++++++++++-------------------- 1 files changed, 320 insertions(+), 168 deletions(-) diff --git a/doc/xpath.txt b/doc/xpath.txt index 0d419f1..92d9814 100644 --- a/doc/xpath.txt +++ b/doc/xpath.txt @@ -1,169 +1,321 @@ -From http://www.w3.org/TR/2007/REC-xpath20-20070123/#id-grammar - -[ 1] XPath ::= Expr -[ 2] Expr ::= ExprSingle ("," ExprSingle)* -[ 3] ExprSingle ::= ForExpr | QuantifiedExpr | IfExpr | OrExpr -[ 4] ForExpr ::= SimpleForClause "return" ExprSingle -[ 5] SimpleForClause ::= "for" "$" VarName "in" ExprSingle ("," "$" VarName "in" ExprSingle)* -[ 6] QuantifiedExpr ::= ("some" | "every") "$" VarName "in" ExprSingle ("," "$" VarName "in" ExprSingle)* "satisfies" ExprSingle -[ 7] IfExpr ::= "if" "(" Expr ")" "then" ExprSingle "else" ExprSingle -[ 8] OrExpr ::= AndExpr ( "or" AndExpr )* -[ 9] AndExpr ::= ComparisonExpr ( "and" ComparisonExpr )* -[10] ComparisonExpr ::= RangeExpr ( (ValueComp | GeneralComp | NodeComp) RangeExpr )? -[11] RangeExpr ::= AdditiveExpr ( "to" AdditiveExpr )? -[12] AdditiveExpr ::= MultiplicativeExpr ( ("+" | "-") MultiplicativeExpr )* -[13] MultiplicativeExpr ::= UnionExpr ( ("*" | "div" | "idiv" | "mod") UnionExpr )* -[14] UnionExpr ::= IntersectExceptExpr ( ("union" | "|") IntersectExceptExpr )* -[15] IntersectExceptExpr ::= InstanceofExpr ( ("intersect" | "except") InstanceofExpr )* -[16] InstanceofExpr ::= TreatExpr ( "instance" "of" SequenceType )? -[17] TreatExpr ::= CastableExpr ( "treat" "as" SequenceType )? -[18] CastableExpr ::= CastExpr ( "castable" "as" SingleType )? -[19] CastExpr ::= UnaryExpr ( "cast" "as" SingleType )? -[20] UnaryExpr ::= ("-" | "+")* ValueExpr -[21] ValueExpr ::= PathExpr -[22] GeneralComp ::= "=" | "!=" | "<" | "<=" | ">" | ">=" -[23] ValueComp ::= "eq" | "ne" | "lt" | "le" | "gt" | "ge" -[24] NodeComp ::= "is" | "<<" | ">>" -[25] PathExpr ::= ("/" RelativePathExpr?) | ("//" RelativePathExpr) -| RelativePathExpr /* xgs: leading-lone-slash */ -[26] RelativePathExpr ::= StepExpr (("/" | "//") StepExpr)* -[27] StepExpr ::= FilterExpr | AxisStep -[28] AxisStep ::= (ReverseStep | ForwardStep) PredicateList -[29] ForwardStep ::= (ForwardAxis NodeTest) | AbbrevForwardStep -[30] ForwardAxis ::= ("child" "::") - | ("descendant" "::") - | ("attribute" "::") - | ("self" "::") - | ("descendant-or-self" "::") - | ("following-sibling" "::") - | ("following" "::") - | ("namespace" "::") -[31] AbbrevForwardStep ::= "@"? NodeTest -[32] ReverseStep ::= (ReverseAxis NodeTest) | AbbrevReverseStep -[33] ReverseAxis ::= ("parent" "::") - | ("ancestor" "::") - | ("preceding-sibling" "::") - | ("preceding" "::") - | ("ancestor-or-self" "::") -[34] AbbrevReverseStep ::= ".." -[35] NodeTest ::= KindTest | NameTest -[36] NameTest ::= QName | Wildcard -[37] Wildcard ::= "*" | (NCName ":" "*") | ("*" ":" NCName) /* ws: explicit */ -[38] FilterExpr ::= PrimaryExpr PredicateList -[39] PredicateList ::= Predicate* -[40] Predicate ::= "[" Expr "]" -[41] PrimaryExpr ::= Literal | VarRef | ParenthesizedExpr | ContextItemExpr | FunctionCall -[42] Literal ::= NumericLiteral | StringLiteral -[43] NumericLiteral ::= IntegerLiteral | DecimalLiteral | DoubleLiteral -[44] VarRef ::= "$" VarName -[45] VarName ::= QName -[46] ParenthesizedExpr ::= "(" Expr? ")" -[47] ContextItemExpr ::= "." -[48] FunctionCall ::= QName "(" (ExprSingle ("," ExprSingle)*)? ")" /* xgs: reserved-function-names */ - /* gn: parens */ -[49] SingleType ::= AtomicType "?"? -[50] SequenceType ::= ("empty-sequence" "(" ")") - | (ItemType OccurrenceIndicator?) -[51] OccurrenceIndicator ::= "?" | "*" | "+" /* xgs: occurrence-indicators */ -[52] ItemType ::= KindTest | ("item" "(" ")") | AtomicType -[53] AtomicType ::= QName -[54] KindTest ::= DocumentTest - | ElementTest - | AttributeTest - | SchemaElementTest - | SchemaAttributeTest - | PITest - | CommentTest - | TextTest - | AnyKindTest -[55] AnyKindTest ::= "node" "(" ")" -[56] DocumentTest ::= "document-node" "(" (ElementTest | SchemaElementTest)? ")" -[57] TextTest ::= "text" "(" ")" -[58] CommentTest ::= "comment" "(" ")" -[59] PITest ::= "processing-instruction" "(" (NCName | StringLiteral)? ")" -[60] AttributeTest::= "attribute" "(" (AttribNameOrWildcard ("," TypeName)?)? ")" -[61] AttribNameOrWildcard ::= AttributeName | "*" -[62] SchemaAttributeTest ::= "schema-attribute" "(" AttributeDeclaration ")" -[63] AttributeDeclaration ::= AttributeName -[64] ElementTest ::= "element" "(" (ElementNameOrWildcard ("," TypeName "?"?)?)? ")" -[65] ElementNameOrWildcard ::= ElementName | "*" -[66] SchemaElementTest ::= "schema-element" "(" ElementDeclaration ")" -[67] ElementDeclaration ::= ElementName -[68] AttributeName ::= QName -[69] ElementName ::= QName -[70] TypeName ::= QName - -Reduced grammar for Augeas: - -[ 1] XPath ::= Expr -[ 2] Expr ::= ExprSingle ("," ExprSingle)* -[ 3] ExprSingle ::= OrExpr -[ 8] OrExpr ::= AndExpr ( "or" AndExpr )* -[ 9] AndExpr ::= ComparisonExpr ( "and" ComparisonExpr )* -[10] ComparisonExpr ::= AdditiveExpr ((ValueComp | GeneralComp | NodeComp) AdditiveExpr)? -[12] AdditiveExpr ::= MultiplicativeExpr ( ("+" | "-") MultiplicativeExpr )* -[13] MultiplicativeExpr ::= UnaryExpr ( ("*" | "div" | "idiv" | "mod") UnaryExpr )* -[20] UnaryExpr ::= ("-" | "+")* PathExpr -[22] GeneralComp ::= "=" | "!=" | "<" | "<=" | ">" | ">=" -[23] ValueComp ::= "eq" | "ne" | "lt" | "le" | "gt" | "ge" -[24] NodeComp ::= "is" -[25] PathExpr ::= ("/" RelativePathExpr?) | ("//" RelativePathExpr) - | RelativePathExpr /* xgs: leading-lone-slash */ -[26] RelativePathExpr ::= StepExpr (("/" | "//") StepExpr)* -[27] StepExpr ::= FilterExpr | AxisStep -[28] AxisStep ::= (ReverseStep | ForwardStep) PredicateList -[29] ForwardStep ::= (ForwardAxis NodeTest) | AbbrevForwardStep -[30] ForwardAxis ::= ("child" "::") - | ("descendant" "::") - | ("attribute" "::") - | ("self" "::") - | ("descendant-or-self" "::") - | ("following-sibling" "::") - | ("following" "::") - | ("namespace" "::") -[31] AbbrevForwardStep ::= "@"? NodeTest -[32] ReverseStep ::= (ReverseAxis NodeTest) | AbbrevReverseStep -[33] ReverseAxis ::= ("parent" "::") - | ("ancestor" "::") - | ("preceding-sibling" "::") - | ("preceding" "::") - | ("ancestor-or-self" "::") -[34] AbbrevReverseStep ::= ".." -[35] NodeTest ::= KindTest | NameTest -[36] NameTest ::= QName | Wildcard -[37] Wildcard ::= "*" | (NCName ":" "*") | ("*" ":" NCName) /* ws: explicit */ -[38] FilterExpr ::= PrimaryExpr PredicateList -[39] PredicateList ::= Predicate* -[40] Predicate ::= "[" Expr "]" -[41] PrimaryExpr ::= Literal | VarRef | ParenthesizedExpr | ContextItemExpr | FunctionCall -[42] Literal ::= NumericLiteral | StringLiteral -[43] NumericLiteral ::= IntegerLiteral | DecimalLiteral | DoubleLiteral -[44] VarRef ::= "$" VarName -[45] VarName ::= QName -[46] ParenthesizedExpr ::= "(" Expr? ")" -[47] ContextItemExpr ::= "." -[48] FunctionCall ::= QName "(" (ExprSingle ("," ExprSingle)*)? ")" /* xgs: reserved-function-names */ - /* gn: parens */ -[51] OccurrenceIndicator ::= "?" | "*" | "+" /* xgs: occurrence-indicators */ -[54] KindTest ::= TextTest | AnyKindTest -[55] AnyKindTest ::= "node" "(" ")" -[57] TextTest ::= "text" "(" ")" -[61] AttribNameOrWildcard ::= AttributeName | "*" -[68] AttributeName ::= QName - -Really needed: - - /files/etc/hosts/*[ipaddr = "127.0.0.1"] - /files/etc/hosts/*[ipaddr = "127.0.0.1"]/alias[last() - 1] - /augeas/files//error - /files/etc/puppet/puppet.conf/section[value() = "main"]/vardir - -PathExpr ::= (("/" | "//") StepExpr)+ -StepExpr ::= (Name | "*") PredicateList -RedicateList ::= "[" PredExpr "]" * -PredExpr ::= ValueTest | PositionTest -ValueTest ::= (Name | "value()") "=" ValueLiteral -PositionTest ::= Number | "last()" ( "-" Number ) -Name ::= /[^/\[]+/ -ValueLiteral ::= '"' /[^"]*/ '"' | "'" /[^']*/ "'" | "nil" +Path expressions +================ + +In the public API, especially for aug_match and aug_get, tree nodes can be +identified with a powerful syntax, that is modelled on the XPath syntax for +XML documents. + +In the simplest case, a path expression just lists a path to some node in +the tree, for example, + + /files/etc/hosts/1/ipaddr + +If multiple nodes have the same label, one of them can be picked out by +providing its position, either counting from the first such node (at +position 1) or counting from the end. For example, the second alias of the +first host entry is + + /files/etc/hosts/1/alias[2] + +and the penultimate alias is + + /files/etc/hosts/1/alias[last() - 1] + +For /etc/hosts, each entry can be thought of as a primary key (the ipaddr) +and additional attributes relating to that primary key, namely the +canonical host name and its aliases. It is therefore natural to refer to +host entries by their ipaddr, not by the synthetic sequence number in their +path. The canonical name of the host entry with ipaddr 127.0.0.1 can be +found with + + /files/etc/hosts/*[ipaddr = "127.0.0.1"]/canonical + +or, equivalently, with + + /files/etc/hosts/*/canonical[../ipaddr = "127.0.0.1"] + +The canonical names of all hosts that have at least one alias: + + /files/etc/hosts/*/canonical[../alias] + +It is also possible to search bigger parts of the tree by using '//'. For +example, all nodes called 'ipaddr' underneath /files/etc can be found with + + /files/etc//ipaddr + +This is handy for finding errors reported by Augeas underneath /augeas: + + /augeas//error + +A lazy way to find localhost is + + /files/etc//ipaddr[. = '127.0.0.1'] + +The vardir entry in the main section of puppet.conf is at + + /files/etc/puppet/puppet.conf/section[. = "main"]/vardir + +All pam entries that use the system-auth module: + + /files/etc/pam.d/*[.//module = "system-auth"] + +More examples can be found in tests/xpath.tests + +One further extension that might be useful is to add boolean operators for +predicates, so that we can write + + /files/etc/hosts/ipaddr[../alias = 'localhost' or ../canonical = 'localhost'] + +Grammar for path expressions +============================ + +Formally, path expressions are generated by this grammar. The grammar uses +nonterminals from the XPath 1.0 grammar to point out the similarities +between XPath and Augeas path expressions. + +Unfortunately, the production for PathExpr is ambiguous, since Augeas is +too liberal in what it allows as labels for tree nodes: the expression '42' +can either be the number 42 (a PrimaryExpr) or the RelativeLocationPath +'child::42'. The reason for this ambiguity is that we allow node names like +'42' in the tree; rather than forbid them, we resolve the ambiguity by +always parsing '42' as a number, and requiring that the user write the +RelativeLocationPath in a different form, e.g. 'child::42' or './42'. + +LocationPath ::= RelativeLocationPath | AbsoluteLocationPath + +AbsoluteLocationPath ::= '/' RelativeLocationPath? + | AbbreviatedAbsoluteLocationPath +AbbreviatedAbsoluteLocationPath ::= '//' RelativeLocationPath + +RelativeLocationPath ::= Step + | RelativeLocationPath '/' Step + | AbbreviatedRelativeLocationPath +AbbreviatedRelativeLocationPath ::= RelativeLocationPath '//' Step + +Step ::= AxisSpecifier NameTest Predicate* | '.' | '..' +AxisSpecifier ::= AxisName '::' | <epsilon> +AxisName ::= 'ancestor' + | 'ancestor-or-self' + | 'child' + | 'descendant' + | 'descendant-or-self' + | 'parent' + | 'self' + | 'root' +NameTest ::= '*' | Name +Predicate ::= "[" Expr "]" * + +PathExpr ::= LocationPath | PrimaryExpr +PrimaryExpr ::= Literal + | Number + | FunctionCall +FunctionCall ::= Name '(' ( Expr ( ',' Expr )* )? ')' + +Expr ::= EqualityExpr +EqualityExpr ::= AdditiveExpr (EqualityOp AdditiveExpr)? +EqualityOp ::= "=" | "!=" +AdditiveExpr ::= MultiplicativeExpr (AdditiveOp MultiplicativeExpr)* +AdditiveOp ::= '+' | '-' +MultiplicativeExpr ::= PathExpr ('*' PathExpr)* + +Literal ::= '"' /[^"]* / '"' | "'" /[^']* / "'" Number ::= /[0-9]+/ +Name ::= /[^/\[ \t\n]+/ + + +Additional stuff +================ + +Just for reference, not really interesting as documentation + +XPath 1.0 (from http://www.w3.org/TR/xpath) +------------------------------------------- + +[ 1] LocationPath ::= RelativeLocationPath | AbsoluteLocationPath +[ 2] AbsoluteLocationPath ::= '/' RelativeLocationPath? + | AbbreviatedAbsoluteLocationPath +[ 3] RelativeLocationPath ::= Step + | RelativeLocationPath '/' Step + | AbbreviatedRelativeLocationPath +[ 4] Step ::= AxisSpecifier NodeTest Predicate* + | AbbreviatedStep +[ 5] AxisSpecifier ::= AxisName '::' + | AbbreviatedAxisSpecifier +[ 6] AxisName ::= 'ancestor' + | 'ancestor-or-self' + | 'attribute' + | 'child' + | 'descendant' + | 'descendant-or-self' + | 'following' + | 'following-sibling' + | 'namespace' + | 'parent' + | 'preceding' + | 'preceding-sibling' + | 'self' +[ 7] NodeTest ::= NameTest + | NodeType '(' ')' + | 'processing-instruction' '(' Literal ')' +[ 8] Predicate ::= '[' PredicateExpr ']' +[ 9] PredicateExpr ::= Expr +[10] AbbreviatedAbsoluteLocationPath ::= '//' RelativeLocationPath +[11] AbbreviatedRelativeLocationPath ::= RelativeLocationPath '//' Step +[12] AbbreviatedStep ::= '.' | '..' +[13] AbbreviatedAxisSpecifier ::= '@'? +[14] Expr ::= OrExpr +[15] PrimaryExpr ::= VariableReference + | '(' Expr ')' + | Literal + | Number + | FunctionCall +[16] FunctionCall ::= FunctionName '(' ( Argument ( ',' Argument )* )? ')' +[17] Argument ::= Expr +[18] UnionExpr ::= PathExpr + | UnionExpr '|' PathExpr +[19] PathExpr ::= LocationPath + | FilterExpr + | FilterExpr '/' RelativeLocationPath + | FilterExpr '//' RelativeLocationPath +[20] FilterExpr ::= PrimaryExpr + | FilterExpr Predicate +[21] OrExpr ::= AndExpr | OrExpr 'or' AndExpr +[22] AndExpr ::= EqualityExpr | AndExpr 'and' EqualityExpr +[23] EqualityExpr ::= RelationalExpr + | EqualityExpr '=' RelationalExpr + | EqualityExpr '!=' RelationalExpr +[24] RelationalExpr ::= AdditiveExpr + | RelationalExpr '<' AdditiveExpr + | RelationalExpr '>' AdditiveExpr + | RelationalExpr '<=' AdditiveExpr + | RelationalExpr '>=' AdditiveExpr + +[25] AdditiveExpr ::= MultiplicativeExpr + | AdditiveExpr '+' MultiplicativeExpr + | AdditiveExpr '-' MultiplicativeExpr +[26] MultiplicativeExpr ::= UnaryExpr + | MultiplicativeExpr MultiplyOperator UnaryExpr + | MultiplicativeExpr 'div' UnaryExpr + | MultiplicativeExpr 'mod' UnaryExpr +[27] UnaryExpr ::= UnionExpr + | '-' UnaryExpr +[28] ExprToken ::= '(' | ')' | '[' | ']' | '.' | '..' | '@' | ',' | '::' + | NameTest + | NodeType + | Operator + | FunctionName + | AxisName + | Literal + | Number + | VariableReference +[29] Literal ::= '"' [^"]* '"' + | "'" [^']* "'" +[30] Number ::= Digits ('.' Digits?)? | '.' Digits +[31] Digits ::= [0-9]+ +[32] Operator ::= OperatorName + | MultiplyOperator + | '/' | '//' | '|' | '+' | '-' | '=' | '!=' | '<' | '<=' | '>' | '>=' +[33] OperatorName ::= 'and' | 'or' | 'mod' | 'div' +[34] MultiplyOperator ::= '*' +[35] FunctionName ::= QName - NodeType +[36] VariableReference ::= '$' QName +[37] NameTest ::= '*' | NCName ':' '*' | QName +[38] NodeType ::= 'comment' | 'text' + | 'processing-instruction' + | 'node' +[39] ExprWhitespace ::= (#x20 | #x9 | #xD | #xA)+ + +Useful subset +------------- + +Big swath of XPath 1.0 that might be interesting for Augeas + +start symbol [14] Expr + +[14] Expr ::= OrExpr +[21] OrExpr ::= AndExpr ('or' AndExpr)* +[22] AndExpr ::= EqualityExpr ('and' EqualityExpr)* +[23] EqualityExpr ::= RelationalExpr + | EqualityExpr '=' RelationalExpr + | EqualityExpr '!=' RelationalExpr +[24] RelationalExpr ::= AdditiveExpr + | RelationalExpr '<' AdditiveExpr + | RelationalExpr '>' AdditiveExpr + | RelationalExpr '<=' AdditiveExpr + | RelationalExpr '>=' AdditiveExpr +[25] AdditiveExpr ::= MultiplicativeExpr + | AdditiveExpr '+' MultiplicativeExpr + | AdditiveExpr '-' MultiplicativeExpr +[26] MultiplicativeExpr ::= UnaryExpr + | MultiplicativeExpr MultiplyOperator UnaryExpr +[27] UnaryExpr ::= UnionExpr | '-' UnaryExpr +[18] UnionExpr ::= PathExpr ('|' PathExpr)* + +[19] PathExpr ::= LocationPath + | FilterExpr + | FilterExpr '/' RelativeLocationPath + | FilterExpr '//' RelativeLocationPath + +[ 1] LocationPath ::= RelativeLocationPath | AbsoluteLocationPath +[ 3] RelativeLocationPath ::= Step + | RelativeLocationPath '/' Step + | AbbreviatedRelativeLocationPath +[11] AbbreviatedRelativeLocationPath ::= RelativeLocationPath '//' Step +[ 2] AbsoluteLocationPath ::= '/' RelativeLocationPath? + | AbbreviatedAbsoluteLocationPath +[10] AbbreviatedAbsoluteLocationPath ::= '//' RelativeLocationPath + +[ 4] Step ::= AxisSpecifier NameTest Predicate* | '.' | '..' +[ 5] AxisSpecifier ::= AxisName '::' | <epsilon> + +[ 6] AxisName ::= 'ancestor' + | 'ancestor-or-self' + | 'attribute' + | 'child' + | 'descendant' + | 'descendant-or-self' + | 'following' + | 'following-sibling' + | 'namespace' + | 'parent' + | 'preceding' + | 'preceding-sibling' + | 'self' + +[ 8] Predicate ::= '[' Expr ']' + +[20] FilterExpr ::= PrimaryExpr Predicate* +[15] PrimaryExpr ::= '(' Expr ')' + | Literal + | Number + | FunctionCall +[16] FunctionCall ::= FunctionName '(' ( Argument ( ',' Argument )* )? ')' +[17] Argument ::= Expr + +Lexical structure + +[28] ExprToken ::= '(' | ')' | '[' | ']' | '.' | '..' | '@' | ',' | '::' + | NameTest + | NodeType + | Operator + | FunctionName + | AxisName + | Literal + | Number + | VariableReference +[29] Literal ::= '"' [^"]* '"' + | "'" [^']* "'" +[30] Number ::= Digits ('.' Digits?)? | '.' Digits +[31] Digits ::= [0-9]+ +[32] Operator ::= OperatorName + | MultiplyOperator + | '/' | '//' | '|' | '+' | '-' | '=' | '!=' | '<' | '<=' | '>' | '>=' +[33] OperatorName ::= 'and' | 'or' | 'mod' | 'div' +[34] MultiplyOperator ::= '*' +[35] FunctionName ::= QName - NodeType +[36] VariableReference ::= '$' QName +[37] NameTest ::= '*' | QName +[38] NodeType ::= 'comment' | 'text' + | 'processing-instruction' + | 'node' +[39] ExprWhitespace ::= (#x20 | #x9 | #xD | #xA)+ _______________________________________________ augeas-devel mailing list [email protected] https://www.redhat.com/mailman/listinfo/augeas-devel
