Lexikální struktura
Dokumenty
Dokument M je seřazená posloupnost znaků Unicode. Jazyk M umožňuje různé třídy znaků Unicode v různých částech dokumentu M. Informace o třídách znaků Unicode naleznete v části 4.5 Standard Unicode verze 3.0.
Dokument se skládá z přesně jednoho výrazu nebo skupin definic uspořádaných do oddílů. Oddíly jsou podrobně popsány v kapitole 10. Koncepčně řečeno se k přečtení výrazu z dokumentu používají následující kroky:
Dokument je dekódován podle schématu kódování znaků do posloupnosti znaků Unicode.
Provede se lexikální analýza, čímž se přeloží datový proud znaků Unicode do datového proudu tokenů. Zbývající pododdíly této části pokrývají lexikální analýzu.
Provede se syntaktická analýza, čímž se přeloží datový proud tokenů do formuláře, který lze vyhodnotit. Tento proces je popsaný v dalších částech.
Gramatické zásady
Lexikální a syntaktické gramatiky jsou prezentovány pomocí gramatických produkce. Každá gramatická produkce definuje nekonterminální symbol a možné rozšíření tohoto netermiálního symbolu do sekvencí nekonterminálních nebo terminálových symbolů. V gramatických produkčních prostředích se symboly bez terminálu+ zobrazují kurzívou a symboly terminálu se zobrazují v písmu s pevnou šířkou.
První řádek produkce představuje název definovaného neterminálního symbolu následovaný dvojtečkou. Každá po sobě jdoucí odsazená čára obsahuje možné rozšíření netermiálního znaku zadaného jako posloupnost nekonvenčních nebo terminálových symbolů. Například tato produkce:
if-expression:
if
if-condition then
true-expressionelse
false-expression
definuje výraz if, který se má skládat z tokenu if
, následovaný podmínkou if, následovaný tokenem then
, následovaným výrazem true-expression, následovaným tokenem else
, následovaným nepravdivým výrazem.
Když existuje více než jedno možné rozšíření neterminálního symbolu, jsou alternativy uvedeny na samostatných řádcích. Například tato produkce:
variable-list:
proměnná
proměnná seznamu ,
proměnných
definuje seznam proměnných, který se buď skládá z proměnné, nebo se skládá z seznamu proměnných následovaných proměnnou. Jinými slovy, definice je rekurzivní a určuje, že seznam proměnných se skládá z jedné nebo více proměnných oddělených čárkami.
K označení volitelného symbolu se používá dolní indexovaná přípona opt. Produkce:
specifikace pole:
optional
opt field-name =
field-type
představuje zkrácený tvar této produkce:
specifikace pole:
field-name =
field-type
optional
název =
pole typ pole
a definuje specifikaci pole, která může volitelně začínat symbolem optional
terminálu následovaným názvem pole, symbolem =
terminálu a typem pole.
Alternativy jsou obvykle uvedeny na samostatných řádcích, i když v případech, kdy existuje mnoho alternativ, může fráze "jedna z" předcházet seznamu rozšíření zadaných na jednom řádku. To je jednoduše zkratka pro výpis každé z alternativ na samostatném řádku. Například tato produkce:
decimal-digit: one of
0 1 2 3 4 5 6 7 8 9
představuje zkrácený tvar této produkce:
decimal-digit:
0
1
2
3
4
5
6
7
8
9
Lexikální analýza
Výroba lexikálních jednotek definuje lexikální gramatiku pro dokument M. Každý platný dokument jazyka M odpovídá této gramatikě.
lexical-unit:
lexikální prvky opt
lexikální prvky:
lexical-element
lexical-element
lexikální prvky
lexical-element:
prázdný znak
komentář tokenu
Na lexikální úrovni se dokument M skládá z datového proudu prázdných znaků, komentářů a prvků tokenu . Jednotlivé typy produkcí jsou probrány v následujících částech. Syntaktické gramatiky jsou významné pouze prvky tokenu .
Prázdný znak
Prázdné znaky slouží k oddělení komentářů a tokenů v dokumentu M. Prázdné znaky zahrnují znak mezery (který je součástí třídy Unicode Zs), stejně jako vodorovné a svislé tabulátor, informační kanál formuláře a sekvence znaků nového řádku. Sekvence znaků nového řádku zahrnují návrat na začátek řádku, odřádkování, návrat na začátek řádku následovaný znakem odřádkování, další řádek a oddělovač odstavců.
prázdné znaky:
Libovolný znak s třídou Zs unicode
Vodorovný znak tabulátoru (U+0009
)
Svislý znak tabulátoru (U+000B
)
Znak informačního kanálu formuláře (U+000C
)
Znak návratu na začátek řádku (U+000D
) následovaný znakem odřádkování (U+000A
)
new-line-character
new-line-character:
Znak návratu na začátek řádku (U+000D
)
Znak odřádkování (U+000A
)
Znak dalšího řádku (U+0085
)
Znak oddělovače řádků (U+2028
)
Znak oddělovače odstavců (U+2029
)
Z důvodu kompatibility s nástroji pro úpravy zdrojového kódu, které přidávají značky koncového souboru a umožňují zobrazení dokumentu jako posloupnost správně ukončených řádků, se pro dokument M použijí následující transformace:
Pokud je posledním znakem dokumentu znak Control-Z (
U+001A
), odstraní se tento znak.Znak návratu na začátek řádku (
U+000D
) se přidá na konec dokumentu, pokud tento dokument není prázdný a pokud poslední znak dokumentu není návrat na začátek řádku (U+000D
), odřádk (U+000A
), oddělovač řádků (U+2028
) nebo oddělovač odstavců (U+2029
).
Komentáře
Podporují se dvě formy komentářů: jednořádkové komentáře a komentáře s oddělovači. Jednořádkové komentáře začínají znaky //
a rozšiřují se na konec zdrojového řádku. Komentáře s oddělovači začínají znaky /*
a končí znaky */
.
Komentáře s oddělovači můžou zahrnovat více řádků.
komentář:
jednořádkový komentář
delimited-comment
jednořádkový komentář:
//
Opt-znakys jedním řádkem
jednořádkové znaky komentáře:
Jednořádkový-koment-character single-line-comment-charactersopt
jednořádkový znak komentáře:
Libovolný znak Unicode s výjimkou nového znaku řádku
delimited-comment:
/*
delimited-comment-textopt asterisks /
delimited-comment-text:
delimited-comment-section delimited-comment-text
opted-comment-section:
/
asterisksopt not-slash-or-asterisk
hvězdičky:
*
asterisksopt
not-slash-or-asterisk:
Libovolný znak Unicode s výjimkou *
nebo /
Komentáře nejsou vnořené. Sekvence znaků /*
a */
nemá v rámci jednořádkových komentářů žádný speciální význam. To stejné platí se sekvencemi //
a /*
v komentářích s oddělovači.
Komentáře se nezpracovávají v textových literálech. Příklad
/* Hello, world
*/
"Hello, world"
obsahuje komentář s oddělovači.
Příklad
// Hello, world
//
"Hello, world" // This is an example of a text literal
zobrazuje několik jednořádkových komentářů.
Tokeny
Token je identifikátor, klíčové slovo, literál, operátor nebo interpunkční znaméčko. Prázdné znaky a komentáře se používají k oddělení tokenů, ale nepovažují se za tokeny.
symbol:
identifikátor
klíčové slovo
literal
operátor nebo interpunkční znaméčko
Řídicí sekvence znaků
Textové hodnoty jazyka M mohou obsahovat libovolné znaky Unicode. Textové literály jsou však omezeny na grafické znaky a vyžadují použití řídicích sekvencí pro jiné než grafické znaky. Chcete-li například do textového literálu zahrnout znak návratu na začátek řádku, řádek nebo znak tabulátoru #(cr)
, lze použít sekvence , #(lf)
a #(tab)
řídicí sekvence. Pokud chcete do textového literálu vložit počáteční znaky escapesequence, #
musí být řídicí znaky#(
:
#(#)(
Řídicí sekvence můžou obsahovat také krátké (čtyři šestnáctkové číslice) nebo dlouhé (osm šestnáctkových číslic) hodnot kódu Unicode. Následující tři řídicí sekvence jsou proto ekvivalentní:
#(000D) // short Unicode hexadecimal value
#(0000000D) // long Unicode hexadecimal value
#(cr) // compact escape shorthand for carriage return
Více řídicích kódů lze zahrnout do jedné řídicí sekvence oddělené čárkami; následující dvě sekvence jsou tedy ekvivalentní:
#(cr,lf)
#(cr)#(lf)
Následuje popis standardního mechanismu znakového uvozování v dokumentu 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 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:
#
Literály
Literál představuje ve zdrojovém kódu hodnotu.
literál:
logický literál
number-literal
text-literal
null-literal
doslovný literál
Literály null
Literál null se používá k zápisu null
hodnoty. Hodnota null
představuje chybějící hodnotu.
null-literal:
null
Logické literály
Logický literál se používá k zápisu hodnot true
a false
k vytvoření logické hodnoty.
logický literál:
true
false
Číselné literály
Číselný literál se používá k zápisu číselné hodnoty a vytvoří číselnou hodnotu.
number-literal:
decimal-number-literal
šestnáctkový-number-literal
decimal-number-literal:
decimal-digits decimal-digits .
exponent-partopt
.
decimal-digits exponent-part opt
decimal-digits exponent-part opt
decimal-digits:
opt-digit-digits decimal-digitsopt
decimal-digit: one of
0 1 2 3 4 5 6 7 8 9
exponent-part:
e
znaménkoopt decimal-digits
E
znaménkoopt decimal-digits
sign: one of
+ -
šestnáctkový-number-literal:
0x
šestnáctkové číslice
0X
šestnáctkové číslice
šestnáctkové číslice:
hex-digit hex-digits opts
šestnáctkové číslice: jedna z
0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f
Číslo lze zadat v šestnáctkovém formátu tak, že před šestnáctkovou číslicí zadáváte znaky 0x
. Příklad:
0xff // 255
Všimněte si, že pokud je desetinná čárka zahrnuta do číselného literálu, musí mít za sebou alespoň jednu číslici. Jedná se například 1.3
o číselný literál, 1.e3
ale 1.
nikoli.
Textové literály
Textový literál se používá k zápisu sekvence znaků Unicode a vytvoří textovou hodnotu.
textový literál:
"
opt-text-literal-charactersopt "
text-literal-characters:
text-literal-character text-literal-charactersopt
text-literal-character:
jednotextový znak
character-escape-sequence
double-quote-escape-sequence
jednotextový znak:
Libovolný znak kromě "
(U+0022
) nebo #
(U+0023
) následovaný (
(U+0028
)
double-quote-escape-sequence:
""
(U+0022
, U+0022
)
Pokud chcete do textové hodnoty zahrnout uvozovky, je značka uvozovek opakovaná následujícím způsobem:
"The ""quoted"" text" // The "quoted" text
K zápisu znaků v textových hodnotách je možné použít produkci sekvence řídicích znaků, aniž byste je museli přímo zakódovat jako znaky Unicode v dokumentu. Například návrat na začátek řádku a odřádkování lze zapsat do textové hodnoty takto:
"Hello world#(cr,lf)"
Doslovné literály
Doslovný literál se používá k uložení sekvence znaků Unicode, které uživatel zadal jako kód, ale nelze je správně analyzovat jako kód. Za běhu vytvoří chybovou hodnotu.
doslovný literál:
#!"
opt-text-literal-charactersopt "
Identifikátory
Identifikátor je název, který slouží k odkazování na hodnotu. Identifikátory můžou být buď běžné identifikátory, nebo uvozované identifikátory.
identifikátor:
regular-identifier
quoted-identifier
regular-identifier:
dostupný identifikátor
available-identifier dot-character regular-identifier
dostupný identifikátor:
Klíčové slovo nebo identifikátor, který není klíčovým slovem
klíčové slovo nebo identifikátor:
opt identifikátor-start-character identifier-part-charactersopt
identifikátor-počáteční znak:
letter-character
znak podtržítka
Znaky identifikátoru:
opt-identifier-part-character identifier-part-characters
identifier-part-character:
letter-character
decimal-digit-character
znak podtržítka
spojovací znak
combining-character
formatting-character
tečka:
.
(U+002E
)
znak podtržítka:
_
(U+005F
)
letter-character:
Znak Unicode tříd Lu, Ll, Lt, Lm, Lo nebo Nl
combining-character:
Znak Unicode tříd Mn nebo Mc
decimal-digit-character:
Znak Unicode třídy Nd
připojovací znak:
Znak Unicode počítače třídy
formatting-character:
Znak Unicode třídy Cf
Identifikátor uvozovek lze použít k tomu, aby se jako identifikátor používala libovolná posloupnost nulových nebo více znaků Unicode, včetně klíčových slov, prázdných znaků, komentářů, operátorů a interpunkčních znaků.
quoted-identifier:
#"
opt-text-literal-charactersopt "
Všimněte si, že řídicí sekvence a dvojité uvozovky pro řídicí uvozovky lze použít v uvozovkách stejně jako v textovém literálu.
Následující příklad používá uvozování identifikátorů pro názvy obsahující znak mezery:
[
#"1998 Sales" = 1000,
#"1999 Sales" = 1100,
#"Total Sales" = #"1998 Sales" + #"1999 Sales"
]
Následující příklad používá uvozování identifikátorů k zahrnutí operátoru do identifikátoru +
:
[
#"A + B" = A + B,
A = 1,
B = 2
]
Generalizované identifikátory
V jazyce M existují dvě místa, kde identifikátory, které obsahují prázdné hodnoty, nebo jiné klíčová slova nebo číselné literály, nejsou uvedeny nejednoznačností. Tato místa jsou názvy polí záznamů v literálu záznamu a v operátoru přístupu k poli ([ ]
) Tam M umožňuje tyto identifikátory bez nutnosti používat uvozované identifikátory.
[
Data = [ Base Line = 100, Rate = 1.8 ],
Progression = Data[Base Line] * Data[Rate]
]
Identifikátory používané k pojmenování a přístupu polí se označují jako generalizované identifikátory a jsou definovány takto:
generalized-identifier:
generalized-identifier-part
generalizovaný identifikátor oddělený pouze prázdnými hodnotami (U+0020
)
generalized-identifier-part
generalized-identifier-part:
generalized-identifier-segment
decimal-digit-character generalized-identifier-segment
generalized-identifier-segment:
klíčové slovo nebo identifikátor
keyword-or-identifier dot-character keyword-or-identifier
Klíčová slova
Klíčové slovo je posloupnost znaků, která je vyhrazena, a nelze ji použít jako identifikátor s výjimkou použití mechanismu uvozování identifikátorů nebo pokud je povolený generalizovaný identifikátor.
klíčové slovo: jedno z
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
Operátory a interpunkční znaky
Existuje několik druhů operátorů a interpunkčních znamétek. Operátory se používají ve výrazech k popisu operací zahrnujících jeden nebo více operandů. Například výraz a + b
sečte pomocí operátoru +
dva operandy a
a b
. Interpunkční znaky slouží k seskupení a oddělení.
operátor nebo interpunkční znaméčko: jeden z
, ; = < <= > >= <> + - * / & ( ) [ ] { } @ ! ? ?? => .. ...