Perché una lingua sia programmabile, è obbligatorio che si basi su una grammatica libera dal contesto


23

In pratica, per un linguaggio che può eventualmente essere compilato / trasformato in istruzioni a livello di sistema, è necessario che sia una grammatica libera dal contesto?

es: tutte le lingue di programmazione / scripting sono grammatiche libere dal contesto? Java si basa su CFG, ma in realtà tutti i linguaggi di programmazione si basano su CFG?

Non sembra obbligatorio, ma ci sono lacune nella mia comprensione.

Qualche contesto per la domanda: stavo guardando le specifiche del linguaggio Java, che fornisce anche le regole grammaticali . Questo mi ha fatto pensare a questa domanda.


1
In generale, penso solo che tu voglia che il problema della compilazione sia calcolabile, e analizzare i CFG è facile e facile. Anche se ho sentito alcune affermazioni secondo cui, ad esempio, riconoscere programmi perl validi è in realtà un problema non calcolabile.
Janne H. Korhonen,

2
in realtà tutto ciò di cui hai veramente bisogno è una sintassi decidibile (che sono tutti i CFG). È inoltre potrebbe fare un linguaggio di programmazione, che la cui sintassi non è Turing-decidibile, ma quando si fa un errore di battitura il compilatore potrebbe non fermarsi mai, mentre si sta cercando di decidere se si tratta di è sintassi valida. questo non è davvero utile
maniaco del cricchetto,

@ratchet, stai assumendo che la sintassi debba essere enumerabile in modo ricorsivo?
David Harris,

4
@JanneKorhonen: In particolare, il Perl non può essere analizzato staticamente , ovvero non può essere analizzato senza essere eseguito; poiché detta esecuzione potrebbe essere non-terminante, l'analisi statica di Perl implicherebbe la risoluzione del problema di arresto.
Jon Purdy,

@janne Voglio dire, la post-elaborazione che può comportare problemi che possono o non possono essere calcolabili, è generalmente il caso in cui la grammatica finale rispetto alla quale il programma è validato è senza contesto. Per essere più precisi, dopo la pre-elaborazione, per identificare una regola che si adatta a una sequenza di token dobbiamo guardare altri token che circondano la sequenza. Non so se abbia senso, mi dispiace per quello. Sono un po 'confuso in realtà.
sandeepkunkunuru,

Risposte:


20

Due volte no.

Innanzitutto, la maggior parte degli HPL non sono privi di contesto. Sebbene di solito abbiano una sintassi basata su un CFG, hanno anche ciò che le persone chiamano semantica statica (che è anche spesso inclusa nel termine sintassi). Ciò può includere nomi e tipi che devono essere verificati per un programma corretto. Per esempio,

class A {
  String a = "a";
  int b = a + d;
}

è un programma Java sintatticamente corretto ma non verrà compilato perché dnon è definito e anon ha un tipo di adattamento.

In secondo luogo, è possibile analizzare linguaggi non privi di contesto (come ovviamente dimostrato dall'esistenza di compilatori). È solo che i CFG possono essere analizzati in modo efficiente, mentre i CSG non possono, in generale. Tuttavia, è possibile aggiungere alcune funzionalità senza contesto senza rimanere efficienti.

I compilatori vengono spesso eseguiti in fasi: prima la tokenizzazione (normale), quindi l'analisi senza contesto, quindi l'analisi del nome e del tipo (sensibile al contesto, a volte anche più difficile). Puoi osservare quel comportamento in base al tipo di messaggi di errore che ricevi.


3
Non dimenticare il public class Program { public static void main(String[] args) { ... } }... Java non ti lascerà scendere così facilmente. :-)
Roy Tinker l'

Tecnicamente, class A { ... }è completamente sufficiente poiché javaccompila cose che non puoi effettivamente eseguire (per mancanza di un punto di ingresso). Ma sì
Raffaello

20

6
Sento che questa dovrebbe essere la battuta finale di uno scherzo Perl :)
Suresh Venkat,

