Está en la página 1de 17

Java Modeling Languaje (JML)

-- Expresiones de especificación --

Una expresión de especificación es similar a un predicado de lógica que se evalúa a verdadero


o falso. Permite describir condiciones que deben cumplirse en determinados puntos durante la
ejecución de un programa y el comportamiento de métodos y clases.

Índice

1 Operadores lógicos
2 Cuantificadores
2.1 \forall | \exists
2.2 \max | \min | \product | \sum
2.3 \num_of
3 Expresiones primarias JML para
3.1 Variable
3.2 Método
3.3 Objeto
3.4 Clase
3.5 Hilo
4 Bibliografía
5 Anexos de sintaxis

Operadores lógicos

Si a y b son expresiones booleanas JML, las siguientes también son expresiones booleanas
JML.
!a ("¬a")
a && b ("a ʌ b")
a || b (" a v b")
a ==> b ("a implica b")
a <== b ("a está implicado por b")
a <==> b ("a es equivalente a b") ó ("a si y solo si b")
a <=!=> b ¬ ("a es equivalente a b")
Donde:

 Los operadores <==> y <=!=> tienen el mismo significado que == y != respectivamente.

 La notación <==> se puede leer si y solo si. Tiene el mismo significado para los valores
booleanos que == pero tiene una precedencia más baja. Por lo tanto, la expresión:

\result <==> size == 0 es equivalente a \result == (size == 0)

 La notación <=!=> se puede leer no es equivalente a tiene el mismo significado para los
valores booleanos que != pero con una precedencia más baja. Por lo tanto, la expresión:

\result <=!=> size == 0 es equivalente a \ result != (size == 0)

 Las expresiones a ambos lados de estos operadores deben ser de tipo boolean y el
tipo del resultado también es boolean.

 El operador ==> se asocia a la derecha, pero el operador <== se asocia a la izquierda,


calculando implicaciones directas e inversas, respectivamente.

Por lo tanto:

En a ==> b si a es false entonces la expresión es true y b no se evalúa.


Luego, es equivalente a (!a || b)
P  Q = ¬P v Q

De manera similar:

En a <== b si a es true la expresión es true y b no se evalúa.


Luego, es equivalente a (a || !b).

Como se observa, a ==> b no es equivalente a b <== a.


Ejemplo1.

public class Persona {


private int edad;
//@ ensures \resut <==> this.edad>18; // es equivalente
// a \resut ==this.edad > 18
public boolean esMayorDeEdad() {
...
}
}

Cuantificadores

Todos los cuantificadores tienen la misma sintaxis: Vx Є Z.P

 Definición de una variable ligada.


 Rango de una variable.
 Expresión sobre la que se aplica el cuantificador (Predicado).

\forall | \exists

Son los cuantificadores universal y existencial respectivamente. El cuerpo de un cuantificador


universal o existencial debe ser de tipo boolean. El tipo de una expresión cuantificada universal
o existencial en su conjunto es boolean.

Sintaxis. Si a y b son expresiones booleanas JML y x es una variable de tipo t las siguientes
también son expresiones booleanas JML.

( \forall t x ; a) ("para todo x del tipo t ; a es true")


(\exists t x ; a) ("existe x de tipo t ; tal que a")
( \forall t x ; a ; b) (“para todo x del tipo t ; cumpliendo a ; b es true”)
(\exists t x ; a ; b) (“existe un x del tipo t ; cumpliendo a ; tal que b”)

Cuando el predicado de rango no es satisfacible, el valor de una expresión \forall es true y el


valor de una expresión \exists es false, como se muestra a continuación.
Ejemplo2.

( \forall int i ; 0 < i && i < 0 ; 0 < i ) == true

Ejemplo3.

( \exist int i ; 0 < i && i < 0; 0 < i ) == false

Ejemplo4. El arreglo arr esta ordenado en el índice de 0 a 9.

(\forall int i, j ; 0 <= i && i < j && j < 10 ; arr[ i ] <= arr[ j ] )

Ejemplo5 . El arreglo arr solo tiene valores menores o iguales a 2.

( \forall int i ; 0 <= i && i < arr.lenght ; arr[ i ] <= 2 )

Ejemplo6. La variable m contiene el valor máximo del arreglo arr.

( \forall int i ; 0 <= i && i < arr.lenght ; m >= arr[ i ] )

Ejemplo7. Existe un valor en el arreglo arr que es igual a m.

