9

Ho bisogno di andare in giro a scrivere quel linguaggio di programmazione che intendevo scrivere. Come fanno i bambini a farlo in questi giorni? Sono fuori dal giro da oltre un decennio; lo stai facendo in modo diverso ora di quanto non facessimo nei giorni pre-internet, pre-windows? Sai, quando i codificatori "reali" codificati in C, usavano la linea di comando, e cavillosi su quale shell era superiore?Come creare una lingua in questi giorni?

Giusto per chiarire, voglio dire, non come si progetta un linguaggio (che riesco a capire abbastanza facilmente) ma come si costruisce il compilatore e le librerie standard e così via? Che strumenti usi oggi ai tuoi bambini?

+8

Per la cronaca, noi "figli" usano ancora la riga di comando e cavillo su quale shell è superiore, o almeno lo faccio C. C è morto, ma ora devo fuggire dall'avanguardia dei programmatori C, quindi ci vediamo in giro! –

+0

Che tipo di linguaggio, interpretato o compilato? –

+0

interpretato o compilato? Hmmm buona domanda.Però suppongo che faccia la differenza, quindi dirò entrambi solo per essere al sicuro. – Mike

risposta

2

Sono quasi sicuro che tu faccia ciò che è sempre stato fatto.

Scrivere un codice e mostrare i risultati al mondo.

Rispetto ai vecchi tempi, ci sono alcuni strumenti per rendere il vostro lavoro più facile però. Potrei suggerire ANTLR per analizzare la grammatica della tua lingua?

0

I codificatori reali sono ancora codificati in C. Solo che è un po 'più nitido.
Hmmm ... linguaggio design? o scrivere un compilatore? Se vuoi scrivere un compilatore, devi usare Flex + Bison. (google)

+1

Se vuoi scrivere un buon compilatore, eseguirai manualmente il tuo ricorsivo -analizzatore parsimonioso, perché se un parser di Bison moderatamente complesso si incapperà presto in problemi (se non si riesce a far funzionare la lingua, si otterrà il compilatore/interprete per segnalare errori). –

+0

+1 per il modo in cui hai fatto riferimento a C# – RCIX

+0

@chris Sì, forse, ma solo per LISP (ASM, Scheme ...) Scrivere manualmente un compilatore completo è l'ultima cosa che vuoi fare ... solo per la complessità coinvolta. – aviraldg

2

Non dovresti accettare soluzioni wimpy come utilizzare gli strumenti più recenti. È necessario eseguire il bootstrap del linguaggio scrivendo un compilatore minimo in Visual Basic, Applications Edition o un linguaggio simile, quindi scrivere tutti gli strumenti di compilazione nella nuova lingua e quindi compilare automaticamente utilizzando solo la lingua stessa.

Inoltre, qual è il nome proposto della lingua?

Penso che di recente non ci siano state lingue con TUTTI i LETTERA MAIUSCOLA come COBOL e FORTRAN, quindi spero che lo chiamerai MIKELANG con tutte le lettere maiuscole.

+1

BASIC? Ho sentito che qualcuno stava facendo delle ricerche basandosi sul fatto che gli scimpanzé che battono su una tastiera fossero più ordinati rispetto al codice BASIC di livello di produzione. Indovina ... – aviraldg

+2

Fantastica idea. Ho scelto "Complicity" diversi anni fa, ma mi piace l'idea di un linguaggio ALLCAPS! MIKTRAN, MOBOL, MIKEBASIC, MALEVOLENT, MALT, MARKV, MINGLE, MING, UNILANG ... – Mike

0

Non è una risposta facile, ma ..

Si desidera in sostanza di definire un insieme di regole scritte nel testo (gettoni) e poi alcuni parser che controlla queste regole e li assembla in frammenti.

http://www.mactech.com/articles/mactech/Vol.16/16.07/UsingFlexandBison/

le persone possono trascorrere anni su questo, L'articolo parla sopra sull'utilizzo di due strumenti (Flex e Bison) che può essere utilizzato per convertire il testo in codice è possibile alimentare a un compilatore.

2

Parlando come qualcuno che ha appena creato un assembly semplice come lingua e interprete, inizierei con il framework .NET o simile. Nulla può battere la potente sintassi di C# + il supporto dell'intera comunità .NET quando si tenta di scrivere la maggior parte delle cose. Da qui ho progettato un semplice formato bytecode e sintassi di assembly e ho iniziato a scrivere il mio interprete + assemblatore.

