Inserção de parênteses

Os blocos implicam parênteses. Por exemplo, ao ver os blocos a seguir, suponha que isso significa -(5 + 2), e não -5 + 2, porque 5 e 2 fazem parte de um bloco e o - é parte de outro bloco.

blocos que representam -(5 + 2)

Mas se você colocar parênteses em torno de cada bloco, o código ficará muito menos legível. Compare (((5) * (2)) + (3)) com 5 * 2 + 3. Ambas as opções as expressões são avaliadas como a mesma coisa (13), mas a segunda é muito mais fácil para ler.

As regras de precedência de operador do Blockly ajudam você a gerar um código número de parênteses, para facilitar a leitura.

Gerar "correto" saída

Se você não precisa que o código gerado seja legível por humanos, não é necessário se preocupar com a minimização dos parênteses. Envolver todos os blocos é uma boa abordagem, e garante que o código gerado seja sempre avaliado corretamente.

Para garantir a correção, sempre transmita Order.ATOMIC para chamadas valueToCode. sempre retornar Order.NONE do seu gerador de código de bloco.

Gerar parênteses ideais

Parênteses só precisam ser inseridos se o código gerado estiver incorreto sem para resolvê-los com rapidez. Isso acontece quando a precedência de um operador no bloco externo é mais forte do que a precedência de um operador no bloco interno.

Por exemplo, nos blocos a seguir há um operador de negação unário e um adicionar. A negação unária tem uma precedência mais forte do que a adicionar.

negação e adição

Portanto, se você não adicionar parênteses, -5 + 2, e - será avaliado. antes do +, que não corresponde aos blocos.

Você pode dizer ao gerador quando inserir parênteses, informando o quão forte de diferentes operadores. Se perceber que o operador externo é mais forte, que o operador interno, ele insere parênteses para proteger o operador interno.

valueToCode tem na precedência do operador externo, e o retorno tupla especifica a precedência do operador interno.

Aqui está um exemplo de um bloco que inclui dois operadores:

Um bloco com um operador de negação unário, um operador de adição e um filho
bloco de recursos dependente.

import {javascriptGenerator, Order} from 'blockly/javascript';

javascriptGenerator.forBlock['negate_plus_two'] = function(block, generator) {
  // valueToCode takes in the precedence of the outer operator.
  const innerCode = generator.valueToCode(block, 'INNER', Order.UNARY_NEGATION);
  const code = `-${innerCode} + 2`;
  // The return tuple specifies the precedence of the inner operator.
  return [code, Order.ADDITION];
}

Precedência de valueToCode

Quando você chama valueToCode para gerar o código de um bloco interno, ele é transmitido a precedência do operador mais forte agindo no código do bloco de recursos dependente. Esse é o operador do qual o código do bloco interno precisa ser protegido.

Por exemplo, no bloco a seguir, o operador de negação unário e o operador de adição atuam no código do bloco interno. Negação unária é mais forte, então essa é a precedência que você precisa transmitir para valueToCode.

Um bloco com um operador de negação unário, um operador de adição e um filho
bloco de recursos dependente.

// The - is the strongest operator acting on the inner code.
const innerCode = generator.valueToCode(block, 'INNER', Order.UNARY_NEGATION);
const code = `-${innerCode} + 2`;

Precedência de retorno

Ao retornar uma precedência do seu gerador de código de bloco, retorne o precedência do operador mais fraco dentro do código do bloco. Esta é a ou operador que precisa de proteção.

Por exemplo, o bloco a seguir contém um operador de negação unário e um adicionar. A adição é mais fraca, então essa é a precedência que você deve do gerador de código de bloco.

Um bloco com um operador de negação unário, um operador de adição e nenhum filho
bloquear

const code = `-${innerCode} + 2`;
// The + is the weakest operator in the block.
return [code, Order.ADDITION];

Enumeração do pedido

Cada módulo gerador de linguagem define um tipo enumerado Order que inclui todos os as precedências dela.

As precedências mais fortes têm valores de apoio menores, e as precedências mais fracas têm valores de apoio mais altos. Você pode pensar nas precedências fortes como sendo "classificadas mais alto" em força, e as mais fracas como “classificação inferior” como se eles eram lutadores competitivos.

Confira onde você pode encontrar os tipos enumerados Order para todos os idiomas integrados:

Precedências especiais

A maioria das precedências Os tipos enumerados Order correspondem às precedências definidos pelos respectivos idiomas baseados em texto. Mas há duas características precedências, Order.ATOMIC e Order.NONE.

Order.ATOMIC é a precedência mais forte. Ele é usado quando:

Order.NONE é a precedência mais fraca. Ele é usado quando: