I blocchi implicano l'uso di parentesi. Ad esempio, quando vedi i seguenti blocchi, assumere che il significato sia -(5 + 2)
e non -5 + 2
perché 5
e 2
fanno parte di un blocco e -
fa parte di un altro blocco.
Tuttavia, se inserisci le parentesi tonde attorno a ogni blocco, il codice diventa molto meno scorrevole. Confronta (((5) * (2)) + (3))
con 5 * 2 + 3
. Entrambe queste espressioni danno lo stesso risultato (13
), ma la seconda è molto più facile da leggere.
Le regole di precedenza degli operatori di Blockly ti aiutano a generare codice con il numero minimo di parentesi per una leggibilità ottimale.
Generare un output "corretto"
Se non è necessario che il codice generato sia leggibile da un essere umano, non è necessario preoccuparsi di ridurre al minimo le parentesi. È un approccio valido, e garantisce che il codice generato venga sempre valutato correttamente.
Per garantire la correttezza, passa sempre Order.ATOMIC
alle chiamate valueToCode
e
riporta sempre Order.NONE
dal generatore di codice blocco.
Genera parentesi ottimali
Le parentesi devono essere inserite solo se il codice generato è errato senza di esse. Questo accade quando la precedenza di un operatore nel blocco esterno è più forte della precedenza di un operatore nel blocco interno.
Ad esempio, nei blocchi seguenti sono presenti un operatore di negazione unaria e un operatore di addizione. La negazione unaria ha una precedenza maggiore rispetto all'operatore di addizione.
Pertanto, se non aggiungi le parentesi, ottieni -5 + 2
e -
viene valutato prima di +
, il che non corrisponde ai blocchi.
Puoi dire al generatore quando inserire le parentesi indicando l'importanza dei diversi operatori. Se rileva che l'operatore esterno è più forte dell'operatore interno, inserisce le parentesi per proteggerlo.
valueToCode
prende la precedenza dell'operatore esterno e la tuple di ritorno specifica la precedenza dell'operatore interno.
Ecco un esempio di blocco che include due operatori:
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];
}
Precedenza di valueToCode
Quando chiami valueToCode
per generare il codice di un blocco interno, gli passi la precedenza dell'operatore più forte che agisce sul codice del blocco interno. Questo è l'operatore da cui il codice del blocco interno deve essere protetto.
Ad esempio, nei blocchi seguenti sia l'operatore di negazione unaria sia l'operatore di addizione agiscono sul codice del blocco interno. La negazione unaria è più forte, quindi è la precedenza che devi passare a valueToCode
.
// The - is the strongest operator acting on the inner code.
const innerCode = generator.valueToCode(block, 'INNER', Order.UNARY_NEGATION);
const code = `-${innerCode} + 2`;
Precedenza del ritorno
Quando restituisci una precedenza dal generatore di codice del blocco, restituisci la precedenza dell'operatore più debole all'interno del codice del blocco. Si tratta dell'operatore che deve essere protetto.
Ad esempio, il seguente blocco contiene sia un operatore di negazione unario sia un operatore di addizione. L'addizione è più debole, quindi è la precedenza che devi restituire dal generatore di codice blocco.
const code = `-${innerCode} + 2`;
// The + is the weakest operator in the block.
return [code, Order.ADDITION];
Ordine enum
Ogni modulo del generatore di lingue definisce un enum Order
che include tutte le precedenze per quella lingua.
Le precedenze più elevate hanno valori di supporto inferiori, mentre quelle più basse hanno valori di supporto superiori. Puoi considerare le precedenze forti come "classificate più in alto" in termini di forza e le precedenze più deboli come "classificate più in basso", come se fossero lottatori competitivi.
Qui puoi trovare gli enum Order
per tutte le lingue integrate:
Precedenze speciali
La maggior parte delle precedenze negli enum Order
dei generatori corrisponde alle precedenze
definite dai rispettivi linguaggi basati su testo. Esistono però due precedenze speciali, Order.ATOMIC
e Order.NONE
.
Order.ATOMIC
è la precedenza più elevata. Viene utilizzata quando:
- Vuoi assicurarti che il codice sia sempre tra parentesi, quindi lo passi a
valueToCode
. - Il blocco non include operatori, quindi lo restituisci dal generatore di codice del blocco.
Order.NONE
è la priorità più bassa. Viene utilizzata quando:
- Vuoi assicurarti che il codice sia sempre tra parentesi, quindi lo restituisci dal generatore di codice in blocco.
- Non ci sono operatori che agiscono su un blocco interno, quindi lo passi a
valueToCode
.