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 :

  1. Le document est décodé en fonction de son schéma d’encodage de caractères en une séquence de caractères Unicode.

  2. 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.

  3. 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:
      ifif-conditionthentrue-expressionelsefalse-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:
      optionalopt field-name=field-type

est un raccourci de :

field-specification :
      field-name
=field-type
      optionalfield-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:
      esignopt decimal-digits
      Esignopt decimal-digits
sign :
une des valeurs suivantes
      + -
hexadecimal-number-literal:
      0xhex-digits
      0Xhex-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
      , ; = < <= > >= <> + - * / & ( ) [ ] { } @ ! ? ?? => .. ...