Perché C ++ per scrivere un compilatore?


15

Mi chiedevo perché C ++ sia una buona scelta per scrivere un compilatore. Naturalmente C è buono anche per questo scopo, perché molti compilatori sono scritti in C o C ++ ma questa volta sono più interessato al C ++. Qualche buona ragione? Lo cercavo su Internet, ma non riesco a trovare buoni motivi.


3
"Molti compilatori sono scritti [...] in C ++" - qualche riferimento? Quale? Cosa ti fa pensare che il C ++ sia più spesso usato per la costruzione di compilatori rispetto ad altre lingue popolari?
Doc Brown,

5
@DocBrown Bene, Clang e MSVC sono scritti principalmente in C ++, gcc ha un po 'di C ++ in esso ora, Java JVM è scritto in C ++ stackoverflow.com/questions/410320/what-is-java-written-in e anche superutente. com / questions / 136136 /…
Klaim,

@DocBrown DMD il compilatore di riferimento per D è scritto in C ++
maniaco del cricchetto,

3
Chi dice che sia una buona scelta ??
Phil

1
@Phil Pensi che abbiano fatto questa scelta senza considerare le alternative? Non è una scelta "buona", è una scelta "efficiente".
Klaim,

Risposte:


21

Il C ++ ha due lati. Ha un lato di sviluppo di basso livello che lo fa sembrare un linguaggio naturale per fare cose di basso livello come la generazione di codice. Ha anche un lato di alto livello (cosa che C non ha) che ti consente di strutturare un'applicazione complessa (come un compilatore) in modo logico, orientato agli oggetti, mantenendo comunque le prestazioni. Poiché presenta aspetti sia di basso che di alto livello, è una buona scelta per applicazioni di grandi dimensioni che richiedono funzionalità o prestazioni di basso livello.


9
Per quanto ne so, gran parte della logica all'interno di un compilatore è di natura funzionale (trasformazione di strutture di dati complesse in altre strutture di dati), quindi non sono sicuro che strutture orientate agli oggetti (che sono più mirate alla programmazione in-the-large , aspetti architettonici) apportano un reale vantaggio alla costruzione di compilatori rispetto a uno stile di programmazione procedurale. Solo i miei 2 centesimi.
Giorgio,

5
@Giorgio Avere oggetti aiuta in molti altri aspetti della scrittura del compilatore. Ad esempio, c'è un sacco di stato che un compilatore deve affrontare durante l'ottimizzazione e quel tipo di cose si presta bene a OOP. Inoltre, la programmazione OOP e funzionale può essere abbastanza complementare, quindi solo perché gli algoritmi potrebbero essere principalmente funzionali, non significa che gli oggetti non aiuteranno.
Oleksi

3
@Giorgio e Oleksi: posso confermare entrambi. Ho scritto un compilatore con Haskell per una lingua del mondo reale. Era davvero una buona scelta. Ma a volte mi mancava un po 'di OO in giro. Se dovessi scrivere un altro compilatore sceglierei sicuramente Haskell, ma questo è davvero un caso speciale. Non sceglierei Haskell senza esitazione per altri tipi di progetti.
scarfridge

24
Perché hai bisogno di avere una lingua con un "lato di basso livello" per generare codice? Non riesco a vedere come questi due siano collegati in alcun modo.
phant0m

5
Non è necessario un "lato di basso livello" per generare codice più di quanto non siano necessari identificatori Unicode per poter scrivere testo giapponese in un file.
dan04,

11

La mia esperienza non è d'accordo con la tua premessa qui. In effetti, per le lingue di livello generale di alto livello, è una pratica molto comune scrivere il compilatore nella stessa lingua della lingua di origine (la lingua in fase di compilazione). Per esempio:

  • Il compilatore Java di Sun è scritto in Java
  • Il compilatore Scala è scritto in Scala
  • Il compilatore C # di Mono è scritto in C #
  • Il compilatore di Smalltalk di Squick è scritto in Smalltalk
  • ... e molti altri

Un'eccezione sono i front-end del compilatore scritti per i framework di compilatori esistenti, come GCC, LLVM o Polyglot, che vengono quindi scritti nel linguaggio del framework, o compilatori che si basano su generatori di parser esistenti come Yacc. Poiché GCC, LLVM e Yacc sono strumenti comuni e consolidati scritti in C e C ++, ciò incentiva gli scrittori di compilatori a usarli, il che potrebbe portare C e C ++ a ottenere una grande quota nella distribuzione del linguaggio di implementazione del compilatore.