5
Suresh: Ho già fatto quella battuta, anche se non si è rivelata una battuta molto buona, nel documento "Su linguaggi di programmazione inaffidabili" in SIGBOVIK 2011 ( sigbovik.org/2011/proceedings.pdf - pagina 79- 82).
Rob Simmons,

1
Nota: l'interprete Perl non è ancora non deterministico, se questo è di conforto per nessuno :)
Roy Tinker

15

Non credo che la grammatica di Python sia senza contesto. Il requisito che le righe nello stesso blocco di codice abbiano la stessa quantità di rientro non è il genere di cose che le grammatiche libere dal contesto gestiscono bene.

Più precisamente, sembra esserci un omomorfismo dal linguaggio dei blocchi Python della forma

se condizione:
     Linea 1
     linea 2
     line3
altro:
     Line4

al linguaggio senza contesto cui il primo blocco di zeri proviene dall'insieme di spazi all'inizio della riga 1, il secondo blocco arriva l'insieme di spazi all'inizio della riga 2, il terzo blocco arriva dall'insieme di spazi all'inizio di line3, e le restanti linee con else etc sono lì per forzare line1, line2 e line3 ad appartenere allo stesso blocco.0n10n10n


4
Strettamente hai ragione, ma nel contesto dei linguaggi di programmazione cerchiamo di rendere privo di contesto il linguaggio risultante dopo una fase di preelaborazione chiamata tokenizzazione . Penso che il rientro sia verificato prima di quello.
Diego de Estrada,

7
Sì, il lexer di Python (tokenizer) ha una pila di profondità di rientro; il flusso di token ha un simbolo INDENT all'inizio di ogni blocco e un simbolo DEDENT alla fine che può essere analizzato in modo libero dal contesto (INDENT e DEDENT agiscono in modo simile alle parentesi graffe in C). C ha il problema "non so se dichiarazione o espressione": foo * bar;una dichiarazione è foocome un puntatore baro una moltiplicazione dei footempi bar?
Max

8
Ok, certo, ma poi stai solo nascondendo la stessa complessità nel lexer, piuttosto che renderlo un trasduttore di stato finito come spesso accade.
David Eppstein,

1
@DavidEppstein: Ad essere onesti, ha detto che la complessità non è eccezionale.
Jon Purdy,

1
Oltre alla gestione di INDENT / DEDENT nel lexer, Python ha una grammatica LL (1) molto semplice.
rmmh

13

Bodo Manthey e Martin Böhme mostrano che ogni compilatore C ++ è necessariamente Turing completo, ovvero può calcolare qualsiasi funzione ricorsiva parziale al momento della compilazione momento della . Quindi è molto peggio di un semplice contesto.

http://wwwhome.math.utwente.nl/~mantheyb/journals/BotEATCS_BoehmeManthey_CompilingCPP.pdf


Sì, ma il compilatore non è mai solo grammatica senza contesto. Dovresti discutere della grammatica stessa, non del compilatore.
Jeff Burdges,

@Jeff: "Tempo di compilazione" nella mia risposta significa "verificare se un determinato codice sorgente C + è corretto". Con una leggera modifica della costruzione nel documento, ne consegue che è possibile ridurre ogni lingua decidibile all'insieme di tutti i programmi C ++ corretti.
Markus Bläser il

7

Penso che la dichiarazione prima dell'uso delle variabili e il polimorfismo delle funzioni dei linguaggi OOP siano altri esempi di specifiche dei linguaggi di programmazione che non possono essere gestite da grammatiche libere dal contesto:

int myfun(int a) { ... }
int myfun(int a, int b) { ... }
int myfun(int a, int b, int c, ...) { ... }
...
int I_m_I_cfg = myfun(1,2);
...

Ho fatto una piccola ricerca su Google e ho trovato questo articolo: " A Boolean Grammar for a Simple Boolean Language " di A.Okhotin (2004); secondo lui, il vero problema è trovare un linguaggio di programmazione completamente descritto da una grammatica formale:

Viene definito un linguaggio di programmazione procedurale e viene costruita una grammatica booleana per l'insieme di programmi ben formati in questo linguaggio. Questa è apparentemente la prima specifica di un linguaggio di programmazione interamente da una grammatica formale.

