Data una stringa e un CFG, quali caratteri possono seguire la stringa (nelle forme sentenziali del CFG)?


10

Let l'insieme di terminale e l'insieme di simboli non terminali di alcuni grammatica libera dal contesto .N GΣNG

Supponiamo che io abbia una stringa tale che dove e sono le forme proposizionali di . x a y S ( G ) x , y ( Σ N ) S ( G ) Ga(ΣN)+Xun'yS(sol)X,y(ΣN)*S(sol)sol

Dato , vorrei determinare un set .C = { b w a b z S ( G ) , b Σ N }solC={B|wun'BzS(sol),BΣN}

Per chiarire, in questo caso, sono stringhe di terminali e non terminali e è di lunghezza uno.bw,X,y,z,un',BB

Posso vedere come fare questo se è anche di lunghezza; ogni è un membro dell'insieme seguente di (inclusi i non terminali).un'Bun'

Tuttavia, sono curioso di sapere se è possibile per una sequenza di personaggi. Per la mia applicazione, la stringa di non è molto più lungo del lato destro delle produzioni in .un'sol

La distinzione tra terminali e non terminali è piuttosto muta nella mia applicazione perché sto usando una grammatica generativa; e credo che questo non causerà molti problemi poiché è di lunghezza uno.B


1
Qual è la tua applicazione? Stai costruendo un parser?
Raffaello

Possiamo supporre che la grammatica sia in qualsiasi forma normale o debba funzionare per quelle arbitrarie?
Raffaello

@AlextenBrink - ed y sono stringhe arbitrarie. Sto solo guardando un frammento / sottostringa. Xy
Thomas

@Raphael - Sto cercando di automatizzare le trasformazioni delle grammatiche L-System ... quindi non è in forma normale. In effetti modificherò di nuovo questa domanda per renderla più precisa.
Thomas

Spero di non aver cambiato troppo la domanda: ora ha una natura leggermente diversa.
Thomas

Risposte:


6

Descriverò un algoritmo che funziona. Il tempo di esecuzione non dovrebbe essere così male. Puoi anche pre-calcolarne un po '.

Presumo che non contenga non terminali (anche se probabilmente è facile adattarsi a quel caso) e che non si conosce x , y o la derivazione di a . Presumo anche che la tua grammatica non contenga produzioni che non sono mai utilizzate in alcuna derivazione ( A A per esempio).un'Xyun'UNUN

Il problema principale è davvero analizzare , poiché vuoi sapere in che tipo di stati finisci, quindi sai cosa può seguire un . Non è così facile perché non conosci x .un'un'X

Usiamo un adattamento dell'algoritmo di Earley . Ti consigliamo di capire prima quell'algoritmo. Il nostro algoritmo funziona quasi allo stesso modo, tranne che le fasi di inizializzazione e completamento sono diverse.

Per l'inizializzazione, seminiamo il nostro primo set con un elemento Earley per ogni occorrenza di (il primo carattere in una ) in qualsiasi produzione del vostro grammatica. Impostiamo il puntatore indietro di questo elemento su -1, un valore non valido. Questo è importante nel nostro completamento modificato. In sostanza, -1 significa "Non ho idea di dove sia iniziata questa produzione".un'1un'

Ora eseguiamo l'algoritmo Earley separatamente per ogni possibile articolo Earley iniziale. Non possiamo semplicemente eseguirle tutte contemporaneamente, poiché le analisi potrebbero interferire tra loro. Non riesco a vedere facilmente un metodo più veloce del backtracking qui.

Per la fase di completamento, dobbiamo solo apportare una modifica per gestire -1 puntatori posteriori. Dato che abbiamo completato una produzione di cui non conosciamo l'origine, siamo nei guai. Tuttavia, il metodo utilizzato per calcolare i set di lookahead LUNLR(1) di Pennello e DeRemer ci salva: ciò di cui abbiamo bisogno qui è esattamente il set di lookahead . Ogni articolo in questi set di lookahead ha una posizione corrispondente nella grammatica, che a sua volta corrisponde a una possibile continuazione della produzione completata.LUNLR(1)

Sfortunatamente, non vedo davvero altra scelta che tornare indietro di nuovo qui. Per ogni posizione nel set di lookahead, esegui il passaggio di completamento con questa posizione e continua l'analisi da lì. Lo fai separatamente per ogni analisi. Nota che se la tua grammatica è , il tuo lookahead determinerà in modo univoco in quale posizione devi andare, quindi non devi tornare indietro.LUNLR(1)

un'

Modifica: penso di aver trovato il metodo che rimuove la maggior parte delle spese generali introdotte dal backtracking. Associamo ad ogni articolo Earley un insieme di identificatori, che sono stringhe, poiché dovremo utilizzare i prefissi di questi identificatori. All'inizializzazione, aggiungiamo tutti gli elementi iniziali al set Earley e associamo un identificatore univoco a ogni set.

Sulle fasi dello scanner e del predittore, gli identificatori vengono riportati a nuovi elementi. Gli articoli Earley nello stesso set Earley che differiscono solo nei loro identificatori vengono uniti unendo i loro identificatori insieme. È possibile eseguire passaggi dello scanner e dei predittori su questi nuovi elementi con identificatori, senza dover eseguire questo passaggio per ogni identificatore separatamente.

LUNLR(1)

In sostanza, eseguiamo il backtracking utilizzando questi identificatori, in modo da non fare doppio lavoro nei passaggi dello scanner e dei predittori.


un'un'

@Thomas Non è troppo difficile: consideri semplicemente il non terminale come un terminale per quella particolare posizione nell'analisi: continui a prevederlo e completarlo normalmente, ma lo consideri anche durante la scansione.
Alex ten Brink,

Sì, davvero - ora che ho capito la tua soluzione, non dovrebbe fare alcuna differenza.
Thomas
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.