Inserção de parênteses

Os blocos sugerem parênteses. Por exemplo, ao ver os blocos a seguir, você supõe que significa -(5 + 2), e não -5 + 2, porque 5 e 2 fazem parte de um bloco, e o - faz parte de outro.

blocos que representam -(5 + 2);

No entanto, se você colocar parênteses em cada bloco, o código ficará muito menos legível. Compare (((5) * (2)) + (3)) com 5 * 2 + 3. As duas expressões avaliam a mesma coisa (13), mas a segunda é muito mais fácil de ler.

As regras de precedência de operadores do Blockly ajudam a gerar o código com o número mínimo de parênteses, para maior legibilidade.

Gerar uma saída "correta"

Se você não precisa que o código gerado seja legível, 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 exatidão, sempre transmita Order.ATOMIC para chamadas valueToCode e sempre retorne Order.NONE do gerador de código de bloco.

Gerar parênteses ideais

Os parênteses só precisam ser inseridos se o código gerado estiver incorreto sem eles. Isso acontece quando a precedência de um operador no bloco externo é mais forte 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 operador de adição. A negação unária tem uma precedência mais forte do que o operador de adição.

negação e adição

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

Você pode informar ao gerador quando inserir parênteses, informando a intensidade dos diferentes operadores. Se ele notar que o operador externo é mais forte que o interno, ele insere parênteses para proteger o operador interno.

valueToCode tem a precedência do operador externo, e a tupla de retorno 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 bloco
filho.

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

Ao chamar valueToCode para gerar o código de um bloco interno, você transmite a ele a precedência do operador mais forte que atua no código do bloco interno. Esse é o operador do qual o código do bloco interno precisa ser protegido.

Por exemplo, nos blocos a seguir, o operador de negação unário e o operador de adição atuam no código do bloco interno. A 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 bloco
filho.

// 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 devolução

Quando você retornar uma precedência do seu gerador de código de bloco, retorne a precedência do operador mais fraco no código do bloco. Esse é o operador que precisa de proteção.

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

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

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

enumeração do pedido

Cada módulo de gerador de idioma define um tipo enumerado Order que inclui todas as precedências desse idioma.

Precedências mais fortes têm valores de apoio menores e precedências mais fracas têm valores de apoio mais altos. Pense em precedências fortes como uma "classificação mais alta" em força e nas precedências mais fracas como sendo "classificadas em menor nível", como se fossem lutadores competitivos.

Veja onde você encontra os tipos enumerados Order para todos os idiomas integrados:

Precedências especiais

A maioria das precedências nos tipos enumerados Order dos geradores corresponde às precedências definidas pelos respectivos idiomas baseados em texto. Mas há duas precedências especiais, Order.ATOMIC e Order.NONE.

Order.ATOMIC é a precedência mais forte. Ela é usada quando:

Order.NONE é a precedência mais fraca. Ela é usada quando: