Share via


Lexikalische Struktur

Dokumente

Ein M-Dokument ist eine geordnete Sequenz aus Unicode-Zeichen. M ermöglicht verschiedene Klassen von Unicode-Zeichen in verschiedenen Teilen eines M-Dokuments. Informationen zu Unicode-Zeichenklassen finden Sie in Abschnitt 4.5 unter Unicode-Standard-Version 3.0.

Ein Dokument besteht entweder aus genau einem Ausdruck oder aus Gruppen von Definitionen, die in Abschnitte unterteilt sind. Diese Abschnitte werden in Kapitel 10 ausführlich beschrieben. Konzeptionell werden die folgenden Schritte zum Lesen eines Ausdrucks aus einem Dokument verwendet:

  1. Das Dokument wird gemäß seines Zeichenverschlüsselungsschemas in eine Sequenz aus Unicode-Zeichen decodiert.

  2. Die lexikalische Analyse wird durchgeführt, wodurch der Stream aus Unicode-Zeichen in einen Stream aus Token übersetzt wird. Die verbleibenden untergeordneten Abschnitte dieses Abschnitts behandeln die lexikalische Analyse.

  3. Die syntaktische Analyse wird durchgeführt, wodurch der Stream von Tokens in ein Formular übersetzt wird, das ausgewertet werden kann. Dieses Prozess wird in den nachfolgenden Abschnitten behandelt.

Grammatikalische Konventionen

Die lexikalische und syntaktische Grammatik wird mithilfe von Grammatikproduktionen dargestellt. Jede Grammatikproduktion definiert ein Nichtterminalsymbol und dessen mögliche Erweiterungen in Sequenzen aus Nichtterminal- oder Terminalsymbolen. In Grammatikproduktionen werden Nichtterminalsymbole kursiv und Terminalsymbole in einer Schriftart mit fester Schrittbreite dargestellt.

Die erste Zeile einer Grammatikproduktion entspricht dem Namen des Nichtterminalsymbols, das definiert wird, gefolgt von einem Doppelpunkt. Jede aufeinanderfolgende eingerückte Zeile enthält eine mögliche Erweiterung des Nichtterminalsymbols als Sequenz aus Nichtterminal- und Terminalsymbolen. Zum Beispiel wird bei der folgenden Produktion:

if-Ausdruck:
      ifif-conditionthentrue-expressionelsefalse-expression

definiert einen if-Ausdruck, der aus dem Token if besteht, gefolgt von einer if-Bedingung, gefolgt vom Token then, gefolgt von einem TRUE-Ausdruck, gefolgt vom Token else, gefolgt von einem FALSE-Ausdruck.

Wenn es mehrere mögliche Erweiterungen eines Nichtterminalsymbols gibt, werden die Alternativen in separaten Zeilen aufgeführt. Zum Beispiel wird bei der folgenden Produktion:

variable-list:
      -Variable
      variable-list
,variable

eine Variablenliste so definiert, dass sie entweder aus einer Variable oder einer Variablenliste, gefolgt von einer Variable, besteht. Das bedeutet, die Definition ist rekursiv und legt fest, dass eine Variablenliste aus einer oder mehreren Variablen besteht, die durch Trennzeichen getrennt sind.

opt“ wird als indexiertes Suffix verwendet, um optionale Symbole zu kennzeichnen. Die Produktion:

field-specification:
      optionalopt field-name=field-type

ist die Kurzform für:

field-specification:
      field-name
=field-type
      optionalfield-name=field-type

und definiert eine Feldspezifikation, die optional mit dem Terminalsymbol optional, gefolgt von einem Feldnamen, dem Terminalsymbol = und einem Feldtyp beginnt.

Alternativen werden normalerweise in separaten Zeilen aufgeführt. In einigen Fällen mit vielen Alternativen kann „One of“ („Eine von“) einer Liste von Erweiterungen vorangestellt werden, die in einer einzelnen Zeile angegeben werden. Dabei handelt es sich lediglich um eine Kurzform zum Auflisten aller Alternativen in einer separaten Zeile. Zum Beispiel wird bei der folgenden Produktion:

decimal-digit: one of
      0 1 2 3 4 5 6 7 8 9

ist die Kurzform für:

decimal-digit:
      0
      1
      2
      3
      4
      5
      6
      7
      8
      9

