Partilhar via


Estrutura Lexical

Documentos

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

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

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

  2. A análise lexical é realizada, traduzindo assim o fluxo de caracteres Unicode em um fluxo de tokens. As restantes subsecções desta secção abrangem a análise lexical.

  3. A análise sintática é realizada, traduzindo assim o fluxo de tokens em uma forma que pode ser avaliada. Este processo é abordado nas secções seguintes.

Convenções gramaticais

As gramáticas lexical e sintática são apresentadas utilizando produções gramaticais. Cada produção gramatical 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 não terminais ou terminais. Em produções gramaticais, símbolos não-terminais+ são mostrados em itálico e símbolos terminais são mostrados em uma fonte de largura fixa.

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

expressão-se:
      ifif-condição then Expressãoelse verdadeirafalsa-expressão

define uma expressão if para consistir no token if, seguido por uma condição if, seguido pelo token then, seguido por uma expressão verdadeira, seguido pelo token else, seguido por uma expressão falsa.

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

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

define uma lista de variáveis para consistir em uma variável ou consistir em 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:
      optional opt field-name = field-type

é a forma abreviada de:

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

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

As alternativas são normalmente listadas em linhas separadas, embora nos casos em que há muitas alternativas, a frase "uma das" pode preceder uma lista de expansões dadas em uma única linha. Esta é simplesmente uma abreviatura para listar cada uma das alternativas em uma linha separada. Por exemplo, a produção:

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

é a forma abreviada de:

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

Análise Lexical

A produção da unidade léxica define a gramática lexical para um documento M. Todos os documentos M válidos estão em conformidade com esta gramática.

unidade lexical:
      Os elementosléxicos optam
elementos-lexicais:
      elemento-léxico
      elemento-léxico
      elementos-lexicais
elemento-lexical:
      espaço em branco
      token comentário

No nível lexical, um documento M consiste em um fluxo de espaços em branco, comentários e elementos de token. Cada uma destas produções é abordada nas seguintes secções. Apenas os elementos simbólicos são significativos na gramática sintática.

Espaço em branco

O espaço em branco é usado para separar comentários e tokens dentro de um documento M. Espaço em branco inclui o caractere de espaço (que faz parte da classe Unicode Zs), bem como tabulação horizontal e vertical, alimentação de formulário e 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, próxima linha 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 alimentação de formulário (U+000C)
      Caractere de retorno de carro (U+000D) seguido de 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 alimentação de linha (U+000A)
      Caractere da 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 fim de arquivo e para permitir que um documento seja exibido como uma sequência de linhas terminadas corretamente, as seguintes transformações são aplicadas, em ordem, a um documento M:

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

  • Um caractere de retorno de carro (U+000D) é 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) ou um separador de parágrafo (U+2029).

Comentários

Duas formas de comentários são suportadas: 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
      delimitado-comentário
comentário de linha única:

      //optam por caracteresde comentário de linha única
caracteres de comentário de linha única:
      single-line-comment-character single-line-comment-charactersopt
caractere de comentário de linha única:

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

      /*delimitado-comentário-textoopt asteriscos /
delimitado-comentário-texto:
      delimitado-comentário-seção delimitado-comentário-textoopt
delimitado-comentário-seção:

      /
      asteriscosoptam não-barra-ou-asterisco
asteriscos:

      *asteriscosopt
não-barra-ou-asterisco:

      Qualquer caractere Unicode, exceto * ou /

Os comentários não aninham. As sequências de carateres /* e */ não têm um significado especial dentro de um comentário de linha única e as sequências de carateres // e /* não têm um significado especial dentro de um comentário delimitado.

Os comentários não são processados dentro de 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, palavra-chave, literal, operador ou pontuador. Espaço em branco e 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 Carateres

Os valores de texto M podem conter caracteres Unicode arbitrários. Os literais de texto, no entanto, 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 caractere de retorno de carro, alimentação de linha ou tabulação em um literal de texto, as #(cr)sequências , #(lf)e #(tab) escape podem ser usadas, respectivamente. Para incorporar os caracteres #( de início da sequência de escape em um literal de texto, o # próprio precisa ser escapado:

#(#)(

As sequências de escape também podem conter valores de ponto de código Unicode curtos (quatro dígitos hexadecimais) ou longos (oito dígitos hexadecimais). As três sequências de escape seguintes são, portanto, 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 duas sequências seguintes são, portanto, equivalentes:

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

A seguir descreve-se o mecanismo padrão de fuga de caracteres em um documento M.

caractere-fuga-sequência:
      #( escape-sequence-list )
escape-sequence-list:
      sequência de fuga única
      lista de sequências de fuga únicas-seqüentes-de-escape
,
sequência de escape único:
      long-unicode-escape-sequence
      curto-unicode-escape-sequence
      controle-caractere-fuga-sequência
      fuga-fuga
long-unicode-escape-sequence:
      hex-dígito hex-dígito hex-dígito hex-dígito hex-dígito hex-dígito hex-dígito
