Estrutura lexical

Documentos

Um documento do M é uma sequência ordenada de caracteres Unicode. O M permite o uso de diferentes classes de caracteres Unicode em diferentes partes de um documento do M. Para obter informações sobre classes de caracteres Unicode, confira O Padrão Unicode, Versão 3.0, seção 4.5.

Um documento consiste em exatamente uma expressão ou em grupos de definições organizadas em seções. As seções são descritas em detalhes no Capítulo 10. Em termos conceituais, as seguintes etapas são usadas para ler uma expressão de um documento:

  1. O documento é decodificado de acordo com o respectivo esquema de codificação de caracteres em uma sequência de caracteres Unicode.

  2. A análise lexical é executada, convertendo assim o fluxo de caracteres Unicode em um fluxo de tokens. As subseções restantes desta seção abordam a análise lexical.

  3. A análise sintática é executada, convertendo assim o fluxo de tokens em um formulário que pode ser avaliado. Esse processo é abordado nas seções subsequentes.

Convenções gramaticais

As gramáticas lexical e sintática são apresentadas usando produções gramaticais. Cada produção de gramática define um símbolo não terminal e as possíveis expansões desse símbolo não terminal em sequências de símbolos terminais ou não terminais. Em produções de gramática, os símbolos não terminais são mostrados em itálico, e os símbolos terminais são mostrados em uma fonte de largura fixa.

A primeira linha de uma produção de gramática é o nome do símbolo não terminal que está sendo definido, seguido por dois-pontos. Cada linha recuada sucessiva contém uma possível expansão do símbolo não terminal fornecida como uma sequência de símbolos terminais ou não terminais. Por exemplo, a produção:

expressão-if:
      ifcondição-ifthenexpressão-trueelseexpressão-false

define uma expressão-if consistindo do token if, seguido por uma condição-if, seguida pelo token then, seguido por uma expressão-true, seguida pelo token else, seguido por uma expressão-false.

Quando há mais de uma possível expansão de um símbolo não terminal, as alternativas são listadas em linhas separadas. Por exemplo, a produção:

lista-de-variáveis:
      variável
      lista-de-variáveis
,variável

define uma lista-de-variáveis para consistir de uma variável ou consistir de uma lista-de-variáveis seguida por uma variável. Em outras palavras, a definição é recursiva e especifica que uma lista de variáveis consiste em uma ou mais variáveis, separadas por vírgulas.

Um sufixo subscrito "opt" é usado para indicar um símbolo opcional. A produção:

especificação-do-campo:
      optionalopcional nome-do-campo=tipo-de-campo

é uma versão abreviada de:

especificação-do-campo:
      nome-do-campo
=tipo-de-campo
      optionalnome-do-campo=tipo-de-campo

e define uma especificação-do-campo para, opcionalmente, começar com o símbolo do terminal optional seguido por nome-do-campo, o símbolo do terminal = e um tipo-de-campo.

As alternativas normalmente são listadas em linhas separadas, porém, nos casos em que há muitas alternativas, a frase "one of" pode preceder uma lista de expansões dadas em uma única linha. Isso é simplesmente uma forma mais prática do que listar cada uma das alternativas em uma linha separada. Por exemplo, a produção:

dígito-decimal: um dos seguintes
      0 1 2 3 4 5 6 7 8 9

é uma versão abreviada de:

dígito-decimal:
      0
      1
      2
      3
      4
      5
      6
      7
      8
      9

Análise lexical

A produção unidade-lexical define a gramática lexical para um documento do M. Todos os documentos do M válidos estão em conformidade com essa gramática.

unidade-lexical:
      elementos-léxicosopcional
elementos-léxicos:
      elemento-léxico
      elemento-léxico
      elementos-léxicos
elemento-léxico:
      espaço em branco
      comentário de token

No nível lexical, um documento do M consiste em um fluxo de elementos de espaço em branco, comentário e token. Cada uma dessas produções é abordada nas seções a seguir. Somente os elementos token são significativos na gramática sintática.

Espaço em branco

