¿Cómo debo implementar una aplicación de procesamiento de comandos?

9

Quiero hacer una aplicación simple de prueba de concepto (REPL) que tome un número y luego procese comandos en ese número.

Ejemplo: empiezo con 1. Luego escribo " add 2", me da 3. Luego escribo " multiply 7", me da 21. Entonces quiero saber si es primo, entonces escribo " is prime" (en el número actual - 21), me da falso. " is odd" me daría la verdad. Y así.

Ahora, para una aplicación simple con pocos comandos, incluso un simple switchserviría para procesar los comandos. Pero si quiero extensibilidad, ¿cómo necesitaría implementar la funcionalidad? ¿Utilizo el patrón de comando? ¿Construyo un analizador / intérprete simple para el idioma? ¿Qué sucede si quiero comandos más complejos, como " multiply 5 until >200"? ¿Cuál sería una manera fácil de extenderlo (agregar nuevos comandos) sin volver a compilar?

Editar: para aclarar algunas cosas, mi objetivo final no sería hacer algo similar a WolframAlpha, sino más bien un procesador de listas (de números). Pero quiero comenzar lentamente al principio (en números individuales).

Tengo en mente algo similar a la forma en que uno usaría Haskell para procesar listas, pero una versión muy simple. Me pregunto si algo como el patrón de comando (o equivalente) sería suficiente, o si tengo que hacer un nuevo mini-idioma y un analizador para lograr mis objetivos.

Edit2: Gracias por todas las respuestas, todas me han sido de gran ayuda, pero Emmad Kareem me ha ayudado más, así que la elegiré como respuesta. ¡Gracias de nuevo!

Nini Michaels
fuente
2
No entiendo los votos negativos. Indique su razón para que pueda formular mejor mi pregunta la próxima vez.
Nini Michaels
2
Realmente me gusta esta pregunta. Esperamos ver qué diseños sugieren las personas. ¿Está buscando específicamente un diseño orientado a objetos (menciona el patrón de comando, que es un patrón OO)?
Bjarke Freund-Hansen
gracias :) sí, preferiría OOP, ¡pero no me importará si se sugieren otros métodos!
Nini Michaels
2
Parece una implementación de la notación polaca inversa , ¡un tema de programación genial!
Alberto De Caro
2
Probablemente te estés quedando sin la cláusula del libro de ¿Qué tipo de preguntas no debo hacer aquí? en las preguntas frecuentes, es decir, si puede imaginar un libro completo que responda a su pregunta, está preguntando demasiado .
Mark Booth el

Respuestas:

5

Esto suena como un intérprete. Parece que le preocupa más la implementación que la funcionalidad detallada (solo supongo que aquí). Este proyecto si se extiende no es una tarea trivial. Asegúrese de estudiar el alcance claramente, ya que esto requiere un enfoque de ingeniería y no un enfoque de desarrollo ad-hoc para obtener un producto confiable en lugar de un producto con 1000 parches que a veces solo funciona.

Decida una sintaxis y esté listo para analizarla y realizar las comprobaciones de sintaxis necesarias. Este enlace puede ayudarlo con esto: cree su propio analizador .

Eche un vistazo a este tema, ya que toca diferentes aspectos del trabajo, también hay buenos enlaces que pueden ayudarlo (especialmente la respuesta de RMK): Creación de un intérprete de idiomas . Es posible que desee ver un ejemplo de un proyecto atractivo que sea algo similar en: Ultimate Programmable Scientific Calculator . Puede encontrar el código fuente y el programa de trabajo para un intérprete de línea de comandos C # aquí Command-Line-Implementation-of-C # -Made-for-Teaching . Usar el compilador para hacer las tareas complejas para usted, como el análisis y la escritura de variables, etc., puede ser una forma inteligente de escapar de las complejidades de escribir todo esto usted mismo. Además, existe la opción Mono que proporciona una función de shell charp que quizás desee ver: CsharpRepl .

