Je veux créer une application simple de preuve de concept (REPL) qui prend un nombre et traite ensuite les commandes sur ce nombre.
Exemple: je commence par 1. Ensuite j'écris " add 2
", ça me donne 3. Puis j'écris " multiply 7
", ça me donne 21. Ensuite je veux savoir si c'est premier, alors j'écris " is prime
" (sur le nombre courant - 21), cela me donne de faux. " is odd
" me donnerait raison. Etc.
Maintenant, pour une application simple avec peu de commandes, même une simple switch
suffirait pour le traitement des commandes. Mais si je veux une extensibilité, comment aurais-je besoin d'implémenter la fonctionnalité? Dois-je utiliser le modèle de commande? Dois-je créer un analyseur / interprète simple pour la langue? Et si je veux des commandes plus complexes, comme " multiply 5 until >200
"? Quel serait un moyen simple de l'étendre (ajouter de nouvelles commandes) sans recompiler?
Edit: pour clarifier certaines choses, mon objectif final ne serait pas de faire quelque chose de similaire à WolframAlpha, mais plutôt un processeur de liste (de nombres). Mais je veux commencer lentement au début (sur des numéros simples).
Je pense à quelque chose de similaire à la façon dont on utiliserait Haskell pour traiter les listes, mais une version très simple. Je me demande si quelque chose comme le modèle de commande (ou équivalent) suffirait, ou si je dois créer un nouveau mini-langage et un analyseur pour qu'il atteigne mes objectifs?
Edit2: Merci pour toutes les réponses, toutes m'ont été très utiles, mais celles d'Emmad Kareem m'ont le plus aidé, alors je vais le choisir comme réponse. Merci encore!
la source
Réponses:
Cela ressemble à un interprète. Il semble que vous vous inquiétiez plus de l'implémentation que des fonctionnalités détaillées (je ne fais que deviner ici). Ce projet, s'il est étendu, n'est pas une tâche triviale. Assurez-vous d'étudier clairement la portée car cela nécessite une approche d'ingénierie et non une approche de développement ad hoc pour obtenir un produit fiable plutôt qu'un produit avec 1000 correctifs qui ne fonctionne parfois que.
Décidez d'une syntaxe et soyez prêt à l'analyser et à effectuer les vérifications de syntaxe nécessaires. Ce lien peut vous aider avec ceci: Créez votre propre analyseur .
Jetez un œil à: ce sujet car il touche à différents aspects du travail, il existe également de bons liens qui peuvent vous aider (en particulier la réponse de RMK).: Création d'un interprète de langue . Vous voudrez peut-être voir un exemple d'un beau projet qui est quelque peu similaire à: Ultimate Programmable Scientific Calculator . Vous pouvez trouver le code source et le programme de travail d'un interpréteur C # en ligne de commande ici Command-Line-Implementation-of-C # -Made-for-Teaching . Utiliser le compilateur pour effectuer les tâches complexes pour vous comme l'analyse et le typage de variables, etc. peut être un moyen intelligent d'échapper à la complexité de l'écriture de tout cela vous-même. En outre, il existe l'option Mono qui fournit une fonctionnalité de shell charp que vous voudrez peut-être consulter: CsharpRepl .
la source
À moins que vous ne soyez spécifiquement intéressé par l'écriture de l'analyseur réel pour vous-même, je vous suggère de jeter un œil à l'un des cadres du générateur d'analyseur. Pour C, vous avez YACC ou Bison , mais il devrait y avoir d'autres alternatives pour d'autres langues si vous préférez.
Cela élimine la complexité de l'analyse syntaxique de grammaires complexes et vous permet de vous concentrer sur la tâche que vous souhaitez effectuer. Bien sûr, cela peut être exagéré pour la grammaire que vous suggérez dans la question, mais puisque vous mentionnez avoir la possibilité d'étendre à une grammaire plus complexe plus tard, cela vaut au moins la peine de s'inspirer de ces cadres.
la source
Ce que vous décrivez est très proche d'un langage de pile .
Par exemple, dans Factor, ce que vous décrivez se ferait comme
Ou vous pouvez définir vos propres mots, puis les utiliser, comme
Avec ces définitions, l'exemple ci-dessus devient
Habituellement, les langues de pile sont triviales à analyser car elles utilisent des mots uniques séparés par des espaces. Je vous suggère de jeter un œil à Factor - il peut être exactement ce que vous voulez. Il devrait être facile de définir les mots qui font le traitement dont vous avez besoin.
EDIT : Si vous voulez réellement concevoir un langage similaire, je vous suggère de jouer avec l'un d'eux de toute façon. L'analyse d'un langage de pile est triviale - vous vous divisez sur des espaces vides et une implémentation naïve du traitement est facile: il vous suffit de prendre soin de ce qui se passe sur une pile.
la source
Tu ne devrais pas. L'extensibilité crée beaucoup de complexité pour très peu de gain. Cela dit, vous devrez fournir un raccordement à l'état existant. Une façon de voir l'état, de modifier l'état et de fournir un mécanisme pour renvoyer d'autres résultats (imprimer à l'écran). Vous aurez besoin d'un moyen pour le code principal de découvrir les modules, de les charger et de leur envoyer des commandes.
Vous pouvez, mais ce n'est probablement pas approprié.
Vous n'allez pas prendre l'intégralité de l'entrée et l'envoyer pour traitement, mais analysez plutôt l'entrée, envoyez-la au gestionnaire approprié et laissez-la faire son travail. La commande ne varie pas dans cette communication; donc pas de modèle de commande.
Vous aurez besoin de quelque chose pour gérer la décomposition de l'entrée en jetons. Pour une solution extensible, vous n'en ferez probablement pas beaucoup plus. Pour une solution bien définie, disposer d'un arbre d'analyse complet offrira de meilleures performances, une meilleure gestion des erreurs et une capacité de débogage.
Ensuite, vous devriez peut-être vous pencher sur le langage de traitement LISt . La juxtaposition de code et de données devrait correspondre à ce que vous décrivez.
la source