O espaço em branco é usado para separar comentários e tokens em um documento do M. O espaço em branco inclui o caractere de espaço (que faz parte da classe Unicode ZS), bem como a tabulação horizontal e a vertical, o feed de formulário e as sequências de caracteres de nova linha. As sequências de caracteres de nova linha incluem retorno de carro, alimentação de linha, retorno de carro seguido de alimentação de linha, linha seguinte e caracteres separadores de parágrafo.

espaço em branco:
      Qualquer caractere com classe Unicode ZS
      Caractere de tabulação horizontal (U+0009)
      Caractere de tabulação vertical (U+000B)
      Caractere de feed de formulário (U+000C)
      Caractere de retorno de carro (U+000D) seguido pelo caractere de alimentação de linha (U+000A)
      caractere-de-nova-linha
caractere-de-nova-linha:
      Caractere de retorno de carro (U+000D)
      Caractere de feed de linha (U+000A)
      Caractere de próxima linha (U+0085)
      Caractere separador de linha (U+2028)
      Caractere separador de parágrafo (U+2029)

Para compatibilidade com ferramentas de edição de código-fonte que adicionam marcadores de final de arquivo e para permitir que um documento seja exibido como uma sequência de linhas encerradas corretamente, as seguintes transformações são aplicadas, em ordem, a um documento do M:

  • Se o último caractere do documento for um caractere de Controle Z (U+001A), esse caractere será excluído.

  • Um caractere de retorno de carro (U+000D) será adicionado ao final do documento se esse documento não estiver vazio e se o último caractere do documento não for um retorno de carro (U+000D), uma alimentação de linha (U+000A), um separador de linha (U+2028) nem um separador de parágrafo (U+2029).

Comentários

Dois formulários de comentários são compatíveis: comentários de linha única e comentários delimitados. Os comentários de linha única começam com os caracteres // e se estendem até o final da linha de origem. Os comentários delimitados começam com os caracteres /* e terminam com os caracteres */.

Os comentários delimitados podem abranger várias linhas.

comentário:
      comentário-de-linha-única
      comentário-delimitado
comentário-de-linha-única:

      //caracteres-de-comentário-de-linha-únicaopcional
caracteres-de-comentário-de-linha-única:
      caractere-de-comentário-de-linha-única caracteres-de-comentário-de-linha-únicaopcional
caracteres-de-comentário-de-linha-única:

      Qualquer caractere Unicode, exceto um caractere-de-nova-linha
comentário-delimitado:

      /*texto-de-comentário-delimitadoopcionalasteriscos/
texto-de-comentário-delimitado:
      texto-de-comentário-delimitado de seção-de-comentário-delimitadoopcional
seção-de-comentário-delimitado:

      /
      asteriscosopcional caracteres-diferentes-de-barra-e-asterisco
asteriscos:

      *asteriscosopcional
não-barra-/-ou-asterisco:

      Qualquer caractere Unicode, exceto * ou /

Os comentários não podem ser aninhados. As sequências de caracteres /* e */ não têm nenhum significado especial dentro de um comentário de linha única, e as sequências de caracteres // e /* não têm nenhum significado especial dentro de um comentário delimitado.

Os comentários não são processados em literais de texto. O exemplo

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

inclui um comentário delimitado.

O exemplo

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

mostra vários comentários de linha única.

Tokens

Um token é um identificador, uma palavra-chave, um literal, um operador ou um pontuador. O espaço em branco e os comentários são usados para separar tokens, mas não são considerados tokens.

token:
      identificador
      palavra-chave
      literal
      operador-ou-pontuador

Sequências de escape de caractere

Os valores de texto do M podem conter caracteres Unicode arbitrários. Os literais de texto, por sua vez, são limitados a caracteres gráficos e exigem o uso de sequências de escape para caracteres não gráficos. Por exemplo, para incluir um retorno de carro, avanço de linha ou caractere de tabulação em um literal de texto, é possível usar as sequências de escape #(cr), #(lf) e #(tab), respectivamente. Para inserir os caracteres iniciais de sequência de escape #( em um literal de texto, o # propriamente dito precisa ser escapado:

#(#)(

As sequências de escape também podem conter valores curtos (quatro dígitos hexadecimais) ou longos (oito dígitos hexadecimais) de ponto de código Unicode. Portanto, estas três sequências de escape são equivalentes:

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