Ninguna posibilidad
fuente
¡Gracias, tus enlaces son realmente útiles! Así que supongo que un intérprete sería la mejor opción si quiero ampliarlo fácilmente.
Nini Michaels
Gracias por los comentarios, supongo que comenzar con el enlace al CodeProject puede ser una buena idea.
NoChance
2

A menos que esté específicamente interesado en escribir el analizador real para usted, le sugiero que eche un vistazo a uno de los marcos del generador de analizadores. Para C tienes YACC o Bison , pero debería haber otras alternativas para otros idiomas si lo prefieres.

Esto elimina la complejidad de analizar gramáticas complejas y le permite concentrarse en la tarea que desea hacer. Por supuesto, esto puede ser excesivo para la gramática que sugiere en la pregunta, pero dado que menciona tener la opción de expandirse a una gramática más compleja más tarde, al menos vale la pena obtener algo de inspiración de estos marcos.

harald
fuente
1
El problema con la mayoría de los generadores de analizadores sintácticos es que sus artefactos son estáticos y no se prestan fácilmente a la extensión. Creo que OP estaría mejor servido con algo más como un motor de reglas, donde las "reglas" (palabras clave y sintaxis) se almacenan en una estructura de datos flexible y se evalúan después de cada entrada.
TMN
2

Lo que está describiendo está muy cerca de un lenguaje de pila .

Por ejemplo, en Factor, lo que describe se haría como

1
2 +
7 *
even? not

O podría definir sus propias palabras y luego usarlas, como

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

Con estas definiciones, el ejemplo anterior se convierte en

1
2 add
7 multiply
odd?

Por lo general, los idiomas de pila son triviales para analizar porque usan palabras individuales separadas por espacios. Le sugiero que eche un vistazo a Factor: puede ser exactamente lo que desea. Debería ser fácil definir las palabras que realizan el procesamiento que necesita.

EDITAR : Si realmente quieres diseñar un lenguaje similar, te sugiero que juegues con uno de ellos de todos modos. Analizar un lenguaje de pila es trivial: se divide en espacios en blanco, y una implementación ingenua del procesamiento es fácil: solo tiene que ocuparse de lo que sucede en una pila.

Andrea
fuente
Esto suena bastante fácil y es un buen lugar para comenzar. ¡Gracias!
Nini Michaels
1

Pero si quiero extensibilidad, ¿cómo necesitaría implementar la funcionalidad?

No deberías La extensibilidad crea mucha complejidad para muy poca ganancia. Dicho esto, deberá proporcionar un enlace al estado existente. Una forma de ver el estado, modificar el estado y proporcionar un mecanismo para devolver otros resultados (imprimir en pantalla). Necesitará una forma para que el código central descubra los módulos, los cargue y les envíe comandos.

¿Utilizo el patrón de comando?

Puedes, pero es probable que no sea apropiado.

No va a tomar toda la entrada y enviarla para su procesamiento, sino que analiza la entrada, la envía al controlador correcto y deja que haga su trabajo. El comando no varía en esa comunicación; entonces no hay patrón de comando.

¿Construyo un analizador / intérprete simple para el idioma?

Necesitará algo para manejar dividir la entrada en tokens. Para una solución extensible, probablemente no harás mucho más. Para una solución bien definida, tener un árbol de análisis completo proporcionará un mejor rendimiento, manejo de errores y capacidad de depuración.

sino más bien un procesador de lista (de números)

Entonces quizás deberías buscar en el lenguaje de procesamiento de LISt . La yuxtaposición de código y datos debe encajar bien con lo que usted describe.

Telastyn
fuente
Gracias por las sugerencias. En cuanto a LISP, estoy familiarizado con él, y aún más familiarizado con Haskell, lo que me inspiró con esta idea. Sin embargo, aunque pueda estar reinventando un poco la rueda, quiero ensuciarme las manos con los comandos de procesamiento y su interpretación. Por lo tanto, también tiene un propósito educativo además del "procesamiento de listas" real :)
Nini Michaels
@NiniMichaels ciertamente, pero en lo que respecta al diseño de extensibilidad, usar la organización / encadenamiento de código / datos de lisp no es una mala opción.
Telastyn