Os blocos implicam parênteses. Por exemplo, quando você vê os blocos a seguir,
supõe que significa -(5 + 2)
, não -5 + 2
, porque o 5
e o 2
fazem parte de
um bloco, e o -
faz parte de outro bloco.
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
. Ambas as expressões
são avaliadas como 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 código com o número mínimo de parênteses, para máxima legibilidade.
Gerar saída "correta"
Se você não precisa que o código gerado seja legível por humanos, não é necessário minimizar os parênteses. O agrupamento de 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
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 do que a precedência de um operador no bloco interno.
Por exemplo, nos blocos a seguir, há um operador de negação unária e um operador de adição. A negação unária tem uma precedência maior do que o operador de adição.
Portanto, se você não adicionar parênteses, vai receber -5 + 2
, e o -
será avaliado
antes do +
, que não corresponde aos blocos.
É possível informar ao gerador quando inserir parênteses informando a força dos operadores diferentes. Se ele detectar que o operador externo é mais forte do que o interno, ele vai inserir parênteses para proteger o operador interno.
valueToCode
recebe a precedência do operador externo, e a tupla
de retorno especifica a precedência do operador interno.
Confira um exemplo de bloco que inclui dois operadores:
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 transmite
a precedência do operador mais forte atuando no código do bloco
interno. Esse é o operador contra o qual o código do bloco interno precisa ser protegido.
Por exemplo, nos blocos a seguir, o operador de negação unária e o
operador de adição estão atuando 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
.
// 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 da devolução
Ao retornar uma precedência do 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ária 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.
const code = `-${innerCode} + 2`;
// The + is the weakest operator in the block.
return [code, Order.ADDITION];
Enum de ordenação
Cada módulo do gerador de idioma define um tipo enumerado Order
que inclui todas
as precedências desse idioma.
As precedências mais fortes têm valores de suporte mais baixos, e as mais fracas têm valores de suporte mais altos. Você pode pensar em precedências fortes como "classificadas como mais fortes" e em precedências fracas como "classificadas como mais fracas", como se fossem lutadores competitivos.
Confira 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. No entanto, há duas precedências
especiais, Order.ATOMIC
e Order.NONE
.
Order.ATOMIC
tem a precedência mais forte. Ele é usado quando:
- Você quer garantir que o código esteja sempre entre parênteses,
então você o transmite para
valueToCode
. - O bloco não inclui operadores, então ele é retornado pelo gerador de código de bloco.
Order.NONE
é a precedência mais fraca. Ele é usado quando:
- Você quer garantir que o código esteja sempre entre parênteses, então você o retorna do gerador de código de bloco.
- Como não há operadores atuando em um bloco interno, ele é transmitido para
valueToCode
.