Come ho già detto, era un molto linguaggio semplice.

+0

sintassi potente? C#? mi stai prendendo in giro. Ma il framework .net e la community sono comunque carini. –

7

Una considerazione che è nuova poiché l'era delle schede perforate è l'esistenza di macchine virtuali già generosamente fornite con "librerie standard". Targeting della JVM o del CLR .NET invece di "old walled garden" ti consente di risparmiare un sacco di bootstrap. Se stai creando un linguaggio compilato, potresti anche trovare codice byte Java o MSIL un obiettivo di compilazione più facile rispetto al codice macchina (ovviamente, se ci sei dentro per divertirti a creare un compilatore di ottimizzazione stretto, vedrai questo come un bug piuttosto che una funzionalità).

Sul lato negativo, gli idiomi di JVM o CLR potrebbero non essere ciò che si desidera per la propria lingua. Quindi potresti ancora finire con la costruzione di "librerie standard" solo per fornire interfacce idiomatiche sulla piattaforma. (Un esempio è che tutte le lingue e il relativo cane sembrano fornire il proprio metodo per scrivere sulla console, piuttosto che lasciare che gli utenti chiamino manualmente System.out.println o Console.WriteLine.) Tuttavia, consente uno sviluppo incrementale dell'idiomatico librerie e significa che le librerie più oscure per le quali non si arriva mai a costruire interfacce idiomatiche sono ancora accessibili anche se in modo brutto.

Se si sta considerando un linguaggio interpretato, .NET supporta anche l'interpretazione efficiente tramite il Dynamic Language Runtime (DLR). (Non so se c'è un equivalente per la JVM.) Questo dovrebbe aiutarti a concentrarti sulla progettazione della lingua senza dovermi preoccupare tanto dell'ottimizzazione dell'interprete.

+1

VM come JVM e .NET sono un vicolo cieco evolutivo. –

+1

Non è vero! dal momento che le librerie per le piattaforme JVM e .NET non devono preoccuparsi delle idiosincrasie delle carte in gioco, possono essere libere di esplorare aspetti di progettazione dell'API che altrimenti rimarrebbero inalterati. – RCIX

+1

VM come JVM e .NET sono un vicolo cieco evolutivo. –

0

Per prima cosa ho trascorso circa un anno a pensare realmente come dovrebbe essere la lingua. Allo stesso tempo ho aiutato a sviluppare Ioke (www.ioke.org) per imparare le lingue interne.

Ho scelto Objective-C come piattaforma di implementazione in quanto è un linguaggio veloce (sufficiente), semplice e ricco. Fornisce anche un framework di test in modo che l'approccio agile sia immediato. Ha anche una ricca libreria standard su cui posso costruire.

