# XQuery Scripting Extension Proposal

## Authors

- Matthias Brantner, 28msec, Inc., matthias.brantner@28msec.com
- Daniela Florescu, Oracle Corporation, daniela.florescu@oracle.com
- Ghislain Fourny, ETH Zurich, ghislain.fourny@inf.ethz.ch
- Josh Spiegel, Oracle Corporation, josh.spiegel@oracle.com

# Abstract

This specification defines an extension to XQuery 3.0 and XQuery Update Facility 1.0. It introduces statements including the apply, local variable declaration, assignment, while, exit and block statements, as well as statement counterparts to FLWOR, If, Switch, Typeswitch, Trycatch expressions. Statements do not return any value but can have side effects such as applying a PUL or reassigning a variable. It also introduces block expressions, which may contain statements and thus also have side effects. Such expressions must be evaluated in a specific order, which is described here. Subsequent expressions can see the effects of the expressions that came before them.

# Table of Contents

1. Introduction
2. Extensions to the Processing Model
   1. Statements
   2. Expressions
   3. Evaluation Order
   4. Snapshots
   5. Nested Snapshots
   6. Variable Binding Revalidation
   7. Main module
3. Extensions to the Prolog
   1. Global Variable Declarations
   2. Function Declarations
4. Statements
   1. Apply Statement
   2. Assignment Statement
   3. Break Statement
   4. Continue Statement
   5. Exit Statement
   6. Variable Declaration Statement
   7. While Statement
5. Statement counterparts of existing expressions
   1. FLWOR Statements and Expressions
   2. Conditional Statements and Expressions
   3. Switch Statements and Expressions
   4. Try-Catch Statements and Expressions
   5. Typeswitch Statements and Expressions
   6. Block Statements and Expressions
6. Changes to existing expressions
   1. Direct and Computed Node Constructors
   2. Filter and quantified expressions.
   3. Other Expressions
7. Example
8. Extra-Grammatical Constraints
9. Alternative simplified grammar for LL-Parsers

# 1. Introduction

XQuery Scripting Extension Proposal extends XQuery 3.0, enabling it to serve as a scripting language in order to satisfy XQuery Scripting Requirements. A prerequisite for this extension is XQuery Update Facility 1.0. The following abbreviations are used in this specification: [XQUF is an abbreviation for XQuery Update Facility 1.0.] [XQSX is an abbreviation for XQuery Scripting Extension.]

XQSX has the following properties:

- It is a strict superset of XQuery 3.0, in the sense that all valid XQuery 3.0 expressions are also valid XQSX expressions and have the same meaning.

- It is a strict superset of XQUF, in the sense that all valid XQUF expressions are also valid XQSX expressions and have the same meaning.

This specification makes use of the prefix an for some annotations, bound with the namespace http://www.zorba-xquery.com/annotations

# 2. Extensions to the Processing Model

Expressions in XQSX may have side-effects that are visible to subsequent expressions (according to their evaluation order). This requires a number of extensions to the XQuery 3.0 and XQUF processing model.

## 2.1. Statements

[A statement is a grammatical construct which does not return anything (no XDM, no PUL) but can have side-effects. Statements have to be executed in the evaluation order defined in XQSX.]

XQSX introduces the following statements:

- Apply statements

- Variable declaration statements

- Variable assignment statements

- Control flow statements: While, Break, Continue and Exit

- Statements which have expression counterparts: If-Then-Else, FLWOR, Try-Catch, Switch, Typeswitch and Block.

## 2.2. Expressions

### 2.2.1. Updating Expressions

XQSX builds on top of XQuery 3.0 and XQuery Update 1.0, so that it keeps the same constraints about an expression being simple (if it returns an empty PUL), updating (if it returns an empty XDM) or vacuous (if both are empty).

This specification takes into account the fact that the XQUF specification might evolve and allow an updating expression to return both a PUL and an XDM. We use the terminology of "non-updating" for simple expressions.

The composability constraints and category rules for updating expressions are inherited from the XQUF specification. Composability constraints are given for updating expressions in new expressions as well as for sequential expressions.

### 2.2.2. Sequential Expressions

In addition to the updating/non-updating categorization, XQSX introduces another dimension to classify expressions: sequential/non-sequential expressions.

