VB Tip: Math Parser Básico
Autor: Diego Silva | Publicado: 2011-07-24T17:28:00-03:00

Olá.
Essa semana estou criando um editor de imagem profissional, que contará com um sistema de console de comando, tipo como no AutoCad, como no Blender ou como, simplesmente, o Prompt de Comando (para quem não conhece, aqui está alguns exemplos: Console do Blender e Prompt de comando). Também pode se assemelhar ao sistema do Immediate Pane do VB6.
Enfim, e em todos esses sistemas de console, há funções de evaluate, que nada mais é que um sistema que resolve fórmulas em strings para números reais. Andei pesquisando na internet e encontrei alguns exemplos que usam o Eval() do Microsoft Scripting Runtime; Entretanto, para implementar esse sistema em seu aplicativo é necessário redistribuir esse pacote (msscrrun.dll, se não me engano) e isso pode causar problemas de copyright, pois é um complemento da Microsoft. 

Pesquisando mais a fundo e com keywords mais apropriadas, encontrei o termo "Math Parser" (em tradução livre, "Interpretador de Matemática") e alguns exemplos prontos. Aí resolvi criar um Math Parser próprio, com um sistema um pouco diferente dos que vi na internet. 

O código
Abaixo, o código que criei, para quem passar pela mesma situação.

Function Eval(ByVal strFormula As String) As Double
On Error GoTo fim
Dim formula As String
Dim resultado As String
Dim nmbr As String

Dim ops() As String: Dim opC As Long: Dim opB As Boolean
Dim nmbs() As String: Dim nmbC As Long

formula = strFormula

    For i = 1 To Len(formula)
    c = Mid(formula, i, 1)
        Select Case c
        Case "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ".", ","
        nmbr = nmbr & c
        Case "+", "-", "*", "/", "^", "%"
        ReDim Preserve nmbs(nmbC)
        nmbs(nmbC) = nmbr
        nmbC = nmbC + 1
        
        ReDim Preserve ops(opC)
        ops(opC) = c
        opC = opC + 1
        nmbr = ""
        Case Else
        'erro na fórmula
        GoTo fim
        End Select
    Next i
        If nmbr <> "" Then
ReDim Preserve nmbs(nmbC)
nmbs(nmbC) = nmbr
nmbC = nmbC + 1
nmbr = ""
Else
GoTo fim
End If

For j = 0 To opC - 1
atu = ops(j)
op1 = nmbs(j)
op2 = nmbs(j + 1)
    Select Case atu
    Case "+"
    nmbs(j + 1) = CStr(CDbl(op1) + CDbl(op2))
    Case "-"
    nmbs(j + 1) = CStr(CDbl(op1) - CDbl(op2))
    Case "*"
    nmbs(j + 1) = CStr(CDbl(op1) * CDbl(op2))
    Case "/"
    nmbs(j + 1) = CStr(CDbl(op1) / CDbl(op2))
    End Select
    
Next j
resultado = nmbs(j)
Eval = resultado
Exit Function
fim:
Eval = 0

End Function

Se alguém quiser implementar mais o código, colocar suporte a fórmulas e parênteses, seria ótimo para divulgar o conhecimento. 

E como prometido, irei divulgar posteriormente um código pronto de subclassing. Não houve possibilidade de criar um subclassing essa semana porque, como citado no início deste artigo, estou trabalhando em um editor de imagem profissional com um sistema de console. Mas a qualquer momento divulgarei.

Nota: Esse editor de imagem fará parte do projeto MultiSystem; Houve um problema de compatibilidade na minha migração de XP para Seven quanto ao DirectX, e terei que retirar a referência do DirectX8;Infelizmente, por questões burocráticas, a Microsoft fez com que o DirectX atual, que vem integrado no Seven, não fosse compatível com o Visual Basic 6 e sim com o VB.NET. Não há como negar que a linguagem .NET tem mais recursos; Entretanto, ao divulgar um programa feito em VB.NET, por mais leve que o programa em si seja, o cliente tem de baixar outro programa, chamado .NET Framework, que pesa mais de 30MB! Ou seja, o peso final do aplicativo, juntamente com o pacote Framework, fica inviável divulgar. 
E ao migrar para o VB.NET, há questões de incompatibilidade com certos códigos que antigamente (não tão antigo..) eram usados no VB6, seja na conversão de tipos (a declaração e conversão de tipos no .NET é explícita, diferente do VB6, que permite que sejam realizadas operações matemáticas com strings contendo números, o que NÃO vem a ser um Math Parsing; ele não interpreta nativamente (e acredito que nem o .NET) strings contendo equações) ou no uso de certas DLLs ou certos complementos OCX. É por essas e outras que muitos programadores, inclusive eu, usamos o VB6 como linguagem padrão de Visual Basic.

Enfim, até o próximo artigo.