( \exists int i ; 0 <= i && i < arr.lenght ; m == arr[ i ] )

\max | \min | \product | \sum

Estos cuantificadores son llamados generalizados, que devuelven el máximo, mínimo, producto
o suma de los valores de las expresiones dadas, donde las variables satisfacen el rango dado.
La expresión en el cuerpo debe ser de tipo numérico incorporado, como int o double; El tipo de
la expresión cuantificada en su conjunto es el tipo de su cuerpo. Por ejemplo, las siguientes
aserciones son todas verdaderas:
Ejemplo8.

( \sum int i ; 0 <= i && i < 5 ; i ) equivale a 0 + 1 + 2 + 3 + 4 = 10


( \product int i ; 0 < i && i < 5 ; i ) equivale a 1 * 2 * 3 * 4 = 24
( \max int i ; 0 <= i && i < 5 ; i ) equivale a 4
( \min int i ; 0 <= i && i < 5 ; i -1 ) equivale a -1

Cuando el predicado de rango no es satisfacible la suma es 0 y el producto es 1.

Ejemplo9.

( \sum int i ; false ; i ) == 0


( \product double d ; false ; d*d ) == 1.0

\num_of
Este cuantificador devuelve el número de valores para sus variables para las cuales el rango y
la expresión en su cuerpo son verdaderos. El cuerpo debe tener un tipo booleano y toda la
expresión cuantificada tiene un tipo long. El significado de este cuantificador está definido por
la siguiente ecuación:

Ejemplo10.

( \num_of int i ; 0 <= i && i < 5 ; i*2 < 6 ) equivale a 3

i = 0 : 0*2 < 6 V
i = 1 : 1*2 < 6 V
i = 2 : 2*2 < 6 V
i = 3 : 3*2 < 6 F

Expresiones primarias

Las palabras clave JML que se relacionan a continuación y que son usadas en expresiones
empiezan con una barra diagonal inversa (\) para evitar el conflicto con los nombres de las
variables del programa, son los atributos considerados en expresiones JML para elementos de
un programa.
# Expresión Variable Método Objeto Clase Hilo
1 \fresh() Objetos
asignados
recientemente
2 \only_assigned() Únicas
variables
asignadas
\not_assigned() Variables que
3 no debieron ser
asignadas
\not_modified() Variables que
4 no debieron
modificarse
Únicas
\only_accessed() variables que
5
debieron ser
accesadas
6 \old() Valor previo

7 \typeof() Retorna el tipo


dinámico de
una expresión
8 \nonnullelements() Nulidad de
matriz
9 \elemtype() Retorna el tipo
de dato de un
array
10 \type Nombre de tipo

11 \lblpos
Etiquetas a
expresiones
12 \lblneg

13 \duration() Máximo de ciclos


necesarios
14 \only_called()  Llamado

\result Valor de retorno

16 \only_captured(…) Captura de
referencias
17 \working_space() Espacio de
almacenamiento
18 \max() Objetos de
bloqueo
19 \reach() Referencia

20 \space() Almacena-
miento
21 \is_initizalied() Inicialización
estática
22 \invariant() Estados
válidos
23 \lockset() Conjunto
de
bloqueos
(1) \fresh(spec-expression-list) objetos que fueron asignados solo en post-estado

Este operador afirma que objetos se asignaron recientemente. Por ejemplo, \fresh(x, y) afirma
que x e y no son nulos y que los objetos vinculados a estos identificadores no se asignaron en
el pre-estado. Los argumentos de \fresh pueden tener cualquier tipo de referencia, y el tipo de
la expresión general es booleana.

Es de anotar, que es incorrecto usar \fresh (this) en la especificación de un constructor, porque


el nuevo operador de Java asigna almacenamiento para el objeto; el trabajo del constructor es
solo inicializar ese almacenamiento.

Por ejemplo, en la condición posterior de un método de clonación, se podría escribir lo


siguiente para decir que el resultado devuelto por la clonación es un objeto recientemente
asignado que tiene el mismo estado que el receptor (esto):

\fresh(\result) && this.equals(\result);

//@ ensures \fresh (zSc);

verifica que el objeto zSc que almacena un número aleatorio generado recientemente. De esta
forma se asegura de que un objeto de número aleatorio existente no se reutilice accidental o
maliciosamente, lo que evita una cierta clase de fallas de seguridad de valor nuevo.

Por ejemplo: \fresh(\result)

Indica que el objeto retornado debe estar recién creado.

(2) \only_assigned(store-ref-list) ejecución de método únicamente se asignó a determinadas


variables

Este operador afirma que la ejecución del método solo se asigna al subconjunto de los grupos
de datos nombrados por los campos dados. Puede ser usado en la postcondición (normal y
excepcional) de un método (quizás implícitamente en una restricción de historial).
Esto incluye las asignaciones directas en el cuerpo del método y las asignaciones durante las
llamadas realizadas por el método (y los métodos a los que se llamó, etc.).
Este operador se puede aplicar a campos concretos, modelos o fantasmas. Cuando se aplica a
un campo modelo, el significado es que las ubicaciones concretas en el grupo de datos de ese
campo modelo pueden asignarse durante la ejecución del método. El tipo de una expresión
\only_assigned es booleana.

(3) \not_assigned(store-ref-list) datos que no debieron ser asignados

Este operador afirma que las ubicaciones en el grupo de datos no fueron asignadas durante la
ejecución del método que se especifica (o todos los métodos a los que se aplica una restricción
de historial). Se puede usar en postcondiciones normales y excepcionales (clausulas ensures y
signals) y en restricciones de historial.

Una store-ref denota un conjunto de localizaciones. Estos conjuntos se pueden especificar


utilizando grupos de datos y si esto se hace, el conjunto de ubicaciones indicado por una
referencia de la store-ref es la unión de todos los conjuntos de ubicaciones en el conjunto de
grupos de datos especificado.

Por su parte, \nothing denota el conjunto vacío de ubicaciones, \everything el conjunto de


todas las ubicaciones en el programa y \not_specified a un conjunto no especificado de
ubicaciones, cuyo uso está determinado por una herramienta en particular.

(4) \not_modified(store-ref-list) datos que no debieron ser modificados

Este operador afirma que los valores de los campos nombrados son los mismos en el pre-
estado y post-estado del método. Se puede usar únicamente en postcondiciones normales y
excepcionales (cláusulas ensures y signals) y en restricciones de historial.

Este operador se puede aplicar a campos concretos, modelos o fantasmas. Cuando se aplica a
un campo modelo, el significado es que solo el valor del campo modelo no ha cambiado, no
obstante los campos concretos involucrados en su representación pueden haber cambiado. El
tipo de una expresión \not_modified es booleana. Es equivalente a x == \old(x);

(5) \only_accessed(store-ref-list) únicos datos que debieron ser accesados


Este operador se usa en una postcondición de un método que especifica que la ejecución del
método únicamente lee de un subconjunto de los grupos de datos nombrados por los campos
dados.

Por ejemplo, \only_accessed (xval, yval) dice que el método no leyó campos fuera del grupo de
datos xval e yval. Esto incluye las lecturas directas en el cuerpo del método y las lecturas
durante las llamadas realizadas por el método (y los métodos a los que se llamó, etc.). Un
predicado como \only_accessed (x.f) se refiere a todo el grupo de datos nombrado por x.f no
solo a la ubicación x.f en sí misma. El operador \only_accessed puede aplicarse tanto a
campos concretos, modelos o fantasmas. Cuando se aplica a un campo modelo, el significado
es que se permite acceder a las ubicaciones (concretas) en el grupo de datos de ese campo
modelo durante la ejecución del método. El tipo de una expresión \only_accessed es boolean.

(6) old-expession

Una expresión de la forma \old (Expr) se refiere al valor que tenía la expresión Expr en el
estado previo de un método. Se refiere entonces al valor que tenía la expresión Expr cuando el
control llegó por última vez a la etiqueta de declaración Label. Es decir, se refiere al valor de la
expresión justo antes de que el control llegara por última vez a la declaración a la que se
adjunta la etiqueta.

(7) \typeof(spec-expression) retorna el tipo de una expresión

Este operador retorna el tipo dinámico1 de una expresión (un valor del tipo \TYPE). Su
argumento puede ser de tipo primitivo. Es análogo en Java a Object.getClass().

El valor de \typeof(E) es:

 indefinido si E es nulo.
 igual a E.getClass()2 si E tiene un tipo de referencia no genérico.
 igual a t.class si E tiene un tipo primitivo t