1. [A sequential expression is an expression that can have side effects other than constructing a new node or raising an error.] Side effects include applying updates to an XDM instance, altering the dynamic context, or affecting the flow of control.

   An expression is sequential if it contains, directly or nested:

   - a call to a sequential function.

   - an assign statement, and the affected variable is declared outside of the expression.

   - an apply statement, the operand of which is updating.

   - a break or continue statement without FLWOR or while statement inbetween in the expression tree.

   - an exit statement.

   The side effects of a sequential expression are immediately effective and are visible to subsequent expressions. Because of their side effects, sequential expressions must be evaluated in evaluation order, as defined in this specification. In addition to its side effects, a sequential expression may return an XDM instance.

2. [A non-sequential expression is an expression that is is not sequential.]

The classification of each expression into one of the above categories is performed by static analysis.

Note that updating/non-updating and sequential/non-sequential are two orthogonal classification dimensions. Hence, an expression can be non-updating and non-sequential, non-updating and sequential, or updating and non-sequential.

## 2.3. Evaluation Order

[XQSX defines an evaluation order on many kinds of XQuery expressions, which is the order that operand expressions must be evaluated in order to determine what side-effects are visible to later expressions.]

Unless otherwise stated, in an evaluation of a sequential expression or of a statement, the operand expressions or statements must be evaluated exactly once, from left to right.

An implementation may use any execution strategy as long as the result complies with the semantics of this ordering.

## 2.4. Snapshots

The term snapshot is defined in XQuery Update Facility as follows: [A snapshot is a scope within which expressions are evaluated with respect to a fixed XDM instance, accessible through the dynamic context's bindings, and updates are held pending.] A snapshot is terminated by invocation of the upd:applyUpdates operation. Unlike XQUF, XQSX permits an XQuery program to contain more than one snapshot.

XQuery 1.0 and XPath 2.0 Functions and Operators defines certain functions as stable. Stable functions such as fn:current-time and fn:doc are defined to return the same result given the same arguments within an execution scope. XQSX permits an XQuery program to contain more than one execution scope.

In XQSX, a snapshot and execution scope is defined as the lapse between two side effects to the environment, reachable through the dynamic context, on which the XQuery program operates.

Each of the following events marks the end of the current snapshot and execution scope, and the beginning of a new one:

- The invocation of upd:applyUpdates,

- Calling an external, sequential function,

- Assigning a new value to a variable.

## 2.5. Nested Snapshots

To avoid nested snapshots, it is forbidden for an expression to be both updating and sequential. If such is the case, a static error is raised.

## 2.6. Variable Binding Revalidation

To ensure type soundness, variable bindings are revalidated at the end of each scope to check that any updates applied have not made them invalid with repect to their declared types. It is a dynamic error if, after applying a pending update list (using upd:applyUpdates), the XDM instance bound to any in-scope variable does not match the static type of that variable according to SequenceType matching rules.

## 2.7. Main module

    0 - MainModule ::= Prolog Program

    1 - Program ::= StatementsAndOptionalExpr

    4 - StatementsAndOptionalExpr ::= Statements Expr?

A main module is redefined to be be a prolog followed by a program.

A program corresponds to the body of a block expression, except that the final expression may be omitted. If such is the case, the final expression is considered to be the empty sequence.

The program is evaluated like a block expression. The semantics are those of XQuery 3.0 or XQuery Update Facility 1.0, i.e., its XDM value is the result of the program and the PUL it returns is applied

Note:

The current XQUF specification only allows either a non-empty XDM or a non-empty PUL to be returned.

# 3. Extensions to the Prolog

## 3.1. Global Variable Declarations

    [unchanged] AnnotatedDecl ::= "declare" Annotation* (VarDecl | FunctionDecl)

    [unchanged] Annotation : =  "%" EQName ( "(" Literal ("," Literal)* ")" ) ?

    [unchanged] VarDecl	::= "variable" "$" VarName TypeDeclaration? ((":=" VarValue) | ("external" (":=" VarDefaultValue)?)))

Definitions:

XQSX allows the built-in annotations %an:assignable and %an:nonassignable to be used in a Prolog variable declaration. If both annotations are used, a static error is raised.

[An assignable prolog variable is a global variable whose declaration specifies %an:assignable, and may have its value changed by an assign statement.]

[An unassignable prolog variable is a global variable whose declaration specifies %an:nonassignable, and may not have its value changed by an assign statement.]