Vários códigos de escape podem ser incluídos em uma única sequência de escape, separados por vírgulas. As seguintes duas sequências são, portanto, equivalentes:

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

A descrição a seguir representa o mecanismo padrão de saída de caracteres em um documento do M.

sequência-de-escape-de-caracteres:
      #(lista-de-sequências-de-escape)
lista-de-sequências-de-escape:
      sequência-de-escape-individual
      sequência-de-escape-único
,lista-de-sequências-de-escapes
sequência-de-escape-individual:
      sequência-de-escape-longa-unicode
      sequência-de-escape-curta-unicode
      sequência-de-escape-de-caractere-de-controle
      escape-escape
sequência-de-escape-longa-unicode:
      dígito-hexadecimal dígito-hexadecimal dígito-hexadecimal dígito-hexadecimal dígito-hexadecimal dígito-hexadecimal dígito-hexadecimal dígito-hexadecimal
sequência-de-escape-curta-unicode:
      dígito-hexadecimal dígito-hexadecimal dígito-hexadecimal dígito-hexadecimal
sequência-de-escape-de-caractere-de-controle:
      caractere-de-controle
caractere-de-controle:

      cr
      lf
      tab
escape-escape:
      #

Literais

Um literal é uma representação de código-fonte de um valor.

literal:
      literal-lógico
      literal-de-número
      literal-de-texto
      literal-nulo
      literal-textual

Literais nulos

O literal nulo é usado para escrever o valor de null. O valor de null representa um valor ausente.

literal-nulo:
      null

Literais lógicos

Um literal lógico é usado para gravar os valores true e false e produz um valor lógico.

literal-lógico:
      true
      false

Literais de número

Um literal de número é usado para escrever um valor de número e produz um valor de número.

literal-de-número:
      literal-de-número-decimal
      literal-de-número-hexadecimal
literal-de-número-decimal:
      dígitos-decimais
.parte-do-expoente de dígitos-decimaisopcional
      .dígitos-decimais parte-do-expoenteopcional
      dígitos-decimais parte-do-expoenteopcional
dígitos-decimais:
      dígito-decimal dígitos-decimaisopcional
dígito-decimal:
um de
      0 1 2 3 4 5 6 7 8 9
parte-do-expoente:
      esinalopcional dígitos-decimais
      Esinalopcional dígitos-decimais
conectar:
um de
      + -
literal-de-número-hexadecimal:
      0xdígitos-hexadecimais
      0Xdígitos-hexadecimais
dígitos-hexadecimais:
      dígito-hexadecimal dígitos-hexadecimaisopcional
digito-hexadecimal:
um de
      0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f

Um número pode ser especificado em formato hexadecimal colocando-se os caracteres 0x antes dos dígitos-hexadecimais. Por exemplo:

0xff // 255

Observe que, se um ponto decimal for incluído em um número literal, pelo menos um dígito precisará existir depois dele. Por exemplo, 1.3 é um número literal, mas 1. e 1.e3 não são.

Literais de texto

Um literal de texto é usado para escrever uma sequência de caracteres Unicode e produz um valor de texto.

literal-de-texto:
      "caracteres-de-literal-de-textoopcional"
caracteres-de-literal-de-texto:
      caractere-de-literal-de-texto caracteres-de-literal-de-textoopcional
caractere-de-literal-de-texto:
      caractere-de-texto-individual
      sequência-de-escape-de-caracteres
      sequência-de-escape-com-aspas-duplas
caractere-de-texto-individual:

      Qualquer caractere, exceto " (U+0022) ou # (U+0023) seguido por ( (U+0028)
sequência-de-escape-com-aspas-duplas:
      "" (U+0022, U+0022)

Para incluir aspas em um valor de texto, a marca de aspas é repetida, da seguinte maneira:

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

A produção sequência-de-escape-de-caracteres pode ser usada para gravar caracteres em valores de texto sem precisar codificá-los diretamente como caracteres Unicode no documento. Por exemplo, um retorno de carro e uma alimentação de linha podem ser escritos em um valor de texto como:

"Hello world#(cr,lf)"

Literais textuais

