Como devo implementar um aplicativo de processamento de comandos?


9

Desejo criar um aplicativo simples de prova de conceito (REPL) que use um número e depois processe comandos nesse número.

Exemplo: eu começo com 1. Então eu escrevo " add 2", ele me fornece 3. Então eu escrevo " multiply 7", ele me fornece 21. Então eu quero saber se é primo, então eu escrevo " is prime" (no número atual - 21), isso me dá falso. " is odd" me daria verdade. E assim por diante.

Agora, para um aplicativo simples com poucos comandos, até um simples switchseria o processamento dos comandos. Mas se eu quiser extensibilidade, como precisaria implementar a funcionalidade? Eu uso o padrão de comando? Construo um analisador / intérprete simples para o idioma? E se eu quiser comandos mais complexos, como " multiply 5 until >200"? Qual seria uma maneira fácil de estendê-lo (adicionar novos comandos) sem recompilar?

Edit: para esclarecer algumas coisas, meu objetivo final não seria fazer algo semelhante ao WolframAlpha, mas sim um processador de lista (de números). Mas quero começar devagar no início (em números únicos).

Estou pensando em algo semelhante ao modo como alguém usaria o Haskell para processar listas, mas uma versão muito simples. Eu estou querendo saber se algo como o padrão de comando (ou equivalente) seria suficiente, ou se eu tenho que criar uma nova minilinguagem e um analisador para que ele atinja meus objetivos?

Edit2: Obrigado por todas as respostas, todas têm sido muito úteis para mim, mas o Emmad Kareem me ajudou mais, por isso vou escolher como resposta. Obrigado novamente!


2
Eu não recebo os votos negativos. Por favor, indique seu motivo para que possamos formular melhor minha pergunta da próxima vez.
Nini Michaels

2
Eu realmente gosto desta pergunta. Ansioso para ver o que as pessoas sugerem. Você está procurando especificamente design orientado a objeto (menciona padrão de comando, que é um padrão OO)?
Bjarke Freund-Hansen

obrigado :) Sim, eu preferiria OOP, mas não me importo se outros métodos forem sugeridos!
Nini Michaels

2
Parece uma implementação de Reverse Polish Notation , um assunto de programação muito legal!
Alberto De Caro

2
Você provavelmente está desrespeitando a cláusula do livro de Que tipo de perguntas não devo fazer aqui? no FAQ, ou seja, se você consegue imaginar um livro inteiro que responda à sua pergunta, está pedindo demais .
Mark Booth

Respostas:


5

Isso soa como um intérprete. Parece que você está mais preocupado com a implementação do que com a funcionalidade detalhada (só estou supondo aqui). Este projeto, se estendido, não é uma tarefa trivial. Certifique-se de estudar o escopo claramente, pois isso requer uma abordagem de engenharia e não uma abordagem de desenvolvimento ad-hoc para obter um produto confiável, em vez de um produto com 1000 correções que às vezes funciona apenas.

Decida uma sintaxe e esteja pronto para analisá-la e executar as verificações de sintaxe necessárias. Este link pode ajudá-lo com isso: Crie seu próprio analisador .

Dê uma olhada: neste tópico, pois aborda diferentes aspectos do trabalho, também existem bons links que podem ajudá-lo (especialmente a resposta do RMK): Criando um intérprete de idiomas . Você pode querer ver um exemplo de um projeto interessante que é um pouco semelhante em: Calculadora científica programável final . Você pode encontrar o código-fonte e o programa de trabalho para um interpretador de C # da linha de comando aqui Implementação da linha de comando do C # -Made-for-Teaching . Usar o compilador para executar tarefas complexas para você, como análise e digitação de variáveis, etc., pode ser uma maneira inteligente de escapar das complexidades de escrever tudo isso sozinho. Além disso, existe a opção Mono, que fornece um recurso de shell charp que você pode dar uma olhada em: CsharpRepl .


