Structure lexicale
Documents
Un document M est une séquence classée de caractères Unicode. M autorise différentes classes de caractères Unicode dans différentes parties d’un document M. Pour plus d’informations sur les classes de caractères Unicode, consultez la Norme Unicode version 3.0, section 4.5.
Un document se compose d’une seule expression ou de groupes de définitions organisés en sections. Les sections sont décrites en détail dans le chapitre 10. Conceptuellement, la lecture d’une expression à partir d’un document implique les étapes suivantes :
Le document est décodé en fonction de son schéma d’encodage de caractères en une séquence de caractères Unicode.
L’analyse lexicale est effectuée, traduisant ainsi le flux de caractères Unicode en un flux de jetons. Les sous-sections restantes de cette section traitent de l’analyse lexicale.
L’analyse syntaxique est effectuée, traduisant ainsi le flux de jetons sous une forme pouvant être évaluée. Ce processus est abordé dans les sections suivantes.
Conventions grammaticales
Les grammaires lexicales et syntaxiques sont présentées à l’aide de productions grammaticales. Chaque production grammaticale définit un symbole non terminal et les expansions possibles de ce symbole non terminal en séquences de symboles non terminaux ou terminaux. Dans les productions grammaticales, les symboles non terminaux+ sont affichés en italique, et les symboles terminaux sont affichés dans une police de largeur fixe.
La première ligne d’une production grammaticale est le nom du symbole non terminal en cours de définition, suivi d’un signe deux-points. Chaque ligne en retrait successive contient une expansion possible du symbole non terminal sous forme de séquence de symboles non terminaux ou terminaux. Par exemple, la production :
if-expression:
if
if-conditionthen
true-expressionelse
false-expression
définit une if-expression constituée du jeton if
, suivi d’une if-condition, suivie du jeton then
, suivi d’une true-expression, suivie du jeton else
, suivi d’une false-expression.
Quand il existe plusieurs expansions possibles d’un symbole non terminal, les alternatives sont listées sur des lignes distinctes. Par exemple, la production :
variable-list :
variable
variable-list,
variable
définit une variable-list constituée soit d’une variable, soit ou d’une variable-list suivie d’une variable. En d’autres termes, la définition est récursive et spécifie qu’une liste de variables est constituée d’une ou plusieurs variables séparées par des virgules.
Un suffixe en indice « opt » est utilisé pour indiquer un symbole facultatif. La production :
field-specification:
optional
opt field-name=
field-type
est un raccourci de :
field-specification :
field-name=
field-type
optional
field-name=
field-type
et définit une valeur field-specification pour qu’elle commence éventuellement par le symbole terminal optional
suivi d’un field-name, le symbole terminal =
, et d’un field-type.
Les alternatives sont normalement listées sur des lignes distinctes, bien que dans les cas où il existe de nombreuses alternatives, l’expression « one of » peut précéder une liste d’expansions donnée sur une seule ligne. Il s’agit simplement d’un raccourci pour lister chacune des alternatives sur une ligne distincte. Par exemple, la production :
decimal-digit : one of
0 1 2 3 4 5 6 7 8 9
est un raccourci de :
decimal-digit:
0
1
2
3
4
5
6
7
8
9
Analyse lexicale
La production lexical-unit définit la grammaire lexicale d’un document M. Chaque document M valide est conforme à cette grammaire.
lexical-unit :
lexical-elementsopt
lexical-elements :
lexical-element
lexical-element
lexical-elements
lexical-element :
whitespace
token comment
Au niveau lexical, un document M est constitué d’un flux d’éléments whitespace, comment et token. Chacune de ces productions est présentée individuellement dans les sections suivantes. Seuls les éléments token sont significatifs dans la grammaire syntaxique.
Espaces
Les espaces blancs servent à séparer les commentaires et les jetons dans un document M. Les espaces blancs comprennent le caractère espace (qui fait partie de la classe Unicode Zs), ainsi que les séquences de caractères de saut de ligne, tabulations horizontales et verticales, et sauts de page. Les séquences de caractères de saut de ligne incluent les caractères de retour chariot, saut de ligne, retour chariot suivi de saut de ligne, ligne suivante et séparateur de paragraphe.
whitespace:
Tout caractère avec la classe Unicode Zs
Caractère de tabulation horizontale (U+0009
)
Caractère de tabulation verticale (U+000B
)
Caractère de saut de page (U+000C
)
Caractère de retour chariot (U+000D
) suivi du caractère de saut de ligne (U+000A
)
new-line-character
new-line-character:
Caractère de retour chariot (U+000D
)
Caractère de saut de ligne (U+000A
)
Caractère de ligne suivante (U+0085
)
Caractère de séparateur de lignes (U+2028
)
Caractère de séparateur de paragraphes (U+2029
)
Pour la compatibilité avec les outils d’édition de code source qui ajoutent des marqueurs de fin de fichier, et pour permettre à un document d’être affiché sous la forme d’une séquence de lignes correctement terminées, les transformations suivantes sont appliquées, dans l’ordre, à un document M :
Si le dernier caractère du document est un caractère Ctrl+Z (
U+001A
), ce caractère est supprimé.Un caractère de retour chariot (
U+000D
) est ajouté à la fin du document si celui-ci n’est pas vide et que le dernier caractère du document n’est pas un retour chariot (U+000D
), un saut de ligne (U+000A
), un séparateur de lignes (U+2028
) ou un séparateur de paragraphes (U+2029
).
Commentaires
Deux formes de commentaires sont pris en charge : les commentaires sur une seule ligne et les commentaires délimités. Les commentaires sur une seule ligne commencent par les caractères //
et s’étendent jusqu’à la fin de la ligne source. Les commentaires délimités commencent par les caractères /*
et se terminent par les caractères */
.
Les commentaires délimités peuvent s’étendre sur plusieurs lignes.
comment :
single-line-comment
delimited-comment
single-line-comment :
//
single-line-comment-charactersopt
single-line-comment-characters :
single-line-comment-character single-line-comment-charactersopt
single-line-comment-character :
Tout caractère Unicode sauf un new-line-character
delimited-comment :
/*
delimited-comment-textopt asterisks/
delimited-comment-text :
delimited-comment-section delimited-comment-textopt
delimited-comment-section :
/
asterisksopt not-slash-or-asterisk
asterisks :
*
asterisksopt
not-slash-or-asterisk :
Tout caractère Unicode sauf *
ou /
Les commentaires ne peuvent pas être imbriqués. Les séquences de caractères /*
et */
n’ont aucune signification particulière dans un commentaire sur une seule ligne, et les séquences de caractères //
et /*
n’ont aucune signification particulière dans un commentaire délimité.
Les commentaires ne sont pas traités dans les littéraux de texte. L’exemple
/* Hello, world
*/
"Hello, world"
comprend un commentaire délimité.
L’exemple
// Hello, world
//
"Hello, world" // This is an example of a text literal
illustre plusieurs commentaires sur une seule ligne.
Jetons
Un jeton est un identificateur, un mot clé, un littéral, un opérateur ou un signe de ponctuation. Les espaces blancs et les commentaires sont utilisés pour séparer les jetons, mais ne sont pas considérés comme des jetons.
token :
identificateur
mot clé
littéral
operator-or-punctuator
Séquences d’échappement de caractère
Les valeurs de texte M peuvent contenir des caractères Unicode arbitraires. Les littéraux de texte, en revanche, sont limités aux caractères graphiques et nécessitent l’utilisation de séquences d’échappement pour les caractères non graphiques. Par exemple, pour inclure un retour chariot, un saut de ligne ou un caractère de tabulation dans un littéral de texte, les séquences d’échappement #(cr)
, #(lf)
et #(tab)
peuvent être utilisées, respectivement. Pour incorporer les caractères de début de séquence d’échappement #(
dans un littéral de texte, le #
lui-même doit être placé dans une séquence d’échappement :
#(#)(
Les séquences d’échappement peuvent également contenir des valeurs de point de code Unicode courtes (quatre chiffres hexadécimaux) ou longues (huit chiffres hexadécimaux). Les trois séquences d’échappement suivantes sont équivalentes :
#(000D) // short Unicode hexadecimal value
#(0000000D) // long Unicode hexadecimal value
#(cr) // compact escape shorthand for carriage return
Plusieurs codes d’échappement peuvent être inclus dans une même séquence d’échappement, séparés par des virgules. Les deux séquences suivantes sont ainsi équivalentes :
#(cr,lf)
#(cr)#(lf)
La section qui suit décrit le mécanisme standard d’échappement des caractères dans un document M.
character-escape-sequence:
#(
escape-sequence-list)
escape-sequence-list:
single-escape-sequence
single-escape-sequence,
escape-sequence-list
single-escape-sequence :
long-unicode-escape-sequence
short-unicode-escape-sequence
control-character-escape-sequence
escape-escape
long-unicode-escape-sequence :
hex-digit hex-digit hex-digit hex-digit hex-digit hex-digit hex-digit hex-digit
short-unicode-escape-sequence :
hex-digit hex-digit hex-digit hex-digit
control-character-escape-sequence :
control-character
control-character :
cr
lf
tab
escape-escape:
#
Littéraux
Un littéral est une représentation en code source d’une valeur.
literal :
logical-literal
number-literal
text-literal
null-literal
verbatim-literal
Littéraux Null
Le littéral Null est utilisé pour écrire la valeur null
. La valeur null
représente une valeur absente.
null-literal:
null
Littéraux logiques
Un littéral logique est utilisé pour écrire les valeurs true
et false
, et génère une valeur logique.
logical-literal:
true
false
Littéraux numériques
Un littéral numérique est utilisé pour écrire une valeur numérique, et génère une valeur numérique.
number-literal :
decimal-number-literal
hexadecimal-number-literal
decimal-number-literal :
decimal-digits.
decimal-digits exponent-partopt
.
decimal-digits exponent-partopt
decimal-digits exponent-partopt
decimal-digits :
decimal-digit decimal-digitsopt
decimal-digit : une des valeurs suivantes
0 1 2 3 4 5 6 7 8 9
exponent-part:
e
signopt decimal-digits
E
signopt decimal-digits
sign : une des valeurs suivantes
+ -
hexadecimal-number-literal:
0x
hex-digits
0X
hex-digits
hex-digits :
hex-digit hex-digitsopt
hex-digit : une des valeurs suivantes
0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f
Vous pouvez spécifier un nombre au format hexadécimal en faisant précéder hex-digits des caractères 0x
. Par exemple :
0xff // 255
Notez que si une virgule décimale est incluse dans un littéral numérique, elle doit être suivie d’au moins un chiffre. Par exemple, 1.3
est un littéral numérique, mais 1.
et 1.e3
n’en sont pas un.
Littéraux de texte
Un littéral de texte est utilisé pour écrire une séquence de caractères Unicode, et génère une valeur de texte.
text-literal:
"
text-literal-charactersopt"
text-literal-characters :
text-literal-character text-literal-charactersopt
text-literal-character :
single-text-character
character-escape-sequence
double-quote-escape-sequence
single-text-character :
Tout caractère sauf "
(U+0022
) ou #
(U+0023
) suivi de (
(U+0028
)
double-quote-escape-sequence:
""
(U+0022
, U+0022
)
Pour inclure des guillemets dans une valeur de texte, le guillemet est répété comme suit :
"The ""quoted"" text" // The "quoted" text
Vous pouvez utiliser la production character-escape-sequence pour écrire des caractères dans des valeurs de texte sans avoir à les encoder directement en tant que caractères Unicode dans le document. Par exemple, un retour chariot et un saut de ligne peuvent être écrits dans une valeur de texte comme suit :
"Hello world#(cr,lf)"
Littéraux textuels
Un littéral textuel est utilisé pour stocker une séquence de caractères Unicode qui ont été entrés par un utilisateur sous forme de code, mais qui ne peuvent pas être analysés correctement sous forme de code. Au moment de l’exécution, il génère une valeur d’erreur.
verbatim-literal:
#!"
text-literal-charactersopt"
Identificateurs
Un identificateur est un nom utilisé pour faire référence à une valeur. Les identificateurs peuvent être des identificateurs réguliers ou des identificateurs entre guillemets.
identifier :
regular-identifier
quoted-identifier
regular-identifier :
available-identifier
available-identifier dot-character regular-identifier
available-identifier :
keyword-or-identifier qui n’est pas un keyword
keyword-or-identifier :
identifier-start-character identifier-part-charactersopt
identifier-start-character :
letter-character
underscore-character
identifier-part-characters :
identifier-part-character identifier-part-charactersopt
identifier-part-character :
letter-character
decimal-digit-character
underscore-character
connecting-character
combining-character
formatting-character
dot-character :
.
(U+002E
)
underscore-character:
_
(U+005F
)
letter-character:
Caractère Unicode des classes Lu, Ll, Lt, Lm, Lo ou Nl
combining-character:
Caractère Unicode des classes Mn ou Mc
decimal-digit-character:
Caractère Unicode de la classe Nd
connecting-character:
Caractère Unicode de la classe Pc
formatting-character:
Caractère Unicode de la classe Cf
Vous pouvez utiliser un quoted-identifier pour autoriser l’utilisation de n’importe quelle séquence de zéro, un ou plusieurs caractères Unicode comme identificateur, y compris les mots clés, les espaces blancs, les commentaires, les opérateurs et les signes de ponctuation.
quoted-identifier:
#"
text-literal-charactersopt"
Notez que les séquences d’échappement et les guillemets doubles pour échapper des guillemets peuvent être utilisés dans un quoted-identifier, comme dans un text-literal.
L’exemple suivant utilise la mise entre guillemets d’identificateur pour les noms contenant un caractère d’espace :
[
#"1998 Sales" = 1000,
#"1999 Sales" = 1100,
#"Total Sales" = #"1998 Sales" + #"1999 Sales"
]
L’exemple suivant utilise la mise entre guillemets d’identificateur pour inclure l’opérateur +
dans un identificateur :
[
#"A + B" = A + B,
A = 1,
B = 2
]
Identificateurs généralisés
Il existe deux emplacements en M où aucune ambiguïté n’est introduite par les identificateurs qui contiennent des espaces ou qui sont des mots clés ou des littéraux numériques. Il s’agit des noms des champs d’enregistrement dans un littéral d’enregistrement et dans un opérateur d’accès aux champs ([ ]
). À ces emplacements, M autorise ces identificateurs sans avoir à utiliser des identificateurs entre guillemets.
[
Data = [ Base Line = 100, Rate = 1.8 ],
Progression = Data[Base Line] * Data[Rate]
]
Les identificateurs utilisés pour nommer et accéder aux champs sont appelés identificateurs généralisés, et sont définis comme suit :
generalized-identifier :
generalized-identifier-part
generalized-identifier séparés seulement par des espaces (U+0020
)
generalized-identifier-part
generalized-identifier-part :
generalized-identifier-segment
decimal-digit-character generalized-identifier-segment
generalized-identifier-segment :
keyword-or-identifier
keyword-or-identifier dot-character keyword-or-identifier
Mots clés
Un mot clé est une séquence de caractères semblable à un identificateur qui est réservée et qui ne peut pas être utilisée comme identificateur, sauf si vous utilisez identifier-quoting mechanism ou si un identificateur généralisé est autorisé.
keyword : l’un des suivants :
and as each else error false if in is let meta not null or otherwise
section shared then true try type #binary #date #datetime
#datetimezone #duration #infinity #nan #sections #shared #table #time
Opérateurs et signes de ponctuation
Il existe plusieurs genres d’opérateurs et de signes de ponctuation. Les opérateurs sont utilisés dans les expressions pour décrire des opérations impliquant un ou plusieurs opérandes. Par exemple, l’expression a + b
utilise l’opérateur +
pour ajouter les deux opérandes a
et b
. Les signes de ponctuation sont destinés au regroupement et à la séparation.
operator-or-punctuator : one of
, ; = < <= > >= <> + - * / & ( ) [ ] { } @ ! ? ?? => .. ...