If an assignment qualifier is not used, the default is unassignable.

Composability Constraints:

The initializing expression of a prolog variable (whether assignable or not) must be a non-updating and non-sequential expression .

Semantics:

The semantics of declaring assignable variables are the same as the semantics of unassignable variables, except that the static type of an assignable variable without a declared type is always item()*.

## 3.2. Function Declarations

    33 - FunctionDecl ::= "function" EQName "(" ParamList? ")"
                          ("as" SequenceType)? ("{" StatementsAndOptionalExpr "}" | "external"))

    [unchanged] Annotation : =  "%" EQName ( "(" Literal ("," Literal)* ")" ) ?

    4 - StatementsAndOptionalExpr ::= Statements Expr?

Definitions:

XQSX allows the built-in annotations %an:sequential and %an:nonsequential to be used in a Prolog function declaration. If both annotations are used, a static error is raised.

[A non-sequential function is a function whose declaration specifies %an:nonsequential . ]

[A sequential function is a function whose declaration specifies the annotation %an:sequential.]

If a qualifier is not used, the default is non-sequential.

Composability Constraints:

A function body corresponds to a block expression, except that the final expression may be omitted (i.e., there are only statements). If such is the case, the final expression is considered to be the empty sequence. Therefore in the following explanations, we identify the function body with a block expression.

The body of an non-sequential function must be a non-sequential expression, except if the only reason why the expression is sequential is that it contains an exit statement. Otherwise, a static error is raised.

Semantics:

The semantics of functions are as follows. The function body is evaluated like a block expression. Its result is determined by the first exit statement encountered during evaluation of the Block. If no exit statement is encountered, the result of the function is the value returned by the block expression (an empty XDM and an empty PUL if the final expression is omitted). Other than that, the semantics is as defined in XQuery Update Facility 1.0.

# 4. Statements

XQSX extends the XQuery 1.0 syntax by adding statements to the grammar. A statement may or may not have side effects, and does not return anything. There are the following kinds of statements:

    5 - Statement ::=
          ApplyStatement
        | AssignStatement
        | BlockStatement
        | BreakStatement
        | ContinueStatement
        | ExitStatement
        | FLWORStatement
        | IfStatement
        | SwitchStatement
        | TryCatchStatement
        | TypeswitchStatement
        | VarDeclStatement
        | WhileStatement

This part presents the statements that have no expression counterpart because they provide new semantic features.

## 4.1. Apply Statement

    6 - ApplyStatement ::= ExprSimple ";"

Composability Constraints:

(none).

Semantics:

After the evaluation of SimpleExpr, the pending update list returned by this expression is applied (by upd:applyUpdates). The XDM instance returned by this expression is discarded.

Evaluation order:

SimpleExpr is evaluated exactly once before the semantics of the Apply Statement is applied.

Example:

    delete nodes ($user, $items, $bids);

## 4.2. Assignment Statement

    7 - AssignStatement ::= "$" VarName ":=" ExprSingle ";"

Composability Constraints:

The operand must be non-updating.

Semantics:

The variable on the left-hand side of the assignment must be in scope and declared assignable, otherwise a static error is raised. In particular, it must have been declared by a variable declaration, local or in the prolog.

Note:

Variables bound in FLWOR, typeswitch, or quantified expressions or statements, as well as function parameters, may not appear on the left-hand side of an assignment.

The expression on the right-hand side is evaluated, resulting in an XDM instance.

If the XDM instance returned by the expression on the right-hand side does not match the declared type of the variable according to SequenceType matching rules, a type error is raised . If the types match, the XDM instance returned by the expression is bound to the variable (added to variable values in the dynamic context.)

Evaluation order:

The operand expression is evaluated exactly once before the semantics of the Assignment Statement is applied.

Example:

    $result := "Bidding exceeded 60000";

## 4.3. Break Statement

    9 - BreakStatement ::= "break" "loop" ";"

Composability Constraints:

(none)

Semantics:

A break statement interrupts the execution of the innermost while or FLWOR statement. The execution of the program continues as if the execution of the while or FLWOR statement had properly finished.

A static error is raised if there is no enclosing while or FLWOR statement.

Note:

A break statement does not interfere with a FLWOR expression, only with FLWOR statements.

Example:

    break loop;

## 4.4. Continue Statement

    10 - ContinueStatement ::= "continue" "loop" ";"