2
Penso che abbia molto più a che fare con le persone che scrivono il compilatore conoscendo bene e amando molto la lingua per cui stanno scrivendo un compilatore che per ragioni tecniche oggettive.
Thomas Bonini,

1
@Krelp Sono d'accordo che non si tratta di un motivo tecnico oggettivo, ma non è nemmeno "gradimento" - è solo considerato un rito di passaggio per un linguaggio - "è abbastanza maturo per essere in grado di servire come linguaggio di implementazione a sé stante compilatore".
Oak,

1
Compilatore Java di Sun è scritto in C ++: stackoverflow.com/questions/410320/what-is-java-written-in
Klaim

10
@Klaim stai confondendo due prodotti qui. Uno è il compilatore Java ( javacriga di comando) di Sun , che compila da Java a Java Bytecode. È scritto in Java - L'ho modificato molte volte da solo e puoi sfogliare le sue fonti Java online . L'altro è il compilatore just-in-time incorporato nell'Hotspot JVM, che compila il codice byte Java in codice macchina nativo. Come la maggior parte della JVM è scritta in C ++, ma non è un compilatore Java - in realtà, non sa nulla del linguaggio Java.
Oak,

@Oak, assolutamente corretto! In altre parole, JVM! = Javac
Paul Draper,

5

Compilare cosa in cosa? Un compilatore trasforma un codice sorgente da una lingua ( lingua di origine) a un'altra (lingua di destinazione), il che non indica nulla sulla scarsa conoscenza della lingua di destinazione.

  • CoffeeScript viene compilato in JavaScript, il compilatore viene scritto in CoffeeScript.
  • Script # compila C # in JavaScript, il compilatore viene scritto in, se ricordo bene, C #.
  • eccetera.

La lingua scelta per scrivere un compilatore dipende dal contesto. Ad esempio, lavorando a un progetto che compila un linguaggio derivato da PHP in un codice PHP nativo, ho usato un mix di PHP e C # per scrivere il compilatore, perché aveva più senso per me date le mie capacità. Un'altra persona sceglierebbe Python, o Java e PHP, o C ++ con un po 'di JavaScript, o altro.

C o C ++ è una scelta popolare a causa del supporto di strumenti correlati al compilatore (vedi la risposta di Telastyn) e perché queste due lingue ti permettono di diventare veramente nativo. Ma non c'è niente di sbagliato nella scelta di un'altra lingua.

Nota che per essere più geek , puoi scegliere la lingua di origine per scrivere il compilatore stesso. È quello che è successo per il compilatore CoffeeScript e molti altri compilatori. È anche popolare tra gli IDE: uno dei primi Visual Studio è stato creato utilizzando lo stesso Visual Studio.


4
L'auto-hosting non è geniale, è una proprietà importante per il porting di un compilatore.

4
Il motivo è che consente immediatamente al compilatore stesso di essere un programma di test. Molto probabilmente sarà anche il più grande programma per quel compilatore per un bel po '.

5

Tendo a mettere in discussione la premessa di base qui. Mentre C e C ++ funzionano perfettamente per la scrittura di compilatori, parecchi altri linguaggi sembrano funzionare perfettamente anche per l'attività.

Un po 'dipende dalla lingua che stai compilando però. Per linguaggi piccoli e semplici, C e Pascal funzionano abbastanza bene. Se hai intenzione di compilare qualcosa di grande e complesso, anche il tuo compilatore diventa grande e complesso - nel qual caso, le funzionalità extra di C ++ per l'organizzazione e il lavoro con programmi più grandi sono ovviamente utili. Tuttavia, ciò non è molto specifico per la compilazione, ma solo funzioni utili per programmi più grandi in generale.

Penso che valga la pena menzionare anche un altro punto. I principianti (sembrano) pensano ai compilatori come principalmente alla manipolazione del testo, quindi pensano che qualcosa come Perl sarà di grande aiuto nella scrittura di compilatori. In realtà, la maggior parte delle parti interessanti della compilazione non iniziano davvero fino a quando non hai creato il tuo AST. Anche se sono sicuro che Perl può fare perfettamente il lavoro, la sua capacità di manipolazione del testo non gli dà nemmeno un enorme vantaggio (la manipolazione del testo è principalmente nel lexer e i generatori di lexer per cose come C tutti supportano comunque le RE).