Lexikalische Analyse

Die Produktion lexical-unit definiert die lexikalische Grammatik für ein M-Dokument. Jedes gültige M-Dokument entspricht dieser Grammatik.

lexical-unit:
      lexical-elementsopt
lexical-elements:
      lexical-element
      lexical-element
      lexical-elements
lexical-element:
      whitespace
      token comment

Auf lexikalischer Ebene besteht ein M-Dokument aus einem Stream aus den Elementen Leerraum, Kommentar und Token. All diese Produktionen werden in den folgenden Abschnitten beschrieben. Nur Tokenelemente sind in der syntaktischen Grammatik von Bedeutung.

Leerzeichen

Leerraum wird verwendet, um Kommentare und Token in einem M-Dokument voneinander zu trennen. Leerraum umfasst das Leerzeichen (das Teil der Unicode-Klasse „Zs“ ist) sowie horizontale und vertikale Tabstopp-, Seitenvorschub- und Zeilenumbruchzeichenfolgen. Zeilenumbruchzeichenfolgen umfassen Wagenrücklaufzeichen, Zeilenvorschubzeichen, Wagenrücklaufzeichen, gefolgt von Zeilenvorschubzeichen, Zeilenumbruchzeichen und Absatztrennzeichen.

Leerraum:
      Beliebiges Zeichen der Unicode-Klasse „Zs“
      Horizontales Tabstoppzeichen (U+0009)
      Vertikales Tabstoppzeichen (U+000B)
      Seitenvorschubzeichen (U+000C)
      Wagenrücklaufzeichen (U+000D), gefolgt von einem Zeilenvorschubzeichen (U+000A)
      Zeilenumbruchzeichen
Zeilenumbruchzeichen:
      Wagenrücklaufzeichen (U+000D)
      Zeilenvorschubzeichen (U+000A)
      Zeilenumbruchzeichen (U+0085)
      Zeilentrennzeichen (U+2028)
      Absatztrennzeichen (U+2029)

Für die Kompatibilität mit Tools für die Quellcodebearbeitung, die Kennzeichnungen für das Dateiende hinzufügen, und damit ein Dokument als Sequenz ordnungsgemäß beendeter Zeilen angezeigt werden kann, werden die folgenden Transformationen in der entsprechenden Reihenfolge auf ein M-Dokument angewendet:

  • Wenn es sich bei dem letzten Zeichen des Dokuments um ein Substitutionszeichen (U+001A) handelt, wird dieses Zeichen gelöscht.

  • Ein Wagenrücklaufzeichen (U+000D) wird zum Ende des Dokuments hinzugefügt, wenn das Dokument nicht leer ist und es sich bei dem letzten Zeichen des Dokuments nicht um ein Wagenrücklaufzeichen (U+000D), ein Zeilenvorschubzeichen (U+000A), ein Zeilentrennzeichen (U+2028) oder ein Absatztrennzeichen (U+2029) handelt.

Kommentare

Es werden zwei Arten von Kommentaren unterstützt: einzeilige Kommentare und durch Trennzeichen getrennte Kommentare. Einzeilige Kommentare beginnen mit den Zeichen // und werden an das Ende der Quellzeile angefügt. Durch Trennzeichen getrennte Kommentare beginnen mit den Zeichen /* und enden mit den Zeichen */.

Durch Trennzeichen getrennte Kommentare können mehrere Zeilen umfassen.

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:

      Beliebiges Unicode-Zeichen mit Ausnahme eines 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
Sternchen:

      *asterisksopt
not-slash-or-asterisk:

      Beliebiges Unicode-Zeichen mit Ausnahme von * oder /

Kommentare werden nicht geschachtelt. Die Zeichenfolgen /* und */ verfügen innerhalb eines einzeiligen Kommentars über keine besondere Bedeutung, und die Zeichenfolgen // und /* verfügen in einem durch Trennzeichen getrennten Kommentar über keine besondere Bedeutung.

Kommentare werden nicht in Textliteralen verarbeitet. Das Beispiel

/* Hello, world 
*/ 
    "Hello, world"

enthält einen durch Trennzeichen getrennten Kommentar.

Das Beispiel

// Hello, world 
// 
"Hello, world" // This is an example of a text literal

enthält mehrere einzeilige Kommentare.

Token

