Come devo implementare un'applicazione per l'elaborazione dei comandi?


9

Voglio creare una semplice applicazione di prova di concetto (REPL) che prende un numero e quindi elabora i comandi su quel numero.

Esempio: inizio con 1. Quindi scrivo " add 2", mi dà 3. Quindi scrivo " multiply 7", mi dà 21. Quindi voglio sapere se è primo, quindi scrivo " is prime" (sul numero corrente - 21), mi dà falso. " is odd" mi darebbe vero. E così via.

Ora, per una semplice applicazione con pochi comandi, anche una semplice switchfarebbe per l'elaborazione dei comandi. Ma se desidero l'estensibilità, come dovrei implementare la funzionalità? Uso il modello di comando? Costruisco un semplice parser / interprete per la lingua? E se volessi comandi più complessi, come " multiply 5 until >200"? Quale sarebbe un modo semplice per estenderlo (aggiungere nuovi comandi) senza ricompilare?

Modifica: per chiarire alcune cose, il mio obiettivo finale non sarebbe quello di fare qualcosa di simile a WolframAlpha, ma piuttosto un processore di elenco (di numeri). Ma all'inizio voglio iniziare lentamente (su numeri singoli).

Sto pensando a qualcosa di simile al modo in cui uno userebbe Haskell per elaborare gli elenchi, ma una versione molto semplice. Mi chiedo se sarebbe sufficiente qualcosa come il modello di comando (o equivalente) o se devo realizzare un nuovo mini-linguaggio e un parser per raggiungere i miei obiettivi?

Edit2: Grazie per tutte le risposte, tutte mi sono state molto utili, ma Emmad Kareem mi ha aiutato di più, quindi lo sceglierò come risposta. Grazie ancora!


2
Non ricevo i voti negativi. Indica la tua ragione in modo che possa formulare meglio la mia domanda la prossima volta.
Nini Michaels,

2
Mi piace davvero questa domanda. Non vedo l'ora di vedere cosa suggeriscono le persone. Stai specificatamente cercando un design orientato agli oggetti (menzioni il pattern di comando, che è un pattern OO)?
Bjarke Freund-Hansen,

grazie :) sì, preferirei OOP, ma non mi dispiacerebbe se vengono suggeriti altri metodi!
Nini Michaels,

2
Sembra un'implementazione di Reverse Polish Notation , un argomento di programmazione molto interessante!
Alberto De Caro,

2
Probabilmente stai commettendo un fallo sulla clausola del libro da Che tipo di domande non dovrei porre qui? nelle FAQ, ovvero se riesci a immaginare un intero libro che risponda alla tua domanda, stai chiedendo troppo .
Mark Booth,

Risposte:


5

Sembra un interprete. Sembra che tu sia preoccupato per l'implementazione più che per la funzionalità dettagliata (sto solo indovinando qui). Questo progetto se esteso non è un compito banale. Assicurati di studiare chiaramente l'ambito in quanto ciò richiede un approccio ingegneristico e non un approccio di sviluppo ad hoc per ottenere un prodotto affidabile anziché un prodotto con 1000 patch che a volte funziona solo.

Decidi una sintassi e sii pronto ad analizzarla ed esegui i controlli di sintassi necessari. Questo link può aiutarti in questo: Crea il tuo parser .

Dai un'occhiata a questo argomento in quanto tocca diversi aspetti del lavoro, inoltre ci sono buoni collegamenti che possono aiutarti (specialmente la risposta di RMK) .: Creazione di un interprete di lingua . Potresti voler vedere un esempio di un bel progetto che è in qualche modo simile a: Ultimate Programmable Scientific Calculator . Puoi trovare il codice sorgente e il programma di lavoro per un interprete C # della riga di comando qui Command-Line-Implementation-of-C # -Made-for-Teaching . L'utilizzo del compilatore per eseguire le attività complesse per te come l'analisi e la digitazione variabile, ecc. Può essere un modo intelligente per sfuggire alle complessità della scrittura di tutto questo da solo. Inoltre, c'è l'opzione Mono che fornisce una funzionalità di shell charp che potresti voler dare un'occhiata a: CsharpRepl .


Grazie, i tuoi link sono davvero utili! Quindi immagino che un interprete sarebbe la scelta migliore se volessi estenderlo facilmente.
Nini Michaels,