2
AST = Abstract Syntax Tree, RE = Regular Expressions
chaotic3quilibrium

5

I compilatori possono essere implementati in qualsiasi linguaggio moderno. Tuttavia, uno dei requisiti più importanti di un compilatore è essere veloce.

Il C ++ ha un chiaro vantaggio qui. L'ottimizzazione in C ++ non è economica. Tuttavia, a causa della natura di basso livello di questa lingua, è possibile ottimizzare manualmente il codice C ++ più che in qualsiasi altra lingua (tranne Assembly che non è portatile).


9
Un altro requisito importante è che il codice generato sia corretto: preferirei avere un compilatore lento di cui mi posso fidare piuttosto che uno veloce che generi codice errato.

1
Sebbene sia certamente possibile ottimizzare il C ++ molto pesantemente, c'è un sacco di ... beh ... meno del codice C ++ ottimale là fuori.
Donal Fellows,

2
@DonalFellows Al contrario: è possibile scrivere un codice non ottimale in qualsiasi lingua, ma ci sono ottimizzazioni impossibili da abilitare in altre lingue oltre a C ++ (diverso da Assembler. Non includo C per mancanza di strutture di alto livello che consentono un allineamento più forte)
Klaim,

2

Ho il sospetto che la motivazione principale per il loro uso sia che l'output di Lex / Yacc / Bison sia (principalmente) in C. Dal momento che quello è stato lo standard per così tanto tempo, ha slancio.

Non che quelle siano ragioni particolarmente buone ...


In realtà non mi soddisfa, ma grazie per la prova.
Kobra,

Ciò non risponde alla domanda "perché scegliere C ++ su C per la costruzione del compilatore".
Doc Brown,

2
Non è affatto una buona ragione. Strumenti analoghi a Lex e Yacc esistono per molte piattaforme. PLY e ANTLR, per esempio.
user16764,

Inoltre, i compilatori più famosi del mondo reale (sono abbastanza certo per Clang e GCC, per esempio) usano parser scritti a mano.

@delnan: Sì, ma probabilmente hanno iniziato a usarne uno generato per far decollare le cose. La generazione manuale del parser è un passaggio di ottimizzazione che non si vuole veramente fare fino a quando non si può provare che altre cose funzionano.
Martin York,

0

Ho esperienza con questa materia. Ho scritto compilatori in C e C ++. La differenza principale tra C e C ++ è che C non ha una gestione dinamica della memoria in modo automatico. Tutta la gestione della memoria in C deve essere fatta esplicitamente. Scrivere un compilatore si occupa molto dell'elaborazione delle stringhe e della gestione dell'array. In C sei costretto a pensare alla dimensione di ogni stringa e di ogni matrice dichiarata e anche a controllare gli indici quando accedi a quegli oggetti (se vuoi che il tuo codice sia sicuro e stabile). In C puoi avere una gestione dinamica della memoria, ovviamente, ma nulla è automatico. Devi allocare in modo esplicito e liberare memoria usando malloc () e free (), mantenere la dimensione dei tuoi oggetti dinamici in variabili separate per essere sicuro di non accedervi fuori dai confini.

In C ++ puoi avere gli stessi meccanismi ma è davvero efficiente in termini di tempo di sviluppo perché tutta la tua gestione della memoria può essere incapsulata all'interno di costruttori e distruttori che non devi chiamare esplicitamente. Quindi il compilatore sta allocando e liberando risorse per te. La dimensione dei tuoi oggetti dinamici può essere incapsulata anche se crei le tue classi e puoi controllare gli indici per l'accesso ai confini sovraccaricando l'operatore []. Queste astrazioni aiutano a rendere il codice più pulito, più facile da comprendere e da eseguire il debug e rendono sicuramente lo sviluppo più veloce.

Se si crea un compilatore in C, ci vorrà sicuramente più tempo. C ++ ti farà finire il tuo progetto in meno tempo. C e C ++ hanno le stesse prestazioni ma C ++ ha molti vantaggi che C non ha.

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.