Composability Constraints:

(none)

Semantics:

A continue statement interrupts the current execution of the operand or return statement of the innermost while or FLWOR statement. In the case of a while statement, the resumes with a new evaluation of the test expression and, possibly, of the inner statement. In the case of a FLWOR statement, the execution resumes with the next tuple.

Note:

A continue statement does not interfere with a FLWOR expression, only with FLWOR statements.

Example:

    continue loop;

## 4.5. Exit Statement

    11 - ExitStatement ::= "exit" "returning" ExprSingle ";"

Composability Constraints:

(none)

Semantics:

An exit statement serves to define the result of the enclosing function or query body.

The operand expression of the exit expression is evaluated, resulting in an XDM instance and a pending update list.

If an exit statement is evaluated within the body of a function, further evaluation of the function body is interrupted and the XDM instance and pending update list returned by the operand expression are returned as the result of the function call.

If an exit statement is evaluated within a query body (i.e., not within the body of a function), further evaluation of the query is interrupted and the XDM instance and pending update list returned by the operand expression are returned as the result of the query.

Note:

An exit statement in a block terminates evaluation of the enclosing function body or program, not just the immediately enclosing block.

Evaluation order:

The operand expression is evaluated exactly once before the semantics of the Exit Statement is applied. Subsequent expressions or statements within the enclosing function body or query are not evaluated at all.

Example:

    exit returning local:error(concat("You cannot use the ",
                                      $request/method,
                                      " method with this URL."));

## 4.6. Variable Declaration Statement

    20 - VarDeclStatement ::= Annotation* "variable" "$" VarName TypeDeclaration? (":=" ExprSingle)?
        ("," "$" VarName TypeDeclaration? (":=" ExprSingle)?)* ";"

[The expression on the right-hand side of a variable declaration is called an initializing expression.]

[The scope expression of a variable declaration is the innermost block expression, control flow clause (then/else clause, Switch/Typeswitch/FLWOR return clause, while body clause), function body or program containing the variable declaration expression.]

Composability Constraints:

The initializing expression must be non-updating.

Semantics:

A variable declaration defines a local variable whose scope is the remainder of its scope expression (not including its initializing expression). The variable defined in a variable declaration occludes (hides) any variable of the same name that is in scope at the location where the innermost block appears.

The variable may be annotated as assignable or as unassignable. By default, it is assignable. It may only be modified by assignment statements if it is assignable.

Note:

The default for local variable declarations is different from variables declared in the prolog. The latter are unassignable if there is no annotation.

It is a static error if two or more variables declared in the same scope expression have the same expanded QName.

The type of each declared variable is added to in-scope variables in the static context of subsequent expressions in the enclosing block, function body or program. If a variable has both an explicit type declaration and an initializing expression, the value of the initializing expression must match the declared type according to SequenceType matching rules; otherwise a type error is raised . If no explicit type is declared and the variable is assignable, the type of the variable is item()*. If no explicit type is declared and the variable is unassignable, the type is statically inferred from the initializing expression.

The block variable declaration evaluates its initializing expression and binds the resulting XDM instance to the variable values in the dynamic context of subsequent expressions in the enclosing block, function body or program. If no initializing expression is present, the variable has no initial value. A reference to a variable, other than on the left-hand side of an assignment expression, is an error if the variable has no value in variable values when the reference is evaluated .

Evaluation order:

The operand expression is evaluated exactly once before the semantics of the Declaration Statement is applied.

Example:

    variable $uid := doc("users.xml")/users/user_tuple
                     [name = "Roger Smith"]/userid;

## 4.7. While Statement

    21 - WhileStatement ::= "while" "(" Expr ")" Statement

Composability Constraints:

[The expression enclosed in the parentheses of a while expression is called a test expression.]

The test expression must be non-updating.

Semantics:

The while statement is used for conditional iteration. It is evaluated as follows:

The test expression is evaluated, resulting in an XDM instance.

If the effective Boolean value of the test expression is false, the block is not evaluated. If the effective Boolean value of the test expression is true, the statement is evaluated repeatedly. Each evaluation of the statement may cause side effects that affect the result of re-evaluating the test expression. The test expression is re-evaluated after each evaluation of the statement. This process continues until the effective Boolean value of the test expression is evaluated to be false.

Evaluation order:

