[augeas-devel] [PATCH 02/11] Notes on new XPath grammar
David Lutterkort
lutter at redhat.com
Mon Jan 26 05:41:15 UTC 2009
---
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)+
--
1.6.0.6
More information about the augeas-devel
mailing list