Poiché la mia lingua è semplice a livello sintattico (nessuna parola chiave, solo caratteri letterali, operatori e messaggi) potrei andare con Ragel (http://www.complang.org/ragel/) per lo scanner degli edifici. È veloce come l'inferno e semplice da usare.

Ora ho un modello di oggetti di lavoro, uno scanner e un semplice shuffling dell'operatore oltre al codice di bootstrap della libreria standard. Posso persino eseguire un semplice programma, purché si inseriscano in un file :)

6

Ho scritto due compilatori ora in Haskell per piccoli linguaggi specifici del dominio e l'ho trovato un'esperienza incredibilmente produttiva . La libreria parsec semplifica la riproduzione con la sintassi e gli interpreti sono molto semplici da scrivere su una struttura dati Haskell. C'è una descrizione di writing a Lisp interpreter in Haskell che ho trovato utile.

Se si è interessati a un backend ad alte prestazioni, si consiglia di LLVM. Ha un codice byte conciso ed elegante e il miglior backend di generazione x86/amd64 che puoi trovare. C'è un garbage collector opzionale e alcuni backend sperimentali che target the JVM and CLR.

È possibile scrivere un compilatore in qualsiasi linguaggio che generi il bytecode LLVM. Se sei abbastanza avventuroso da imparare Haskell ma vuoi LLVM, ci sono una serie di associazioni Haskell-LLVM.

2

Non tanto un'implementazione, ma una decisione progettuale che influisce sull'implementazione - se rendi ogni affermazione della tua lingua un albero di analisi unico senza contesto, otterrai qualcosa che è facile da codificare a mano un parser, e che non richiede grandi quantità di lavoro per fornire l'evidenziazione della sintassi per. Allo stesso modo, cose semplici come l'utilizzo di un simbolo diverso per gli spazi dei nomi dei moduli e degli oggetti (diversamente da Java che utilizza . per gli spazi dei nomi di pacchetti e classi) significa che è possibile analizzare il codice senza caricare tutti i moduli a cui fa riferimento.

Librerie standard: includere l'equivalente di tutto nelle librerie standard C99 diverse da setjmp. Aggiungi qualsiasi altra cosa che ti serve per il tuo dominio. Elabora un modo semplice per farlo, o qualcosa come SWIG o un FFI in linea come Ruby [non ricordo il nome del modulo] e i ctypes di Python.

Building come gran parte del linguaggio nella lingua è un'opzione, ma i progetti che iniziano a fare o rinunciare (rubinius spostati in C++ per una parte della libreria standard), o è solo per scopi di ricerca (Mozilla Narcissus)

1

Sono in realtà un bambino, haha. Non ho mai scritto un compilatore prima o progettato un linguaggio, ma ho finito The Red Dragon Book, quindi suppongo di avere un'idea (spero).

Dipenderebbe innanzitutto dalla grammatica. Se è LR o LALR suppongo che strumenti come Bison/Flex funzionino bene. Se è più LL, userei Spirit, che è un componente di Boost. Ti permette di scrivere la grammatica della lingua in C++ in una sintassi simile a EBNF, quindi non confondere con i generatori di codice; il compilatore C++ compila la grammatica per te. Se qualcuno di questi fallisce, scriverò una grammatica EBNF su carta e poi procederò a fare un parsing ricorsivo di discesa, che sembra funzionare; se C++ può essere analizzato abbastanza bene usando RDP (come fa GCC), allora suppongo che con un sufficiente numero di test e pazienza potreste scrivere interi compilatori usando RDP.

Una volta eseguito un parser e una sorta di rappresentazione intermedia, dipende da come viene eseguito. Se si tratta di un codice bytecode o di un compilatore di codice nativo, userò LLVM o libJIT per elaborarlo. LLVM è più adatto per la compilazione generale, ma mi piace l'API libJIT e la documentazione migliore. In alternativa, se sono veramente pigro, genererò il codice C e lascerò a GCC la compilazione vera e propria. Un'altra alternativa è quella di indirizzare una macchina virtuale esistente, come Parrot o JVM o CLR. Parrot è la VM progettata per Perl. Se è solo un interprete, camminerò sull'albero della sintassi.

Un'alternativa radicale consiste nell'utilizzare Prolog, che dispone di funzioni di sintassi che simulano notevolmente l'EBNF. Non ho esperienza con esso, però, e se non sbaglio (che quasi certamente sarò), Prolog sarebbe abbastanza lento se usato per analizzare i linguaggi di programmazione heavy duty con molti costrutti sintattici e stranezze (leggi: C++ e Perl).

Tutto ciò che farò in C++, se non altro perché sono più abituato a scrivere in esso rispetto a C. starei lontano da Java/Python o qualcosa del genere per il codice di produzione attuale (scrivendo compilatori in C/C++ aiuta a renderlo portabile), ma potevo vedere me stesso usandoli come linguaggio di prototipazione, in particolare Python, a cui sono parziale. Naturalmente, non ho mai fatto nulla di tutto ciò prima, quindi non sono uno da dire.

3

Cosa è cambiato considerevolmente, ma non è stato ancora citato è il supporto IDE e l'interoperabilità:

Al giorno d'oggi abbiamo praticamente aspettarci Intellisense, step-by-step di esecuzione e il controllo dello stato "diritto nella finestra dell'editor", nuova tipi che dicono al debugger come trattarli e messaggi diagnostici piuttosto utili. Il vecchio eseguibile "compile .x -> .y" non è più sufficiente per creare una lingua. L'ambiente non è nulla su cui concentrarsi prima, ma influenza la volontà di adottare.

Inoltre, le librerie sono diventate molto più potenti, nessuno vuole implementare tutto ciò in un'altra lingua. Cerca di prendere in prestito, semplifica la chiamata del codice esistente e facilita la chiamata ad altri codici.

Targeting di una VM - come suggerito da Itowlson - è probabilmente un buon modo per iniziare. Se si verifica un problema, può ancora essere sostituito da compilatori nativi.

+2

"il vecchio 'eseguibile .x -> .y' eseguibile è praticamente morto" - hahahaha! Dimmi un altro. Andiamo, è stato grandioso! –

+0

alex: come in "tutto ciò che serve per una nuova lingua è ...", immagino che dovrei chiarirlo. – peterchen

-1

Mike -

Se siete interessati a un compilatore di codice nativo di generazione efficiente per Windows in modo da poter ottenere il vostro cuscinetti - senza guadare attraverso tutti i widget inutili, gadget, e altre sciocchezze che ingombrano macchine di oggi - Raccomando il sistema di sviluppo inglese pianura dell'Ordine Osmosiano. Include un'interfaccia unica, un gestore di file semplificato, un editor di testo intuitivo, un comodo dumper esadecimale, il compilatore/linker (ovviamente) e un'applicazione di impaginazione wysiwyg per la documentazione. Scritto interamente in Plain English, è un download veloce (meno di un megabyte), abbastanza piccolo da comprendere in breve tempo (circa 25.000 righe di codice Plain English, con appena 4.000 nel compilatore/linker), ma abbastanza potente da riprodursi su un Dell bottom-of-the-line in meno di tre secondi. Davvero: tre secondi. Ed è gratuito per tutti coloro che scrivono e chiedono una copia, incluso il codice sorgente e un manuale di 100 pagine spiritoso e spiritoso. Vedere www.osmosian.com per i dettagli su come ottenere una copia, o scrivere a me direttamente con domande o commenti: [email protected]

0

Naturalmente le tecniche più vecchie sono ancora comuni (ad esempio utilizzando Flex e Bison) molte più recenti implementazioni linguistiche combinano la fase di lexing e parsing, utilizzando un parser basato su una grammatica di espressione di parsing (PEG). Questo funziona per i parser di discesa ricorsivi creati usando i combinatori o i parser di Packrat memoizing. Molti compilatori sono costruiti utilizzando anche il framework Antlr.

1

tanto per chiarire, voglio dire, non è come si fa a progettare un linguaggio (che mi può capire abbastanza facilmente)

Solo un suggerimento: un'occhiata a qualche bel diverse lingue, prima progettare una nuova lingua (cioè lingue con una strategia di valutazione molto diversa). Haskell e Oz vengono in mente. Anche se dovresti conoscere anche Prolog e Scheme. Un anno fa anche io ero tipo "hey, progettiamo un linguaggio che si comporti esattamente come voglio", ma fortunatamente ho guardato prima quelle altre lingue (o potresti anche dire sfortunatamente, perché ora non so come vuoi che una lingua si comporti più ...).

1

Prima di iniziare a creare un linguaggio si dovrebbe leggere questo:

Hanspeter Moessenboeck, L'arte di Niklaus Wirth

ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe00b.pdf

+0

Niklaus Wirth è stato terribile nel design del compilatore. Ha violato la legge di Einstein: rendere tutto il più semplice possibile, ma non più facile. Le sue lingue erano facili per essere produttivi. A proposito, mi piace Modula3 che non è stato progettato da lui. – Lothar

0

Usa bisonte/flex, che è la versione GNU di Yacc/Lex. Questo book is extremely helpful.

La ragione per utilizzare il bisonte è che rileva eventuali conflitti nella lingua. L'ho usato e mi ha reso la vita facile molti anni (ok quindi sono al mio secondo anno ma i primi 6 mesi sono stati alcuni anni fa scrivendolo in C++ e l'analisi/conflitti/risultati erano terribili! :(.)

0

C'è una grande scorciatoia per l'attuazione di un linguaggio che non vedo nelle altre risposte qui. Se usi una delle forme "non restaurate" di Lukasiewicz (ad esempio Polacco anteriore o Polacco inverso) non hai bisogno di un parser! Con lo smalto inverso, le dipendenze vanno da destra a sinistra in modo da eseguire semplicemente ogni token mentre viene scansionato. Con il forward forward, è il contrario, quindi esegui il programma "backwards", semplificando le sottoespressioni fino a raggiungere il token di partenza.

Per capire perché questo funziona, è necessario esaminare i 3 algoritmi di attraversamento degli alberi primari: pre-ordine, in ordine, post-ordine. Questi tre attraversamenti sono l'inverso del compito di analisi che un lettore di linguaggi (i parser) deve eseguire. Solo la notazione in ordine "richiede" un decente ricorsivo per ricostruire l'albero delle espressioni. Con gli altri due, puoi farcela con solo una pila.

Questo può richiedere più "pensare' e meno 'di esecuzione'.

A proposito, se hai già trovato una risposta (questa domanda è di un anno), è possibile inviare questo e accettarlo.

Problemi correlati