Analisi di testo sensibile al contesto complesso

-2

Sto cercando di imparare come gestire la sensibilità al contesto complessa durante l'analisi. Supponiamo che tu abbia questo semplice esempio di codice:

var x = 10
var y = x + 10
var z = y + 10
var a = z + 10
var b = a + 10
var c = b + 10

Se fosse semplicemente un JavaScript, le variabili valuterebbero questo:

x == 10
y == 20
z == 30
a == 40
b == 50
c == 60

Tuttavia, voglio renderlo molto più sensibile al contesto aggiungendovi una certa complessità arbitraria. Supponiamo che aggiungiamo la seguente regola parser :

If somewhere in the code there is the expression c = b + 10 and y = x, then make a be 5 more than whatever it is set to, as well as converting it to a string.

Ciò significherebbe risolvere il problema in questo modo:

x == 10
y == 20
z == 30
a == "45"
b == "4510"
c == "451010"

Spero che questo esempio non abbia alcuni casi limite per renderlo facile da analizzare. Quello che spero di ottenere è come analizzare in modo efficiente le espressioni .

Dalla mia comprensione, questa è la sensibilità al contesto. Diciamo che il parser è stato rinato in parole / valori e spazi, quindi siamo rimasti con solo token non spaziali. Abbiamo la regola che cerca c = b + 10 e y = x quando arriviamo a a . Quindi quando arriviamo a a , cerchiamo in giro . Guardiamo avanti e indietro e tutto intorno cercando di trovare le espressioni. Scopriamo che c = b + 10 è avanti con un bel numero di token e y = x è dietro a qualche token. Ora immagina che questo file sia lungo 10.000 righe con funzioni complesse e simili, quindi dovrebbe eseguire la scansione dell'intero file ovunque per capirlo, una volta arrivato a var a . Ora immagina di avere più di una regola, ma 100 regole, quindi è costantemente in scansione su tutto il file.

Mi chiedo quale tipo di modello dovrebbe essere usato per gestire questo. Sembra che ci siano almeno due grandi cose che puoi fare per dare una mano. Il primo è quello di costruire una comprensione del testo mentre si va dall'inizio alla posizione corrente . Quindi sapremmo che la regola è presente per y = x (e c = b + 10 ), quindi dovremmo cercare questo in ogni fase del percorso, magari creando una sorta di struttura dati. Una volta trovato, potremmo avere un modo per cercarlo rapidamente una volta che abbiamo trovato var a . Ma non abbiamo ancora c = b + 10 fino alla fine del file. Quindi è come se dovessimo saltare tutto in qualche modo e "leggere" analizzare il resto finché non troviamo c = b + 10 , o lo analizziamo completamente facendo a = 40 e b = 50 , ecc., Finché non troviamo finalmente c = b + 10 , e poi tornare a var a e ri-analizzare con la nuova comprensione . Qualcosa del genere. Il problema è che tutti questi modi sembrano molto elaborati e complicati da comprendere.

Chiedendosi se si potrebbe far luce sui migliori approcci o tecniche su come gestirlo. Non necessariamente algoritmi specifici come immagino sia complicato, ma forse pensieri su dove guardare o come avvicinarsi.

Per approfondire, dì che abbiamo avuto queste regole:

(1) If somewhere in the code there is the expression c = b + 10 and y = x, then make a be 5 more than whatever it is set to, as well as converting it to a string. (2) If b == "4510" then make y == 25, and propagate the rest...

Potrebbe continuare ad andare in circolo come una cosa da iterazione a virgola fissa. Finché non arrivi finalmente al parsing finale. Un'interpretazione influisce sulla prossima influenza sulla successiva fino a quando non si assesta. Sembra che potrebbe esserci un sistema.

Ti stai chiedendo se esiste un qualche tipo di sistema per questo, come "l'iterazione del punto fisso su parser top-down o bottom-up con stato globale e sensibilità al contesto".

    
posta Lance Pollard 27.07.2018 - 09:47
fonte

3 risposte

1

In questo caso, cercherò qualcosa come il progetto Roslyn di Microsoft per l'ispirazione Wikipedia

I passaggi da seguire sono tutti relativi all'analisi statica del codice con le regole in vigore. Roslyn usa più stadi per fare questa analisi e ti suggerisco di fare lo stesso. In primo luogo, tokenize tutto il codice in una struttura di oggetto. Nel tuo caso, vuoi assicurarti di avere un costrutto in cui sono presenti variabili e valori dopo questa fase, ma dovresti anche essere in grado di scoprire se alcune espressioni esistono nel codice.

Successivamente, applicheresti le regole utilizzando queste due funzionalità dei tuoi oggetti. Per fare ciò, potresti includere un'altra funzione nei tuoi oggetti che ti consente di impostare una variabile e avere tutto dopo averla rivalutata.

Quindi, potresti voler ottimizzare tutto il codice.

E infine, si dovrebbe emettere il codice completato per qualsiasi output è adatto.

    
risposta data 27.07.2018 - 14:02
fonte
1

Un approccio tipico che ho visto è elaborare le "regole di contesto" più complesse come un preprocessore , che emette un codice diretto (come nell'esempio superiore), e quindi per elaborare questo codice con un processo standard più semplice.

Ecco come viene eseguita la pre-elaborazione di C e C ++, e anche come sono stati costruiti i primi compilatori C ++: leggono i nuovi elementi di sintassi "fancier" e generano codice (brutto e dettagliato, ma corretto); quindi il compilatore C l'ha eseguito.

    
risposta data 27.07.2018 - 17:08
fonte
0

Questo è probabilmente un approccio ingenuo, ma dato il contesto dato potrebbe funzionare abbastanza bene; Semplice iniziare con un "light parse" come l'hai detto, cercando solo le espressioni considerate per la tua regola, tenendo nota delle parti di quelle regole che hai già trovato e poi passando effettivamente attraverso il codice per valutare una volta "ovunque il codice "regole sono state valutate.

    
risposta data 27.07.2018 - 16:12
fonte

Leggi altre domande sui tag