1
Es el tipo que es comprobado en tiempo de ejecución y puede ser el tipo declarado o un subtipo del tipo declarado.
Es de anotar, que el tipado dinámico es más adecuado para el prototipado.
2
El método getClass() se encuentra definido en Object como un método que devuelve una representación en
tiempo de ejecución de la clase del objeto sobre el cual podemos acceder a una serie de características del objeto
por ejemplo: el nombre de la clase, el nombre de su superclase y los nombres de los interfaces que implementa.
Por ejemplo: si c es una variable de tipo estático3 Collection que contiene un objeto de
la clase HashSet, entonces \typeof(c) es HashSet.class, que es lo mismo que
\type(HashSet).

Si E tiene un tipo estático que no es un tipo de referencia, entonces \typeof(E)


significa la instancia de java.lang.Class que representa su tipo estático.

Por ejemplo: \typeof(true) es Boolean.TYPE, que es lo mismo que \type(boolean).


Por lo tanto, una expresión de la forma \typeof(E) tiene el tipo \TYPE, que JML
considera que es lo mismo que java.lang.Class.

(8) \nonnullelements(spec-expression)

Este operador se puede usar para afirmar que una matriz y sus elementos no son nulos. Por
ejemplo, \nonnullelements(myArray), es equivalente a:

myArray != null &&


(\forall int i; 0 <= i && i < myArray.length; myArray[i] != null)

(9) \elemtype(spec-expression) Retorna el tipo de dato de un array

Este operador toma un argumento de tipo \TYPE y retorna un valor de tipo \TYPE. Si el
argumento es del tipo array, el resultado es el tipo de ese array, es decir devuelve el tipo
compartido por todos los elementos del array.

Por ejemplo: \elemtype(\type(int [ ])) es \type(int).

En consecuencia, \elemtype devuelve nulo si el argumento no es del tipo matriz, pero indefinido
si el argumento es nulo.

Por ejemplo: \elemtype(\type (int)) y


\elemtype(\type(Object)) son nulos.

3
Es el tipo declarado para la variable en el código fuente y su comprobación de tipificación se realiza durante la
compilación.
El argumento de \elemtype debe ser una expresión de tipo \TYPE que JML considera igual que
java.lang.Class y su resultado también tiene tipo \TYPE.

(10) \type(type) asigna tipo a expresiones

Este operador se puede usar para introducir literales de tipo \TYPE en expresiones. Una
expresión de la forma \type(T), donde T es un nombre de tipo, tiene el tipo \TYPE. Dado que en
JML \TYPE es lo mismo que java.lang.Class, una expresión de la forma \type(T) significa lo
mismo que T.class, si T es un tipo de referencia. Si T es un tipo primitivo, entonces \type(T) es
equivalente al valor del campo TYPE del tipo de referencia correspondiente. Por lo tanto,
\type(boolean) es igual a Boolean.TYPE.

Por ejemplo en la expresión:

\typeof(myObj) <: \type(PlusAccount)

el uso de \type(PlusAccount) se utiliza para introducir el tipo PlusAccount en este contexto de


expresión.

(11) ( \lblneg ident spec-expression ) | ()

Estas expresiones entre paréntesis que comienzan con \lblneg y \lblpos se pueden usar para
adjuntar etiquetas a las expresiones. Estas etiquetas pueden imprimirse en varios mensajes
mediante herramientas de soporte, para por ejemplo identificar una aserción que falló. Tal
expresión tiene una etiqueta y un cuerpo.
\lblneg

Por ejemplo, en

( \lblneg indexInBounds 0 <= index && index < length )

el label es indexInBounds y el cuerpo es la expresión 0 <= index && index <length.


El valor de una expresión etiquetada es el valor de su cuerpo, por lo tanto su tipo es el tipo de
su cuerpo. La idea es que si esta expresión es usada en una aserción y su valor es false (por
ejemplo, cuando se realiza una verificación de aserciones en tiempo de ejecución), entonces un
warning se imprimirá incluyendo la etiqueta indexInBounds. La forma usando \lblpos tiene una
sintaxis similar, pero debe usarse para advertencias cuando el valor de la expresión encerrada
es true. Luego, son expresiones que se utilizan para fijar etiquetas a las expresiones, las
cuales pueden ser impresas en varios mensajes, por ejemplo, para identificar a una afirmación
que ha fallado. Tal expresión tiene una etiqueta y un cuerpo.

(12) \lblpos ident spec-expression