Obrigado, seus links são realmente úteis! Então, acho que um intérprete seria a melhor opção se eu quiser estendê-lo facilmente.
Nini Michaels

Obrigado pelo feedback, acho que começar pelo link do CodeProject pode ser uma boa ideia.
NoChance

2

A menos que você esteja especificamente interessado em escrever o analisador real para si mesmo, sugiro dar uma olhada em uma das estruturas de gerador de analisador. Para C você tem YACC ou Bison , mas deve haver outras alternativas para outros idiomas, se preferir.

Isso elimina as complexidades de analisar gramáticas complexas e permite que você se concentre na tarefa que deseja executar. É claro que isso pode ser um exagero para a gramática sugerida na pergunta, mas como você menciona ter a opção de expandir para uma gramática mais complexa posteriormente, vale a pena obter alguma inspiração dessas estruturas.


11
O problema com a maioria dos geradores de analisadores é que seus artefatos são estáticos e não se prestam facilmente à extensão. Eu acho que o OP seria melhor servido com algo mais como um mecanismo de regras, onde as "regras" (palavras-chave e sintaxe) são armazenadas em uma estrutura de dados flexível e avaliadas após cada entrada.
TMN

2

O que você está descrevendo está muito próximo de uma linguagem de pilha .

Por exemplo, no Fator, o que você descreve seria feito como

1
2 +
7 *
even? not

Ou você pode definir suas próprias palavras e depois usá-las, como

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

Com essas definições, o exemplo acima se torna

1
2 add
7 multiply
odd?

Normalmente, os idiomas de pilha são fáceis de analisar porque usam palavras únicas separadas por espaço. Eu sugiro que você dê uma olhada no Factor - pode ser exatamente o que você deseja. Deve ser fácil definir as palavras que fazem o processamento necessário.

Edição : Se você realmente deseja criar uma linguagem semelhante, sugiro que você jogue com uma delas de qualquer maneira. A análise de uma linguagem de pilha é trivial - você divide em espaços em branco, e uma implementação ingênua de processamento é fácil: você só precisa cuidar do que acontece em uma pilha.


Parece muito fácil e um bom lugar para começar. Obrigado!
Nini Michaels

1

Mas se eu quiser extensibilidade, como precisaria implementar a funcionalidade?

Você não deveria. A extensibilidade cria muita complexidade para pouquíssimos ganhos. Dito isto, você precisará fornecer um gancho para o estado existente. Uma maneira de ver o estado, modificar o estado e fornecer um mecanismo para retornar outros resultados (imprimir na tela). Você precisará de uma maneira do código principal descobrir módulos, carregá-los e enviar comandos para eles.

Eu uso o padrão de comando?

Você pode, mas provavelmente não é apropriado.

Você não vai pegar a entrada inteira e enviá-la para processamento, mas, em vez disso, analisa a entrada, despacha para o manipulador correto e deixa que ela faça seu trabalho. O comando não varia nessa comunicação; então nenhum padrão de comando.

Construo um analisador / intérprete simples para o idioma?

Você precisará de algo para lidar com a quebra da entrada em tokens. Para uma solução extensível, você provavelmente não fará muito mais. Para uma solução bem definida, ter uma árvore de análise completa fornecerá melhor desempenho, manipulação de erros e capacidade de depuração.

mas sim um processador de lista (de números)

Talvez você deva procurar a linguagem LISt Processing . A justaposição de código e dados deve se encaixar bem no que você descreve.


Obrigado pelas sugestões. Quanto ao LISP, estou familiarizado com ele e ainda mais com Haskell, que me inspirou com essa ideia. No entanto, mesmo que eu esteja reinventando um pouco o volante, quero sujar minhas mãos com os comandos de processamento e interpretação. Então, ele também tem um propósito educacional, além do "processamento de lista" real :)
Nini Michaels

@NiniMichaels certamente, mas no que diz respeito ao design de extensibilidade, usar a organização / encadeamento de código / dados do lisp não é uma opção ruim.
Telastyn
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.