Appendix E. Grammar

Introduction

This appendix provides an EBNF grammar for the XQuery language. This grammar differs from the official one printed in the standard only in presentation (for example, some names have been changed and some productions cleaned up to make the grammar easier to read).

XQuery borrows two definitions from the XML 1.0 and XML Names specifications: Char and NCName. Because these definitions involve large character tables, I didn't include them here but instead refer you to the URLs in the grammar below.

The XQuery grammar requires that characters be recognized and parsed differently in certain contexts (i.e., a context-sensitive lexer). For example, within element or attribute content, characters are parsed differently than outside it. XQuery also requires that whitespace be handled differently in some contexts.

In general, XQuery requires three characters of lookahead to handle expressions like XML comments, XQuery pragmas, and CDATA sections. XQuery often requires one or two tokens of lookahead to disambiguate production choices.

The XQuery Grammar

Expressions on the left consist of the productions on the right of the ::= symbol. Quoted strings and regular expression character ranges indicate literal text. The EBNF symbols *, +, ?, |, and () are used with their usual meanings (zero or more, one or more, zero or one, choice, and group, respectively).

Example E.1. The XQuery grammar

Module         ::= Version? (Main | Library)
Main           ::= Prolog QueryBody
Library        ::= ModuleDecl Prolog
ModuleDecl     ::= "module" namespace prefix "=" String ";"
Prolog         ::= ((BaseURIDecl
                 | CollationDecl
                 | DefaultNsDecl
                 | FunctionDecl
                 | ModuleImport
                 | NamespaceDecl
                 | SchemaImport
                 | ValidationDecl
                 | VarDecl
                 | XMLSpaceDecl) ";")*
Version        ::= "xquery" "version" String ";"
BaseURIDecl    ::= "declare" "base-uri" StringLiteral
CollationDecl  ::= "declare" "default" "collation" "=" String
DefaultNsDecl  ::= "declare" "default" ("element" | "function")
                   "namespace" "=" String
FunctionDecl   ::= "declare" "function" QName "(" ParamList? ")"
                   ("as" SequenceType)? (EnclosedExpr | "external")
ParamList      ::= Param ("," Param)*
Param          ::= Variable TypeDecl?
ModuleImport   ::= "import" "module" ("namespace" NCName "=")?
                   String ("at" String)?
NamespaceDecl  ::= "declare" "namespace" NCName "=" String
ValidationDecl ::= "declare" "validation" ("lax" | "strict" | "skip")
VarDecl        ::= "declare" S "variable" Variable TypeDecl?
                   ((EnclosedExpr) | "external")
XMLSpaceDecl   ::= "declare" "xmlspace" "=" ("preserve" | "strip")
QueryBody      ::= Expr
Expr           ::= ExprSingle ("," ExprSingle)*
ExprSingle     ::= FLWOR
                 | Quantified
                 | Typeswitch
                 | Conditional
                 | Disjunction
FLWOR          ::= (For | Let)+ Where? OrderBy? Return
For            ::= "for" ForDecl ("," ForDecl)*
ForDecl        ::= Variable TypeDecl? PositionVar? "in" ExprSingle
PositionVar    ::= "at" Variable
Let            ::= "let" LetDecl ("," LetDecl)*
LetDecl        ::= Variable TypeDecl? ":=" ExprSingle
Where          ::= "where" Expr
OrderBy        ::= "stable"? "order" "by" OrderByList
OrderByList    ::= OrderSpec ("," OrderSpec)*
OrderSpec      ::= ExprSingle OrderModifier
OrderModifier ::= ("ascending" | "descending")?
                   ("empty" ("greatest" | "least"))?
                   ("collation" String)?
Return         ::= "return" ExprSingle
Quantified    ::= ("some" | "every") QuantList "satisfies" ExprSingle
QuantList      ::= QuantDecl ("," QuantDecl)*
QuantDecl      ::= Variable TypeDecl? "in" ExprSingle
Typeswitch     ::= "typeswitch" "(" Expr ")" CaseClause+
                   "default" Variable? "return" ExprSingle
CaseClause     ::= "case" (Variable "as")? SequenceType
                   "return" ExprSingle
Conditional    ::= "if" "(" Expr ")" "then" Expr "else" ExprSingle
Disjunction    ::= Conjunction ( "or" Conjunction )*
Conjunction    ::= InstanceOf ( "and" InstanceOf )*
InstanceOf     ::= TreatAs ( "instance" "of" SequenceType )?
TreatAs        ::= CastableAs ( "treat" "as" SequenceType )?
CastableAs     ::= CastAs ( "castable" "as" SingleType )?
CastAs         ::= Comparison ( "cast" "as" SingleType )?
Comparison     ::= Range ( CompOp Range)?
CompOp         ::= ValueComp
                 | GeneralComp
                 | NodeComp
                 | OrderComp