La forma usando \lblpos tiene una sintaxis similar, pero debe usarse para advertencias cuando
el valor de la expresión encerrada es true.

(13) \duration(expression)

Este operador describe el número máximo especificado de ciclos de máquina virtual necesarios
para ejecutar la llamada al método o la expresión de invocación explícita del constructor que es
su argumento. Por ejemplo, \duration(myStack.push(o)) es el número máximo de ciclos de
máquina virtual necesarios para ejecutar la llamada myStack.push(o), de acuerdo con el
contrato del tipo estático del método push del tipo myStack, cuando se pasa el argumento o.

Para una máquina virtual Java dada, un ciclo de máquina virtual se define como el mínimo del
máximo sobre todas las instrucciones de la máquina virtual Java, i, del tiempo necesario para
ejecutar la instrucción i. La expresión de argumento pasada a \duration debe ser una llamada
a método o una expresión de invocación de constructor explícito; El tipo de expresión \duratión
es long.

(14) \only_called(method-name-list)

Este operador afirma que la ejecución del método solo se invocó desde el subconjunto de
métodos dado en la method-name-list. Puede ser usado en precondiciones normales y
excepcionales (cláusulas ensures y signals) y en restricciones de historial. El tipo de una
expresión \only_called es boolean.
Por ejemplo, \only_called(p, q) dice que métodos, aparte de p y q, fueron llamados durante la
ejecución de este método.

\only_accessed(store-ref-list)

Este operador afirma que la ejecución del método solo lee de un subconjunto de los grupos de
datos nombrados por los campos dados. Puede ser usado en la postcondición de un método,
en precondiciones normales y excepcionales (cláusulas ensures y signals) y en restricciones
de historial.

Este operador se puede aplicar a campos concretos, modelos o fantasmas. Cuando se aplica a
un campo modelo, el significado es que se permite acceder a las ubicaciones (concretas) en el
grupo de datos de ese campo modelo durante la ejecución del método. El tipo de la expresión
\only_accessed es boolean.

(15) \result

Es el valor que es retornado por un método. Puede ser usada únicamente con las cláusulas
ensures, duration y workingspace en cualquier método, excepto métodos no-void
constructores.

Las expresiones de esta forma pueden usarse en postcondiciones normales como


excepcionales, en restricciones históricas, en cláusulas de duración y espacio de trabajo, y
también en afirmaciones que aparecen en los cuerpos de los métodos.

(16) \only_captured(store-ref-list)

Este operador afirma que la ejecución del método solo capturó referencias de un subconjunto
de los grupos de datos nombrados por los campos dados. Se puede aplicar tanto a campos
concretos, modelos o fantasmas. Cuando se aplica a un campo modelo, el significado es que
las ubicaciones (concretas) en el grupo de datos de ese campo modelo pueden capturarse
durante la ejecución del método. El tipo de una expresión \only_captured es booleana.
Se captura una referencia cuando se almacena en un campo (a diferencia de una variable
local). Por lo general, un método captura un parámetro formal (o una referencia almacenada en
un campo estático) asignándolo a un campo en el receptor del método (el objeto este), un
campo en algún objeto (o un elemento de matriz) o a un campo estático.

Por ejemplo, \only_captured(xv, yv) dice que el método no capturó referencias, fuera de los
grupos de datos de xv e yv.

(17) \working_space(expression)

Este operador describe la cantidad máxima especificada de espacio de almacenamiento


dinámico, en bytes, utilizada por la llamada al método o la expresión de invocación explícita del
constructor que es su argumento. Por ejemplo, \working_space(myStack.push(o)) es el
número máximo de bytes necesarios en el montón para ejecutar la llamada myStack.push(o),
de acuerdo con el contrato del tipo estático del método push de tipo myStack, cuando se pasa
el argumento o.

Se debe tener en cuenta que la expresión utilizada como argumento para \working_space
debe considerarse como citada, en el sentido de que no debe ejecutarse; por lo tanto, el
método o constructor llamado no necesita estar libre de efectos secundarios.
Los argumentos detallados son necesarios en la especificación de la llamada porque las
llamadas a diferentes métodos, es decir, aquellos con diferentes parámetros, pueden usar
tomar diferentes cantidades de espacio. La expresión de argumento debe ser una llamada a
método o una expresión de invocación de constructor explícito; El tipo de resultado de una
expresión \ working_space es long.

(18) \max(spec-expression)