The test expression is evaluated once. Then if the EBV of the test expression is true, the statement is executed exactly once and the test expression is evaluated again. These steps are repeated until the EBV of the test expression is false.

Example:

In the following query, a while statement is used to compute a sequence containing all the Fibonacci numbers that are less than 100.

    variable $a as xs:integer := 0;
    variable $b as xs:integer := 1;
    variable $c as xs:integer := $a + $b;
    variable $fibseq as xs:integer* := ($a, $b);

    while ($c < 100) {
      $fibseq := ($fibseq, $c);
      $a := $b;
      $b := $c;
      $c := $a + $b;
    }

# 5. Statement counterparts of existing expressions

XQSX defines statement counterparts for control flow expressions (FLWOR, IfThenElse, Switch, Typeswitch, Trycatch). It also defines an evaluation order for statements and sequential expressions. An expression or statement following another according to this evaluation order sees the side effects of this other expression or statement.

Composability Contraints for updating expressions that are operands of any expressions defined in XQUF are extended to operand expressions of their statement counterparts (non-return expressions in FLWOR statements, test expressions in conditional statements, switch statements and typeswitch statements).

## 5.1. FLWOR Statements and Expressions

In addition to FLWOR Expressions, XQSX introduces FLWOR Statements, defined like FLWOR Expressions except that the final clause is a statement.

    12 - FLWORStatement ::= InitialClause IntermediateClause* ReturnStatement

Composability Constraints:

Note:

The XQUF specification currently forbids clauses other than return clauses of a FLWOR expression to be updating. Furthermore, it specifies that the category (updating or not) of a FLWOR expression is the same as that of its return clause.

The expressions in the window-start, window-end, order-by, group-by, where and count clauses must be non-sequential.

Semantics:

The semantics of FLWOR Expressions is unchanged.

For FLWOR Statements, the input tuple stream is generated as described in XQuery 3.0. The return statement is then executed for each tuple in its input tuple stream, using the variable bindings in the respective tuples.

Evaluation order:

Each FLWOR clause is evaluated exactly once, one after the other, from left to right. In the evaluation of the first clause, the operand expression is evaluated exactly once. In the evaluation of each other clause, the operand expression is evaluated exactly once for every tuple in the input stream produced by the former clause, in the exact same order as in the stream.

Example:

    for $book in book:search($eventNode/preceding-sibling::xhtml:input[1])
    return
    insert node
    <xhtml:tr>
      <xhtml:td>{data($book/title)}</xhtml:td>
      <xhtml:td>{data($book/isbn)}</xhtml:td>
      <xhtml:td/>
    </xhtml:tr>
    as last into $table;

The same with bulk updates:

    (for $book in book:search($eventNode/preceding-sibling::xhtml:input[1])
    return
    insert node
    <xhtml:tr>
      <xhtml:td>{data($book/title)}</xhtml:td>
      <xhtml:td>{data($book/isbn)}</xhtml:td>
      <xhtml:td/>
    </xhtml:tr>
    as last into $table);

## 5.2. Conditional Statements and Expressions

In addition to Conditional Expressions, XQSX introduces Conditional Statements, defined like Conditional Expressions except that the then and the else clause are statements.

    14 - IfStatement ::= "if" "(" Expr ")" "then" Statement "else" Statement

Composability Constraints:

Note:

The XQUF specification currently forbids the test expression to be updating.

(none)

Semantics:

The semantics of Conditional Expressions is unchanged.

For Conditional Statements, the test expression is evaluated. If the EBV of its returned XDM is true, then the then statement is executed, otherwise the else statement is executed.

Evaluation order:

The test expression is evaluated exactly once. Then, depending on the EBV of the test expression, either the then clause or the else clause (but not both) is evaluated, exactly once.

Example:

    if($newbid <= 60000) then {
      insert nodes
      <bid_tuple>
        { $uid, $item/itemno }
        <bid>{ $newbid }</bid>
        <bid_date>{ fn:current-date() }</bid_date>
      </bid_tuple>
      into doc("bids.xml")/bids;
      $result := concat("What a bargain! You got a helicopter for ",
                        $newbid);
    } else {
      $result := "Bidding exceeded 60000";
      $maximumExceeded := true();
    }

## 5.3. Switch Statements and Expressions