curto-unicode-escape-sequence:
      hex-digit hex-digit hex-digit hex-digit
controle-caractere-fuga-sequência:
      Caráter de controle
Caráter de controle:

      cr
      lf
      tab
fuga-fuga:
      #

Literais

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

literal:
      lógico-literal
      número-literal
      texto-literal
      nulo-literal
      verbatim-literal

Literais nulos

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

literal nulo:
      null

Literais lógicos

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

lógico-literal:
      true
      false

Literais numéricos

Um literal numérico é usado para escrever um valor numérico e produz um valor numérico.

número-literal:
      decimal-número-literal
      hexadecimal-número-literal
decimal-número-literal:
      decimais dígitos
.decimal expoente parte opt
      . parte expoentede dígitos decimais opt
      parte expoentede dígitos decimais opt
dígitos decimais:
      Os dígitos decimaisoptam por
dígito decimal:
um dos
      0 1 2 3 4 5 6 7 8 9
parte expoente:
      eassinaropt decimal-digits
      Eassinaropt decimal-digits
sinal:
um dos
      + -
hexadecimal-número-literal:
      0xdígitos hexadecimais
      0Xdígitos hexadecimais
dígitos hexadecimais:
      hex-digit hex-digitsopt
hex-digit:
um dos
      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 precedendo os dígitos hexadecimais com os caracteres 0x. Por exemplo:

0xff // 255

Observe que, se um ponto decimal é incluído em um número literal, então ele deve ter pelo menos um dígito seguindo-o. Por exemplo, é um número literal, 1.3 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.

texto-literal:
      " texto-literal-caracteresopt "
texto-literal-caracteres:
      texto-literal-caractere texto-literal-caracteresopt
texto-literal-caractere:
      caractere de texto único
      caractere-fuga-sequência
      seqüência de fuga de aspas duplas
caractere de texto único:

      Qualquer caractere, exceto " (U+0022) ou # (U+0023) seguido de ( (U+0028)
seqüência de fuga de aspas duplas:
      "" (U+0022, U+0022)

Para incluir aspas em um valor de texto, as aspas são repetidas da seguinte maneira:

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

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

"Hello world#(cr,lf)"

Literais literais

Um literal literal é 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.

verbatim-literal:
      #!"texto-literal-caracteresopt "

Identificadores

Um identificador é um nome utilizado para se referir a um valor. Os identificadores podem ser identificadores regulares ou identificadores entre aspas.

identificador:
      identificador regular
      identificador cotado
identificador regular:
      identificador disponível
      available-identifier dot-character regular-identifier
identificador disponível:

      Uma palavra-chave ou identificador que não é uma palavra-chave
palavra-chave ou identificador:
      identifier-start-character identifier-part-charactersopt
identificador-início-caractere:
      letra-caractere
      sublinhado-caráter
caracteres-parte-identificador:
      identificador-parte-caractere identificador-parte-caracteresopt
identificador-part-character:
      letra-caractere
      caracteres de dígito decimal
      sublinhado-caráter
      caractere de conexão
      caractere de combinação
      caractere de formatação
caractere-ponto:

      . (U+002E)
sublinhado-caráter:
      _ (U+005F)
caractere-letra:
      Um caractere Unicode das classes Lu, Ll, Lt, Lm, Lo ou Nl
Combinação-caráter:
      Um caractere Unicode das classes Mn ou Mc
caractere de dígito decimal:
      Um caractere Unicode da classe Nd
Caráter 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 identificador, incluindo palavras-chave, espaços em branco, comentários, operadores e pontuadores.

citado-identificador:
      #" texto-literal-caracteresopt "

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

O exemplo a seguir usa aspas de identificador para nomes que contêm um caractere de espaço:

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

O exemplo a seguir usa a cotação de identificador para incluir o + operador em um identificador:

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

Identificadores generalizados

Há dois lugares em M onde nenhuma ambiguidade é introduzida por identificadores que contêm espaços em branco ou que são palavras-chave ou literais de número. Esses lugares são os nomes dos campos de registro em um literal de registro e em um operador de acesso a campo ([ ]) Lá, M permite tais identificadores sem ter que usar 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 referidos como identificadores generalizados e definidos da seguinte forma:

identificador generalizado:
      generaled-identifier-part
      identificador
generalizado separado apenas por espaços em branco (U+0020)
generaled-identifier-part
generaled-identifier-part:
      generaled-identifier-segment
      decimal-digit-caractere-generaled-identifier-segment
generaled-identifier-segment:
      palavra-chave ou identificador
      palavra-chave ou identificador ponto-caractere palavra-chave ou-identificador

Palavras-chave

Uma palavra-chave é uma sequência de caracteres semelhante a um identificador que é reservada e não pode ser usada como um identificador, exceto quando se usa o mecanismo de citação de identificador ou quando um identificador generalizado é permitido.

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

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

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