ValueComp      ::= "eq" | "ne" | "lt" | "le" | "gt" | "ge" 
GeneralComp    ::= "=" | "!=" | "<" | "<=" | ">" | ">=" 
NodeComp       ::= "is" 
OrderComp      ::= "<<" | ">>" 
Range          ::= Addition ( "to" Addition )?
Addition       ::= Multiplication ( ("+" | "-") Multiplication )*
Multiplication ::= Unary ( ("*" | "div" | "idiv" | "mod") Unary )*
Unary          ::= ("-" | "+")* Union
Union          ::= Set ( ("union" | "|") Set )*
Set            ::= Value ( ("intersect" | "except") Value )*
Value          ::= Validation | Path
Path           ::= ("/" RelativePath?)
                 | ("//" RelativePath)
                 | RelativePath
RelativePath   ::= StepExpr (("/" | "//") StepExpr)*
StepExpr       ::= AxisStep | FilterStep
AxisStep       ::= Step Predicate*
FilterStep     ::= PrimaryExpr Predicate*
Step           ::= Axis "::" NodeTest | AbbrStep
AbbrStep       ::= "." | ".." | "@" NameTest | NodeTest
Axis           ::= "ancestor"
                 | "ancestor-or-self"
                 | "attribute"
                 | "child"
                 | "descendant-or-self"
                 | "descendant"
                 | "following"
                 | "following-sibling"
                 | "parent"
                 | "preceding"
                 | "preceding-sibling"
                 | "self"
NodeTest       ::= KindTest | NameTest
NameTest       ::= QName | Wildcard
Wildcard       ::= (NCName ":")? "*"
                 | "*" ":" NCName
PrimaryExpr    ::= Literal | FunctionCall | Variable | "(" Expr? ")" | Ctor
Predicate      ::= "[" Expr "]"
Validation     ::= "validate" SchemaMode? SchemaContxt? EnclosedExpr
SchemaContxt   ::= "context" SchemaCtxtLoc | "global"
Ctor           ::= ElementCtor
                 | XmlComment
                 | XmlPI
                 | CdataSection
                 | CompDocCtor
                 | CompElemCtor
                 | CompAttrCtor
                 | CompTextCtor
                 | CompNsCtor
                 | CompCommentCtor
                 | CompPiCtor
Literal        ::= Number | String
Number         ::= Integer | Decimal | Double
FunctionCall   ::= QName "(" Expr? ")"
ElementCtor    ::= "<" QName AttrList
                   ("/>" | (">" ElemContent* "</" QName S? ">"))
XmlComment     ::= "<!—" Char* "—>"
XmlPI          ::= "<?" NCName Char* "?>"
CdataSection   ::= "<![CDATA[" Char* "]]>"
CompDocCtor    ::= "document" EnclosedExpr
CompElemCtor   ::= "element" (QName | EnclosedExpr) "{" Expr? "}"
CompAttrCtor   ::= "attribute" (QName | EnclosedExpr) "{" Expr? "}"
CompTextCtor   ::= "text" "{" Expr? "}"
CompNsCtor     ::= "namespace" NCName "{" Expr "}"
CompCommentCtor::= "comment" "{" Expr "}"
CompPiCtor     ::= "processing-information" ("{" Expr "}")? "{" Expr? "}"
ElemContent    ::= ElementChar
                 | Content
                 | ElementCtor
                 | CdataSection
                 | XmlComment
                 | XmlPI
AttrList       ::= (S (QName S? "=" S? AttrValue)?)*
AttrValue      ::= ('"' (EscapeQuot | AttrContent)* '"')
                 | ("'" (EscapeApos | AttrContent)* "'")
AttrContent    ::= QuoteAttrChar
                 | AposAttrChar
                 | Content
Content        ::= CharRef
                 | "{{"
                 | "}}"
                 | EnclosedExpr
                 | EntityRef
EnclosedExpr   ::= "{" Expr "}"
TypeDecl       ::= "as" SequenceType
SingleType     ::= AtomicType "?"?
SequenceType   ::= ItemType Occurrence?
                 | "empty" "(" ")"
ItemType       ::= AtomicType | KindTest | "item" "(" ")"
Occurrence     ::= "?" | "*" | "+"
AtomicType     ::= QName
KindTest       ::= DocumentTest
                 | ElementTest
                 | AttributeTest
                 | PITest
                 | CommentTest
                 | TextTest
                 | AnyKindTest
ElementTest    ::= "element" "(" (SchemaCtxtPath QName |
                           NodeName ("," TypeName "nillable"?)? )? ")"