In addition to Switch Expressions, XQSX introduces Switch Statements, defined like Switch Expressions except that the return clauses are statements.

    15 - SwitchStatement ::= "switch" "(" Expr ")" SwitchCaseStatement+ "default" "return" Statement

Composability Constraints:

Note:

The XQUF specification does not yet take into account the switch expressions introduced in XQuery 3.0. It is outside of the scope of this XQuery Scripting specification to do so, but until the XQUF 3.0 specification is ready we consider that all operand expressions must be non-updating.

(none)

Semantics:

The semantics of Switch Expressions is unchanged.

For Switch Statements, the return statement in the effective case is executed.

Evaluation order:

The test expression is evaluated exactly once. Then, only the return clause in the effective case is evaluated, exactly once.

## 5.4. Try-Catch Statements and Expressions

In addition to Try-Catch Expressions, XQSX introduces Try-Catch Statements, defined like Try-Catch Expressions except that the try and catch clauses are statements.

    17 - TryCatchStatement ::= "try" BlockStatement ("catch" CatchErrorList BlockStatement)+

Composability Constraints:

Note:

The XQUF specification does not yet take into account the try-catch expressions introduced in XQuery 3.0. It is outside of the scope of this XQuery Scripting specification to do so, but until XQUF 3.0 is ready we will consider that try and catch expressions must be either all updating or all non-updating.

Semantics:

The semantics of Try-Catch Expressions is unchanged.

For Try-Catch Statements, the try statement is executed. If this execution raises a dynamic error or a type error, the first catch statement that "matches" the error value is executed.

Evaluation order:

If no error is dynamic or type error is raised during the evaluation of the try clause, no catch clause gets executed. Otherwise, the execution of the try clause is interrupted when this error is raised, and only the first catch statement that "matches" the error value is executed, exactly once.

## 5.5. Typeswitch Statements and Expressions

In addition to Typeswitch Expressions, XQSX introduces Typeswitch Statements, defined like Typeswitch Expressions except that the clauses are statements.

    18 - TypeswitchStatement ::= "typeswitch" "(" Expr ")" CaseStatement+ "default" ("$" VarName)? "return" Statement

Composability Constraints:

Note:

The XQUF specification currently forbids the operand expressions of a typeswitch expression to be updating.

(none)

Semantics:

The semantics of Typeswitch Expressions is unchanged.

For Typeswitch Statements, the return statement in the effective case is executed.

Evaluation order:

The test expression is evaluated exactly once. Then, only the return clause in the effective case is evaluated, exactly once.

## 5.6. Block Statements and Expressions

A block statement is a concatenation of zero, one or more statements, surrounded by curly braces.

A block expression is a concatenation of zero, one or more statements and one expression, surrounded by curly braces.

    31 - PrimaryExpr ::=
          Literal
      |   VarRef
      |   ParenthesizedExpr
      |   ContextItemExpr
      |   FunctionCall
      |   OrderedExpr
      |   UnorderedExpr
      |   Constructor
      |   FunctionItemExpr
      |   BlockExpr

    32 - BlockExpr ::= "{" StatementsAndExpr "}

    3 - StatementsAndExpr ::= Statements Expr

    2 - Statements ::= Statement*

    8 - BlockStatement ::= "{" Statements "}"

Composability Constraints:

If the final expression is non-updating, the block expression is non-updating. If the final expression is updating, the block expression is updating.

Semantics:

Each statement, as well as the final expression if any, is evaluated.

The result of a block expression is the XDM and PUL returned by its final expression.

Evaluation order:

The statements (and the final expression for a Block Expression) are evaluated in the order they appear.

Example:

    {
    variable $uid := doc("users.xml")/users/user_tuple[name = "Roger Smith"]/userid;
    variable $topbid := max(doc("bids.xml")/bids/bid_tuple[itemno = 1002]/bid);
    variable $newbid := $topbid * 1.1;

    insert nodes
    <bid_tuple>
      <userid>{ data($uid) }</userid>
      <itemno>1002</itemno>
      <bid>{ $newbid }</bid>
      <bid_date>1999-03-03</bid_date>
    </bid_tuple>
    into doc("bids.xml")/bids;

    <new_bid>{ $newbid }</new_bid>
    }

# 6. Changes to existing expressions

## 6.1. Direct and Computed Node Constructors