La sezione Introduzione dell'articolo è breve ma molto chiara.


6

Credo che la grammatica di C sia tecnicamente priva di contesto in quanto i parser usano sempre tecniche senza contesto per supportare il dispositivo di Duff .

Le lingue basate sul rientro non sono naturalmente prive di contesto, come ha detto David, ma diventano prive di contesto rispetto a un token di rientro parametrizzato.

Haskell ti consente di cambiare la precedenza dell'operatore con infix e infixl. Il rigoroso modulo pragma di Perl è implementato usando le impostazioni lessicali $ ^ H e% ^ H, che lo rendono non privo di contesto, probabilmente anche altre impostazioni.

Esistono linguaggi di espansione macro come TeX in cui l'analisi di afaik non ha senso senza eseguire.

Probabilmente ci sono anche due grammatiche senza contesto, l'intersezione non è senza contesto ma descrive comunque una macchina di Turing.

Java e assemblatore sono probabilmente entrambi naturalmente privi di contesto.


2
L'ambiguità di (a)-brendere C sensibile al contesto? ( apotrebbe essere una variabile o un typedef - alcune altre lingue non consentono il cast di espressioni meno unarie per questo motivo)
Casuale832

Mi scuso per il commento molto ritardato, ma il dispositivo di Duff non prevede deviazioni sintattiche. Le parentesi graffe si bilanciano correttamente. La caratteristica C più spesso ignorata nelle discussioni sul fatto che C sia libera dal contesto è il preprocessore. Sono scettico sul fatto che esista un'interpretazione, per quanto informale, di "contesto libero" che consente di utilizzarlo per descrivere un linguaggio con un processore macro, anche ben educato. E il preprocessore C è tutt'altro che ben educato.
rici,

4

No, e molte lingue pratiche non sono prive di contesto. Ad esempio la grammatica C ++ non lo è, perché in alcuni contesti la risoluzione grammaticale dipende dalla digitazione di informazioni non libere dal contesto.


4

Prima di tutto, vorrei fare una distinzione tra la sintassi di un linguaggio di programmazione e il linguaggio stesso.

La sintassi di molte lingue è (almeno basata su) una grammatica libera da contesto (CFG) perché sono ben studiate e ci sono algoritmi che possono analizzare in modo efficiente un CFG e il caso limite che non può essere risolto dal CFG può essere gestito in modo speciale

Tuttavia, molte lingue non sono in realtà senza contesto (quando vengono utilizzati simboli di dichiarazione prima dell'uso, ad esempio in java, C (++), D).

Curiosità: D ha una valutazione della funzione di compilazione-tempo completa di Turing e l'espansione del modello che rende il linguaggio stesso non-decidibile. Tuttavia, il creatore della lingua ha fatto di tutto per rendere la sintassi un CFG.


L'analisi di nomi e tipi in genere esegue attività intrinsecamente senza contesto.
Raffaello,

La meta-programmazione dei template in C ++ è Turing completa.
Jeff Burdges,

3

Per quanto riguarda "Tutte le grammatiche di contesto di programmazione / scripting sono libere dal contesto?" parte è preoccupata, la risposta è un numero definito

Ri: la domanda principale di "per un linguaggio che alla fine può essere compilato / trasformato in istruzioni a livello di sistema", non so perché debba necessariamente essere un CFG. Tuttavia, potrebbero esserci spiegazioni migliori.


1
Kris, puoi darci alcuni esempi di linguaggi di programmazione basati sulla grammatica senza contesto. Voglio dire, post pre-elaborazione che può comportare problemi che possono o non possono essere calcolabili, la grammatica finale rispetto alla quale il programma è validato.
sandeepkunkunuru

3

Un linguaggio di programmazione deve essere basato su un qualche tipo di formalismo grammaticale, di cui i CFG ne sono un esempio. Mentre i CFG sono i più comuni (e sono la solita cosa insegnata nei corsi di compilazione presso le università), ci sono altri formalismi come Parsing Expression Grammars, che puoi leggere di più qui (pdf) o su Wikipedia per una lettura più mordace.

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.