No momento, estou implementando um avaliador de expressão (expressões de linha única, como fórmulas) com base no seguinte:
- a expressão inserida é tokenizada para separar booleanos literais, números inteiros, decimais, seqüências de caracteres, funções, identificadores (variáveis)
- Eu implementei o algoritmo Shunting-yard (modificado levemente para lidar com funções com número variável de argumentos) para se livrar dos parênteses e ordenar aos operadores uma precedência decente em uma ordem pós-fixada
- meu pátio de derivação simplesmente produz uma fila (simulada) de tokens (por meio de uma matriz, minha linguagem do Powerbuilder Classic pode definir objetos, mas só possui matrizes dinâmicas como armazenamento nativo - lista não verdadeira, sem dicionário) que avalio sequencialmente com um máquina de pilha simples
Meu avaliador está funcionando bem, mas ainda estou com uma falta if()
e estou pensando em como proceder.
Com minha avaliação pós-fixada e baseada em pilha do shunting yard, se eu adicionar if()
como outra função partes verdadeiras e falsas, uma única if(true, msgbox("ok"), msgbox("not ok"))
exibirá as duas mensagens enquanto eu gostaria de mostrar apenas uma. Isso ocorre porque quando preciso avaliar uma função, todos os seus argumentos já foram avaliados e colocados na pilha.
Você poderia me dar uma maneira de implementar de if()
forma preguiçosa?
Pensei em processá-las como uma espécie de macro, mas, no início, ainda não tenho a avaliação da condição. Talvez eu precise usar outro tipo de estrutura que não seja uma fila para manter separadamente a condição e as expressões true / false? Por enquanto, a expressão é analisada antes da avaliação, mas também planejo armazenar a representação intermediária como um tipo de expressão pré-compilada para avaliação futura.
Edit : depois de algum pensamento sobre o problema, acho que poderia criar uma representação em árvore da minha expressão (um AST em vez de um fluxo de token linear), a partir do qual eu poderia facilmente ignorar um ou outro ramo do meu if()
.
Em vez de a função ter a assinatura:
Dê a assinatura:
Em seguida, sua
if
função chamará a função apropriada com base na condição, avaliando apenas uma delas.fonte
É bem fácil, se você compilar tudo preguiçosamente. Você deve ter alguns meios para ver se um valor já está avaliado ou se precisa de mais avaliação.
Em seguida, você pode fazer o seguinte: Se for um literal ou variável (você possui esses ?, ou seja, nomes de funções?), Empurre-o na pilha. Se for uma aplicação de uma função, compile-a separadamente e empurre o ponto de entrada na pilha.
A execução de um programa é, então, meramente repetida até que o topo da pilha seja avaliado e não uma função. Se não for avaliado ou uma função, chame o código para o qual a parte superior da pilha aponta.
fonte