AttributeTest  ::= "attribute" "(" (SchemaCtxtPath "@" QName |
                           "@" NodeName ("," TypeName)?)? ")"
NodeName       ::= QName | "*"
TypeName       ::= QName | "*"
PITest         ::= "processing-instruction" "(" String? ")"
DocumentTest   ::= "document-node" "(" ElementTest? ")"
CommentTest    ::= "comment" "(" ")"
TextTest       ::= "text" "(" ")"
AnyKindTest    ::= "node" "(" ")"
SchemaCtxtPath ::= SchemaGlobCtxt "/" (SchemaCtxtStep "/")*
SchemaCtxtLoc  ::= (SchemaCtxtPath QName) | SchemaGlobType
SchemaImport   ::= "import" "schema" SchemaPrefix? String
                   ("at" String)?
SchemaPrefix  ::= ("namespace" NCName "=")
                 | ("default" "element" "namespace" "=")
SchemaMode     ::= "lax" | "strict" | "skip"
SchemaGlobType ::= "type" "(" QName ")"
SchemaGlobCtxt ::= QName | SchemaGlobType
SchemaCtxtStep ::= QName
QName          ::= (NCName ':')? NCName
Variable       ::= "$" QName
Integer        ::= Digits
Decimal        ::= ("." Digits) | (Digits "." [0-9]*)
Double         ::= (("." Digits) | (Digits ("." [0-9]*)?))
                   ("e" | "E") ("+" | "-")? Digits
String         ::= ('"' (EntityRef | CharRef | EscQuot | [^"&])* '"')
                 | ("'" (EntityRef | CharRef | EscApos | [^'&])* "'")
EscQuot        ::= '"' '"'
EscApos        ::= "''"
S              ::= (#x20 | #x9 | #xD | #xA)+
Comment        ::= "(:" (Char | Comment)* ":)"
Pragma         ::= "(::" "pragma" QName Char* "::)"
Extension      ::= "(::" "extension" QName Char* "::)"
EntityRef      ::= "&" ("lt" | "gt" | "amp" | "quot" | "apos") ";"
Digits         ::= [0-9]+
HexDigits      ::= ([0-9] | [a-f] | [A-F])+
CharRef        ::= "&#" (Digits | ("x" HexDigits)) ";"
ElementChar    ::= Char - [{}<&]
QuoteAttrChar  ::= Char - ["{}<&]
AposAttrChar   ::= Char - ['{}<&]
Char           ::= [http://www.w3.org/TR/REC-xml#NT-Char]
NCName         ::= [http://www.w3.org/TR/REC-xml-names/#NT-NCName]

Copyright © 1998–2004 World Wide Web Consortium, (Massachusetts Institute of Technology, Institut National de Recherche en Informatique et en Automatique, Keio University). All Rights Reserved.

Reserved Keywords

XQuery prohibits the following keywords from being used as un-prefixed user-defined function names (however, you may still use them as the prefix or local parts of a qualified name): if, typeswitch, node, comment, text, and processing-instruction.

Except for this special case, XQuery doesn't reserve any keywords. For example, it is perfectly legal to write an XQuery like the one in Listing E.2.

Example E.2. XQuery doesn't reserve keywords

declare namespace namespace="namespace";
declare namespace as="as";
declare function function($function as as:as) returns item* {
  for $for in in
  return return
};

In this silly example, keywords like namespace and as are used as namespace prefixes, the function keyword is used as function and variable names, the for keyword is used as a variable name, and the in and return keywords are used as element names for path navigation.

Of course, you shouldn't write queries like this unless you're trying to win an Obfuscated XQuery contest (and then you should be prepared to beat queries like the ones in Listing E.3).

Example E.3. Obfuscated XQuery samples

(/)//(/)

***

<x>{{{()>>()<<()}}}</x>

treat as text? (true or false)

to/be or not(to/be) is the(question)

Operator Precedence

As a consequence of the grammar, the XQuery operators satisfy the precedence listed in Table E.1. Operators are listed from highest to lowest precedence, with operators of the same precedence sharing the same row in the table.

Table E.1. XQuery operator precedence (highest to lowest)

Operators

Associativity

() constructors

left to right

[]

left to right

/ //

right to left

validate

left to right

intersect   except

left to right

union   |

left to right

+   -   (unary)

right to left

*   div   idiv   mod

left to right

+   -   (binary)

left to right

to

left to right

=   !=   <   <=   <<   >>   >=   >   eq   ne   lt 
XQuery operator precedence (highest to lowest)  le  gt   ge   is

left to right

cast as

left to right

castable as

left to right

treat as

left to right

instance of

left to right

and

left to right

FLWOR   some   every   typeswitch  if   or

left to right

,

left to right

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.70.132