Ein Token ist ein Bezeichner, Schlüsselwort, Literal, Operator oder Trennzeichen. Leerraum und Kommentare werden verwendet, um Token voneinander zu trennen, gelten aber nicht als Tokens.

token:
      Bezeichner
      Schlüsselwort (keyword)
      literal
      operator-or-punctuator

Escapezeichensequenzen

M-Textwerte können arbiträre Unicode-Zeichen enthalten. Textliterale werden jedoch auf grafische Zeichen beschränkt und erfordern Escapesequenzen für nicht grafische Zeichen. Zum Beispiel können jeweils die Escapesequenzen #(cr), #(lf) und #(tab) verwendet werden, um ein Wagenrücklauf-, Zeilenvorschub- oder Tabstoppzeichen in ein Textliteral einzufügen. Zum Einbetten der Startzeichen #( für eine Escapesequenz in einem Textliteralzeichen, muss # selbst mit einem Escapezeichen versehen werden:

#(#)(

Escapesequenzen können auch kurze (vier Hexadezimalziffern) oder lange (acht Hexadezimalziffern) Unicode-Codepunktwerte enthalten. Die folgenden drei Escapesequenzen sind daher äquivalent:

#(000D)     // short Unicode hexadecimal value 
#(0000000D) // long Unicode hexadecimal value 
#(cr)       // compact escape shorthand for carriage return

Mehrere Escapecodes können durch Trennzeichen getrennt in eine einzelne Escapesequenz eingefügt werden. Daher sind die folgenden zwei Sequenzen äquivalent:

#(cr,lf) 
#(cr)#(lf)

Im Folgenden wird der Standardmechanismus für Escapezeichen für Zeichen in M-Dokumenten beschrieben.

Escapezeichensequenz:
      #(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
Steuerzeichen:

      cr
      lf
      tab
Escape-Escape:
      #

Literale

Ein Literal ist die Quellcodedarstellung eines Werts.

literal:
      logical-literal
      number-literal
      text-literal
      null-literal
      verbatim-literal

NULL-Literale

NULL-Literale werden zum Schreiben der Werts null verwendet. Der Wert null stellt einen fehlenden Wert dar.

NULL-Literal:
      null

Logische Literale

Logische Literale werden zum Schreiben der Werte true und false verwendet und erzeugen logische Werte.

logical-literal:
      true
      false

Zahlenliterale

Zahlenliterale werden zum Schreiben numerischer Werte verwendet und erzeugen einen numerischen Wert.

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:
einer der folgenden Werte
      0 1 2 3 4 5 6 7 8 9
exponent-part:
      esignopt decimal-digits
      Esignopt decimal-digits
Vorzeichen:
einer der folgenden Werte
      + -
Hexadezimalliteral:
      0xhex-digits
      0Xhex-digits
hex-digits:
      hex-digit hex-digitsopt
hex-digit:
einer der folgenden Werte
      0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f

Eine Zahl kann im Hexadezimalformat angegeben werden, indem hex-digits die Zeichen 0x vorangestellt werden. Beispiel:

0xff // 255

Wenn ein Dezimaltrennzeichen in einem Zahlenliteral enthalten ist, müssen Sie darauf achten, dass mindestens eine Zahl ihm folgt. Zum Beispiel ist 1.3 ein Zahlenliteral, aber 1. und 1.e3 nicht.

Textliterale

Textliterale werden zum Schreiben einer Sequenz von Unicode-Zeichen verwendet und erzeugen einen Textwert.

Textliteral:
      "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:

      Beliebiges Zeichen außer " (U+0022) oder # (U+0023), gefolgt von ( (U+0028)
Escapesequenz mit doppelten Anführungszeichen:
      "" (U+0022, U+0022)

Zum Einfügen von Anführungszeichen in einen Textwert muss das Anführungszeichen wie folgt wiederholt werden:

"The ""quoted"" text" // The "quoted" text

Die Produktion character-escape-sequence kann zum Schreiben von Zeichen in Textwerte verwendet werden, ohne dass sie im Dokument als Unicode-Zeichen codiert werden müssen. Ein Wagenrücklauf und Zeilenvorschub kann beispielsweise wie folgt in einen Textwert geschrieben werden:

"Hello world#(cr,lf)"

Verbatim-Literale