Grazie per il feedback, immagino che iniziare con il link a CodeProject possa essere una buona idea.
NoChance,

2

A meno che tu non sia specificamente interessato a scrivere il parser vero e proprio, suggerirei di dare un'occhiata a uno dei framework del generatore di parser. Per C hai YACC o Bison , ma se preferisci ci dovrebbero essere altre alternative per altre lingue.

Ciò elimina la complessità dell'analisi di grammatiche complesse e ti consente di concentrarti sul compito che desideri svolgere. Ovviamente questo può essere eccessivo per la grammatica che suggerisci nella domanda, ma dato che accenni di avere la possibilità di espandersi in una grammatica più complessa in seguito, vale la pena prendere almeno qualche ispirazione da questi framework.


1
Il problema con la maggior parte dei generatori di parser è che i loro artefatti sono statici e non si prestano facilmente all'estensione. Penso che l'OP sarebbe meglio servito con qualcosa di più simile a un motore di regole, in cui le "regole" (parole chiave e sintassi) sono archiviate in una struttura di dati flessibile e valutate dopo ogni input.
TMN,

2

Quello che stai descrivendo è molto vicino a un linguaggio di stack .

Ad esempio in Factor ciò che descriveresti sarebbe fatto

1
2 +
7 *
even? not

Oppure potresti definire le tue parole e usarle, come

: add ( x y -- sum ) + ;
: multiply ( x y -- product ) * ;
: odd? ( n -- ? ) even? not ;

Con queste definizioni l'esempio sopra diventa

1
2 add
7 multiply
odd?

Di solito le lingue dello stack sono banali da analizzare perché usano parole singole separate da spazi. Ti suggerisco di dare un'occhiata a Factor - potrebbe essere esattamente quello che vuoi. Dovrebbe essere facile definire le parole che eseguono l'elaborazione di cui hai bisogno.

EDIT : Se vuoi davvero progettare un linguaggio simile, ti suggerisco di giocare comunque con uno di loro. Analizzare un linguaggio di stack è banale: ti dividi su spazi vuoti e un'implementazione ingenua dell'elaborazione è semplice: devi solo occuparti di ciò che accade in uno stack.


Sembra abbastanza facile e un buon punto di partenza. Grazie!
Nini Michaels,

1

Ma se desidero l'estensibilità, come dovrei implementare la funzionalità?

Non dovresti. L'estensibilità crea molta complessità per un guadagno molto ridotto. Detto questo, dovrai fornire un gancio nello stato esistente. Un modo per vedere lo stato, modificare lo stato e fornire un meccanismo per restituire altri risultati (stampa su schermo). Avrai bisogno di un modo per il codice principale di scoprire i moduli, caricarli e inviare loro i comandi.

Uso il modello di comando?

Puoi, ma probabilmente non è appropriato.

Non prenderete l'intero input e lo invierete per l'elaborazione, ma analizzerete l'input, inviate al gestore corretto e lasciatelo fare. Il comando non varia in quella comunicazione; quindi nessun modello di comando.

Costruisco un semplice parser / interprete per la lingua?

Avrai bisogno di qualcosa per gestire la suddivisione dell'input in token. Per una soluzione estensibile, probabilmente non farai molto di più. Per una soluzione ben definita, avere un albero di analisi completo fornirà migliori prestazioni, gestione degli errori e capacità di debug.

ma piuttosto un elenco (di numeri) processore

Quindi forse dovresti esaminare il linguaggio LISt Processing . La giustapposizione di codice e dati dovrebbe adattarsi perfettamente a ciò che descrivi.


Grazie per i suggerimenti Per quanto riguarda LISP, ne ho familiarità e ancora più familiare con Haskell, che mi ha ispirato con questa idea. Tuttavia, anche se potrei reinventare un po 'la ruota, voglio sporcarmi le mani con l'elaborazione dei comandi e l'interpretazione. Quindi ha anche uno scopo educativo oltre all'attuale "elaborazione delle liste" :)
Nini Michaels,

@NiniMichaels certamente, ma per quanto riguarda un progetto di estensibilità, usare l'organizzazione / concatenamento di codice / dati di lisp non è una cattiva opzione.
Telastyn,
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.