Node constructors are extended to allow statements in their content.

    24 - CommonContent ::= PredefinedEntityRef | CharRef | "{{" | "}}" | BlockExpr

    25 - ContentExpr ::= StatementsAndExpr

    26 - CompDocConstructor ::= "document" BlockExpr

    27 - CompAttrConstructor ::= "attribute" (EQName | ("{" Expr "}")) ("{" "}" | BlockExpr)

    28 - CompPIConstructor ::= "processing-instruction" (NCName | ("{" Expr "}")) ("{" "}" | BlockExpr)

    29 - CompCommentConstructor ::= "comment" BlockExpr

    30 - CompTextConstructor ::= "text" BlockExpr

Composability Constraints:

(none)

Semantics:

The semantics are the same as in XQuery 3.0.

The block expression is evaluated as such and its results are used as specified in XQuery 3.0.

Evaluation order:

The operands are evaluated from left to right.

## 6.2. Filter and quantified expressions.

Composability Constraints:

The expression in square brackets in a filter expression, as well as the conditional expression (second operand) in a quantified expression, must be non-sequential.

Note:

The motivation behind this restriction is that their operands can be converted to where clauses in FLWOR expressions in the query plan.

Evaluation order:

The base expression in a filter expression is evaluated exactly once.

The base expression (first operand) in a quantified expression is evaluated exactly once.

## 6.3. Other Expressions

All expressions not listed above are extended as follows. This includes the following kinds of expressions:

- Path expressions

- Concatenation expressions

- Function calls

- Range expressions

- Transform expressions

- Union, intersect, and except expressions

- Arithmetic, comparison, and logical expressions

- Ordered and unordered expressions

- Instance of, cast, castable, and treat expressions

- Validate expressions

- Extension expressions (pragmas)

Composability Constraints:

(node)

Evaluation Order:

Operand expressions are evaluated from left to right, bottom-up in the expression tree (i.e., in a function call, the parameters are evaluated before the function body is evaluated).

Note:

Since insert, delete, replace and rename are updating expressions, their operands must be non-effecting, such that the evaluation order is irrelevant for them.

Note:

In transform expressions, since the modify clause must be updating (or vacuous) according to XQUF, it must also be non-sequential. Furthermore, XQUF specifies that the return clause sees that the side-effect of applying the PUL returned by the modify expression is visible to the return expression.

# 7. Example

The following function returns true or false according to whether its parameter is a known user name, and logs the event:

    declare %an:sequential function validate-and-log($username as xs:string)
        as xs:boolean {
      variable $log as document-node() := fn:doc("log.xml");

      variable $entry as element() :=
        <access-attempt>
          <timestamp>{fn:current-dateTime()}</timestamp>
          <user-name>{$username}</user-name>
          <access-allowed/>
        </access-attempt> ;

      variable  $result as xs:boolean;

      if ($username = doc("users.xml")/current-users/user/name )
      then {
        replace value of node $entry/access-allowed with "Yes";
        $result := true();
      } else {
        replace value of node $entry/access-allowed with "No";
       $result := false();
      }

      insert node $entry as last into $log;

      fn:put($log, "log.xml");

      $result
    }

# 8. Extra-Grammatical Constraints

Although the grammar allows syntactically an empty program, this is now allowed.

A program must consist of at least one statement, or at least an expression.

# 9. Alternative simplified grammar for LL-Parsers

For implementors using LL-parsers, the grammar described in this specification (which is LR(1)) needs an arbitrary lookahead (as opposed to a lookahead of 1 for LR-parsers). This arbitrary lookahead can be removed by using a subset of this proposal specified by the following changes. This makes the grammar LL(2).

In a nutshell, block expressions are not available, and statements that could be mistaken for the beginning of an expression (with a lookahead of 2) need to be put in block statements. This happens in function bodies, node constructors and block expressions.

    [unchanged] PrimaryExpr ::= /* as in XQuery 3.0, no standalone BlockExpr */
          Literal
      |   VarRef
      |   ParenthesizedExpr
      |   ContextItemExpr
      |   FunctionCall
      |   OrderedExpr
      |   UnorderedExpr
      |   Constructor
      |   FunctionItemExpr

    Statement ::= Statement1 | Statement2

    Statement1 :=
       AssignStatement
     | BlockStatement
     | BreakStatement
     | ContinueStatement
     | ExitStatement
     | VarDeclStatement
     | WhileStatement

    Statement2 :=
       ApplyStatement
     | FLWORStatement
     | IfStatement
     | SwitchStatement
     | TryCatchStatement
     | TypeswitchStatement

    StatementsAndOptionalExpr ::= Statements1 Expr?

    Statements1 := Statement1*