Ein Verbatim-Literal, also ein wörtliches Literal, wird zum Speichern einer Sequenz von Unicode-Zeichen verwendet, die von einem Benutzer als Code eingegeben wurden aber nicht ordnungsgemäß als Code analysiert werden können. Zur Laufzeit wird ein Fehlerwert erzeugt.

Verbatim-Literal:
      #!"text-literal-charactersopt"

Bezeichner

Bezeichner sind Namen für Werte. Es gibt sowohl reguläre Bezeichner als auch Bezeichner in Anführungszeichen.

identifier:
      regular-identifier
      quoted-identifier
regular-identifier:
      available-identifier
      available-identifier dot-character regular-identifier
available-identifier:

      Ein keyword-or-identifier, der kein keyword ist
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)
Unterstrichzeichen:
      _ (U+005F)
letter-character:
      Ein Unicode-Zeichen der Klassen „Lu“, „Ll“, „Lt“, „Lm“, „Lo“ oder „Nl“
Kombinationszeichen:
      Ein Unicode-Zeichen der Klassen „Mn“ oder „Mc“
Dezimalziffer:
      Ein Unicode-Zeichen der Klasse „Nd“
Verbindungszeichen:
      Ein Unicode-Zeichen der Klasse „Pc“
Formatierungszeichen:
      Ein Unicode-Zeichen der Klasse „Cf“

Ein Bezeichner in Anführungszeichen kann zum Verwenden beliebiger Sequenzen mit keinen oder mehreren Unicode-Zeichen verwendet werden, einschließlich Schlüsselwörter, Leerraum, Kommentare, Operatoren und Trennzeichen.

Bezeichner in Anführungszeichen:
      #"text-literal-charactersopt"

Beachten Sie, dass Escapesequenzen und doppelte Anführungszeichen für Anführungszeichen als Escapezeichen genau wie in einem Textliteral auch in einem Bezeichner in Anführungszeichen verwendet werden kann.

Im folgenden Beispiel werden Bezeichner für Namen in Anführungszeichen gesetzt, die ein Leerzeichen enthalten:

[ 
    #"1998 Sales" = 1000, 
    #"1999 Sales" = 1100, 
    #"Total Sales" = #"1998 Sales" + #"1999 Sales"
]

Im folgenden Beispiel werden Bezeichner in Anführungszeichen gesetzt, um den +-Operator in einen Bezeichner einzufügen:

[ 
    #"A + B" = A + B, 
    A = 1, 
    B = 2 
]

Generalisierte Bezeichner

In M gibt es zwei Stellen, an denen keine Mehrdeutigkeiten durch Bezeichner eingeführt werden, die Leerzeichen enthalten oder auf andere Weise Schlüsselwörter oder Zahlenliterale sind. Diese Stellen sind die Namen von Datensatzfeldern in einem Datensatzliteral und im Feldzugriffsoperator ([ ]). M lässt solche Bezeichner zu, ohne dass Bezeichner in Anführungszeichen gesetzt werden müssen.

[ 
    Data = [ Base Line = 100, Rate = 1.8 ], 
    Progression = Data[Base Line] * Data[Rate]
]

Die Bezeichner für die Benennung und den Zugriff auf Felder werden als generalisierte Bezeichner bezeichnet und folgendermaßen definiert:

generalized-identifier:
      generalized-identifier-part
      generalized-identifier
nur durch Leerzeichen getrennt (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

Schlüsselwörter

Schlüsselwörter sind Bezeichnern ähnelnde Zeichenfolgen, die reserviert sind. Sie können nicht als Bezeichner verwendet werden, es sei denn, sie werden mit dem Mechanismus für in Anführungszeichen gesetzte Bezeichner verwendet oder generalisierte Bezeichner sind zulässig.

Schlüsselwort: eines von
       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

Operatoren und Trennzeichen

Es gibt verschiedene Arten von Operatoren und Trennzeichen. Operatoren werden in Ausdrücken verwendet, um Vorgänge mit einem oder mehreren Operanden zu beschreiben. Der Ausdruck a + b verwendet beispielsweise den Operator +, um die zwei Operanden a und b hinzuzufügen. Trennzeichen werden zum Gruppieren und Trennen verwendet.

operator-or-punctuator: one of
      , ; = < <= > >= <> + - * / & ( ) [ ] { } @ ! ? ?? => .. ...