Este operador devuelve el "mayor" (como lo define <) de un conjunto de objetos de bloqueo,
dado un conjunto de bloqueo como argumento. El resultado es de tipo Object.

(19) \reach(spec-expression)
Este operador permite referirnos al conjunto de objetos alcanzables desde algún objeto en
particular. La sintaxis \reach (x) denota el JMLObjectSet más pequeño que contiene el objeto
denotado por x, si lo hay y todos los objetos accesibles a través de todos los campos de
objetos en este conjunto.

Es decir, si x es null, entonces este conjunto está vacío; de lo contrario este contiene x, todos
los objetos accesibles a través de todos los campos de x, todos los objetos accesibles a través
de todos los campos de estos objetos, y así sucesivamente, recursivamente. Si x denota un
campo modelo (o grupo de datos), entonces \reach(x) denota al JMLObjectSet más pequeño
conteniendo los objetos alcanzables desde x o accesibles desde los objetos referenciados por
los campos en ese grupo de datos.

(20) \space (spec-expression)

Este operador describe la cantidad de espacio de almacenamiento dinámico, en bytes,


asignada al objeto al que hace referencia su argumento. Por ejemplo, \space(myStack) es el
número de bytes en el montón utilizado por myStack, sin incluir los objetos que contiene. El tipo
de la expresión de especificación que es el argumento debe ser un tipo de referencia y el tipo
de resultado de la expresión \space es long.

(21) \is_initialized(reference-type)

Este operador devuelve verdadero solo cuando su argumento de tipo de referencia es una
clase que ha finalizado su inicialización estática. Es de tipo booleano.

(22) \invariant_for(spec-expression)

Este operador devuelve verdadero solo cuando su argumento satisface el invariante de su tipo
estático. Por ejemplo \invariant_for((MyClass)o) es verdadero cuando o satisface el invariante
de MyClass. Toda la expresión \invariant_for es de tipo boolean.

(23) \lockset
La primitiva \lockset denota el conjunto de bloqueos en poder del hilo actual. Es de tipo
JMLObjectSet.
Bibliografía

Leavens, G. T., Poll, E., Clifton, C., Cheon, Y., Ruby, C., Cok, D., ... & Dietl, W. (2008). JML
reference manual.

Anexos de sintaxis

Para este tipo de expresiones la sintaxis correspondiente es:

spec-quantified-expr ::= ( quantifier quantified-var-decls; [ [ predicate ];] spec-expression )


quantifier ::= \forall | \exists | \max | \min | \num_of | \product | \sum
quantified-var-decls ::= [ bound-var-modifiers ] type-spec quantified-var-declarator
[ , quantified-var-declarator ] . . .
bound-var-modifiers ::= non_null | nullable
quantified-var-declarator ::= ident [ dims ]
spec-variable-declarators ::= spec-variable-declarator [ , spec-variable-declarator ] . . .
spec-variable-declarator ::= ident [ dims ] [ = spec-initializer ]
spec-array-initializer ::= { [ spec-initializer [ , spec-initializer ] . . . [ , ] ] }
spec-initializer ::= spec-expression | spec-array-initializer

jml-primary ::= \result | \old(spec-expression) | \pre(spec-expression)


| old-expession | \not_assigned(store-ref-list)
| \not_modified(store-ref-list) | \only_accessed(store-ref-list)
| \only_assigned(store-ref-list) | \only_called(method-name-list)
| \only_captured(store-ref-list | \fresh(spec-expression-list)
| \reach(spec-expression) | \duration(expression)
| \space (spec-expression) | \working_space(expression)
| \nonnullelements(spec-expression) | \typeof(spec-expression)
| \elemtype(spec-expression) | \type(type)
| \lockset | \max(spec-expression) | \is_initialized(reference-type)
| \invariant_for(spec-expression | \lblneg ident spec-expression
| \lblpos ident spec-expression

store-ref-list ::= store-ref-keyword | store-ref [, store-ref ] . . .


store-ref ::= store-ref-expression | informal-description
store-ref-expression ::= store-ref-name [store-ref-name-su_x] . . .
store-ref-name ::= ident | super | this
store-ref-name-su_x ::= . ident | .this | `[' spec-array-ref-expr `]' | .*
spec-array-ref-expr ::= spec-expression | spec-expression .. spec-expression | *
store-ref-keyword ::= \nothing | \everything | \not_specified

----------------- Fin de documento.

También podría gustarte