Trova i seguenti set


14

La sfida di seguito richiede di avere familiarità con la teoria formale del parser. Se non sai quale sia la domanda, perché non sai cosa significano i termini, in molti corsi universitari vengono trattati grammatiche senza contesto e insiemi di primo / seguito.

Posso consigliare questo corso a Stanford , in particolare le dispense 08 e 09 (da pagina 7). Ho estratto anche un cheat sheet da questi volantini - consiglio a chiunque stia tentando questa sfida di leggerlo .


Scrivi un programma o una funzione che, data una grammatica libera dal contesto, trovi il seguente insieme di ogni non terminale. Informalmente, il seguente insieme di un non terminale è un insieme di terminali e $(che significa fine dell'input) che è possibile trovare dopo quel terminale in una frase valida.

L'input è dato come una singola stringa ASCII stampabile o matrice di linee ASCII stampabili. È possibile produrre gli insiemi in qualsiasi formato ragionevole, usando $(come output letterale o stringa all'interno di un insieme, ecc.) Per indicare la fine dell'input. Si può presumere che l'input sia sempre valido secondo il formato seguente.

La grammatica libera dal contesto è data in modo molto semplificato. Ogni linea contiene una singola produzione. Ogni produzione è un elenco di simboli separato da spazi. Un terminale è una stringa di caratteri circondata da apostrofi (ad es '**'.). Per semplicità puoi supporre che i terminali non contengano spazi, ma sarebbe bello se il tuo programma lo consentisse. Un non terminale può essere qualsiasi stringa che non contiene spazi o $. La produzione vuota (normalmente indicata con ε) è semplicemente una linea che contiene solo il lato sinistro non terminale. La prima riga è la produzione che definisce il simbolo iniziale.

Ad esempio, la seguente grammatica:

S → aSa | bSb | ε

Sarà dato come:

S 'a' S 'a'
S 'b' S 'b'
S

Esempi di input / output:

In:
S 'a' S 'a'
S 'b' S 'b'
S

Out:
S {'a', 'b', $}

In:
S A B C
A 'a'
A C 'b'
A
B C
B 'd' A
B
C 'e'
C 'f' 

Out:
S {$}
A {'d', 'e', 'f'}
B {'e', 'f'}
C {'b', 'e', 'f', $}

In:
Start Alice Bob
Alice Charlie 'a'
Alice
Bob Bob 'a' Alice Charlie
Bob '!!!'
Charlie 'b'
Charlie

Out:
Start {$}
Alice {'a', '!!!', 'b', $}
Bob {'a', $}
Charlie {'a', $}

Vince il codice più breve in byte.


4
Supponendo che le persone sappiano che cos'è una grammatica libera dal contesto sembra a posto, ma penso che non danneggerebbe la sfida se includessi la definizione di un set di follow qui proprio invece di collegarti ad essa.
Martin Ender,

1
Ciò riporta alcuni ricordi di " Compiler Construction " all'università, dove abbiamo dovuto risolvere molti compiti simili.
inserireusernamehere

Risposte:


3

Perl, 257 byte

Include +4 per -0p

Fornisci la grammatica su STDIN (senza spazi finali. Assicurati di rimuovere lo spazio aggiuntivo nel secondo esempio). Presuppone che i nomi non terminali contengano solo lettere, cifre e _. Utilizza #invece di $indicare la fine dell'input. Può gestire valori letterali contenenti spazi

perl -M5.010 follow.pl
E T e
e '+' T e
e
T F t
t '*' F t
t
F '(' E ')'
F 'id'
^D

Emette i seguenti insiemi come un elenco non-terminal literalin nessun ordine particolare. Per l'esempio sopra, genera:

F ')'
F #
t ')'
t #
T ')'
T #
F '+'
t '+'
T '+'
F '*'
e ')'
e #
E ')'
E #

follow.pl:

#!/usr/bin/perl -0n
s/'.*?'/~$&/eg;s% (?=(\w.*\n))%$_.=">$1"%reg;/\s/;$_.=">$` #\n";s%^((\w+)\K ?\S*).*%$s{$1}++||"\$a.=s/ $2\\b/$&/rg"%eemgr,s%^(\w+ ).*?(\w+)$%"\$a.=s/>$1/>$2 /rg"%eermg,$_.=$a,s%>.*\xd8\K .*%%g,s%.+\n%$&x!/\n$&/g%eg until$$_++;s/\xd8.*?\xd8/~$&/eg;say/>(\w+ \W\S*\n)/g

Funziona come mostrato, ma sostituisci \xd8e \ncon le loro versioni letterali per ottenere il punteggio richiesto.

Dovrebbe essere possibile migliorarlo poiché la conversione dei firstset in followset è attualmente molto imbarazzante.

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.