Sto lavorando su parser che non elaborano solo contenuti delimitati, ma anche sequenze di escape all'interno di determinate parti di quel contenuto. Sto contemplando l'efficienza di diversi approcci alla tokenizzazione e apprezzerei i pensieri su quanto segue.
Per usare JSON come un solo esempio, ci sono alcuni modi per elaborare quanto segue:
["Foo\n"]
Considera che il flusso di input potrebbe essere multi-megabyte con molte sequenze di escape / evasioni varie
approcci:
Per carattere
La prima opzione è semplicemente quella di tokenize per carattere:
[array string #"F" #"o" #"o" #"^/" /string /array]
Pro: uniforme, veloce da implementare, funziona bene con i contenuti in streaming
Con: non è affatto efficiente poiché stai invocando il gestore di token per un numero di token simile al numero di caratteri nel flusso di input.
Con token di escape / non-escape
Un tokenizzatore un po 'più efficiente potrebbe comportare:
[array string "Foo" "^/" /string /array]
Pro: un po 'più efficiente, rapido da implementare
Contro: ci sono ancora molti token per contenuti ad alto rischio di escape, non può implicare che due token rappresentino uno o due elementi
Per Token interi
Un tokenizzatore minimo potrebbe produrre quanto segue:
[array "Foo^/" /array]
Pro: molti meno token da gestire
Con: questo solleva molte domande, tra le principali: come viene creata la stringa "Foo^/"
? Per rompere questo, prenderà in considerazione due sotto-approcci:
Abbina la sequenza, quindi risolvi gli escape:
Questo potrebbe essere gestito così:
[
"[" (emit 'array)
| "]" (emit /array)
| {"} copy value string-sequence {"} (emit de-escape value)
]
Professionisti: identifica rapidamente le partite, usa e modifica una singola stringa
Contro: si tratta in effetti di un processo a due passaggi: potrebbero esserci due regole separate per abbinare le sequenze di escape: una in string-sequence
e una in de-escape
- ecco lo sforzo extra per garantire che siano coerenti
Abbina porzioni della stringa e aggiungi a un buffer:
Potrebbe essere:
[
"[" (emit 'array)
| "]" (emit /array)
| {"} (buffer: make string! "") some [
copy part unescaped-sequence (append buffer part)
| "\n" (append buffer "^/")
] {"} (emit buffer)
]
Professionisti: un passaggio
Contro: Ora torniamo alla gestione di blocchi simili al metodo "Gestisci la sequenza di escape / non-escaping" e gestendo un valore aggiuntivo buffer
.