# Complete Grammar

## Grammar Proposal

(Non-terminals without a rule correspond to those, unchanged, in XQuery 3.0/XQuery Update 1.0)

### New query body for main modules

    0 - MainModule ::= Prolog Program

    1 - Program ::= StatementsAndOptionalExpr

### Mixing Expressions and Statements

    2 - Statements ::= Statement*

    3 - StatementsAndExpr ::= Statements Expr

    4 - StatementsAndOptionalExpr ::= Statements Expr?

### Statements

    5 - Statement ::=
          ApplyStatement
        | AssignStatement
        | BlockStatement
        | BreakStatement
        | ContinueStatement
        | ExitStatement
        | FLWORStatement
        | IfStatement
        | SwitchStatement
        | TryCatchStatement
        | TypeswitchStatement
        | VarDeclStatement
        | WhileStatement

    6 - ApplyStatement ::= ExprSimple ";"

    7 - AssignStatement ::= "$" VarName ":=" ExprSingle ";"

    8 - BlockStatement ::= "{" Statements "}"

    9 - BreakStatement ::= "break" "loop" ";"

    10 - ContinueStatement ::= "continue" "loop" ";"

    11 - ExitStatement ::= "exit" "returning" ExprSingle ";"

    12 - FLWORStatement ::= InitialClause IntermediateClause* ReturnStatement

    13 - ReturnStatement ::= "return" Statement

    14 - IfStatement ::= "if" "(" Expr ")" "then" Statement "else" Statement

    15 - SwitchStatement ::= "switch" "(" Expr ")" SwitchCaseStatement+ "default" "return" Statement

    16 - SwitchCaseStatement ::= ("case" SwitchCaseOperand)+ "return" Statement

    17 - TryCatchStatement ::= "try" BlockStatement ("catch" CatchErrorList BlockStatement)+

    18 - TypeswitchStatement ::= "typeswitch" "(" Expr ")" CaseStatement+ "default" ("$" VarName)? "return" Statement

    19 - CaseStatement ::= "case" ("$" VarName "as")? SequenceType "return" Statement

    20 - VarDeclStatement ::= Annotation* "variable" "$" VarName TypeDeclaration? (":=" ExprSingle)?
        ("," "$" VarName TypeDeclaration? (":=" ExprSingle)?)* ";"

    21 - WhileStatement ::= "while" "(" Expr ")" Statement

### Expressions

(Separating control-flow expressions)

    22 - ExprSingle ::=
          ExprSimple
      |   FLWORExpr
      |   IfExpr
      |   SwitchExpr
      |   TryCatchExpr
      |   TypeswitchExpr

    23 - ExprSimple ::=
          QuantifiedExpr
      |   OrExpr
      |   InsertExpr
      |   DeleteExpr
      |   RenameExpr
      |   ReplaceExpr
      |   TransformExpr

(Direct element constructors)

    24 - CommonContent ::= PredefinedEntityRef | CharRef | "{{" | "}}" | BlockExpr

(Computed element constructors)

    25 - ContentExpr ::= StatementsAndExpr

    26 - CompDocConstructor ::= "document" BlockExpr

    27 - CompAttrConstructor ::= "attribute" (EQName | ("{" Expr "}")) ("{" "}" | BlockExpr)

    28 - CompPIConstructor ::= "processing-instruction" (NCName | ("{" Expr "}")) ("{" "}" | BlockExpr)

    29 - CompCommentConstructor ::= "comment" BlockExpr

    30 - CompTextConstructor ::= "text" BlockExpr

(Block expression)

    31 - PrimaryExpr ::=
          Literal
      |   VarRef
      |   ParenthesizedExpr
      |   ContextItemExpr
      |   FunctionCall
      |   OrderedExpr
      |   UnorderedExpr
      |   Constructor
      |   FunctionItemExpr
      |   BlockExpr

    32 - BlockExpr ::= "{" StatementsAndExpr "}

### Function body

    33 - FunctionDecl ::= "function" EQName "(" ParamList? ")"
                          ("as" SequenceType)? ("{" StatementsAndOptionalExpr "}" | "external"))