Um literal textual é usado para armazenar uma sequência de caracteres Unicode que foram inseridos por um usuário como código, mas que não podem ser analisados corretamente como código. No tempo de execução, ele produz um valor de erro.

literal-textual:
      #!"caracteres-de-literal-de-textoopcional"

Identificadores

Um identificador é um nome usado para fazer referência a um valor. Os identificadores podem ser identificadores comuns ou identificadores entre aspas.

identificador:
      identificador-comum
      identificador-entre-aspas
identificador-comum:
      identificador-disponível
      identificador-disponível caractere-de-ponto identificador-comum
identificador-disponível:

      Uma palavra-chave-ou-identificador que não é uma palavra-chave
palavra-chave-ou-identificador:
      caractere-de-início-de-identificador caracteres-de-parte-de-identificadoropcional
caractere-de-início-de-identificador:
      caractere-de-letra
      caractere-de-sublinhado
caracteres-de-parte-de-identificador:
      caractere-de-parte-identificadora caracteres-de-parte-identificadoraopcional
caractere-de-parte-de-identificador:
      caractere-de-letra
      caractere-de-dígito-decimal
      caractere-de-sublinhado
      caractere-de-conexão
      caractere-de-combinação
      caractere-de-formatação
caractere de ponto:

      . (U+002E)
caractere-de-sublinhado:
      _ (U+005F)
caractere-de-letra:
      Um caractere Unicode de uma das classes Lu, Ll, Lt, Lm, Lo ou Nl
caractere-de-combinação:
      Um caractere Unicode de uma das classes Mn ou Mc
caractere-de-dígito-decimal:
      Um caractere Unicode da classe Nd
caractere-de-conexão:
      Um caractere Unicode da classe Pc
caractere-de-formatação:
      Um caractere Unicode da classe Cf

Um identificador-entre-aspas pode ser usado para permitir que qualquer sequência de zero ou mais caracteres Unicode seja usada como um identificador, incluindo palavras-chave, espaço em branco, comentários, operadores e pontuadores.

identificador-entre-aspas:
      #"caracteres-de-literal-de-textoopcional"

Observe que as sequências de escape e as aspas duplas para as aspas de escape podem ser usadas em um identificador entre aspas, assim como em um literal-de-texto.

O seguinte exemplo usa aspas em identificadores naqueles nomes que contêm um caractere de espaço:

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

O seguinte exemplo usa aspas em identificadores a fim de incluir o operador + em um identificador:

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

Identificadores generalizados

Há dois lugares no M em que nenhuma ambiguidade é introduzida por identificadores que contêm espaços em branco ou que são palavras-chave ou literais de número. Esses locais são os nomes dos campos de registro em um literal de registro e em um operador de acesso de campo ([ ]). Ali, o M permite o uso desses identificadores sem necessidade de usar de identificadores entre aspas.

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

Os identificadores usados para nomear e acessar campos são chamados de identificadores generalizados e são definidos da seguinte maneira:

identificador-generalizado:
      parte-de-identificador-generalizado
      identificador-generalizado
separado somente por espaços em branco (U+0020)
parte-de-identificador-generalizado
parte-de-identificador-generalizado:
      segmento-de-identificador-generalizado
      caractere-de-dígito-decimal segmento-de-identificador-generalizado
segmento-de-identificador-generalizado:
      palavra-chave-ou-identificador
      palavra-chave-ou-identificador caractere-de-ponto palavra-chave-ou-identificador

Palavras-chave

Uma palavra-chave é uma sequência de caracteres semelhante à de um identificador que é reservada e não pode ser usada como um identificador, exceto ao usar o mecanismo de colocação de aspas em identificadores ou nos casos em que um identificador genérico é permitido.

palavra-chave: um entre
       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

Operadores e pontuadores

Há vários tipos de operadores e pontuadores. Os operadores são usados em expressões para descrever as operações que envolvem um ou mais operandos. Por exemplo, a expressão a + b usa o operador + para adicionar os dois operandos a e b. Os pontuadores servem para agrupamento e separação.

operador-ou-pontuador: um entre
      , ; = < <= > >= <> + - * / & ( ) [ ] { } @ ! ? ?? => .. ...