Parser example afx cWindow

Started by Frank Brübach, January 27, 2025, 03:32:40 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Frank Brübach

hello.. I have made last days a simple parser example with freebasic and Winfbe Editor.
all work are in progress.

now I have used afx cWindow class for my parser example too with an inputbox.

' freebasic parser example by lionheart first edition 25-06-2024
' Parser example freebasic, 24+25-01-2025, by lionheart
' part four, running now all fine, many thanks to fxm for help
' complete code example with Input, 27-01-2025
' for example you are using for Input:
'
' a = 2 + 3 * 10 print a ' result 50
' b = 4 + 9 * 20 print b ' result: 260
' c = 6 + 5 * 6 / 4 print c ' 16.5
'
' afx style cWindow, 27-01-2025 with inputbox
'
#define UNICODE
#INCLUDE ONCE "Afx/CWindow.inc"
USING Afx

' Define the Enum and Type
Enum TokenType
    TK_INTEGER
    TK_PLUS
    TK_MINUS
    TK_MULTIPLY
    TK_DIVIDE
    TK_LPAREN
    TK_RPAREN
    TK_ASSIGN
    TK_IDENTIFIER
    TK_PRINT
    TK_EOF
    TK_UNKNOWN
End Enum

Type Token
    Type1 As TokenType
    Value As String
End Type

' IsNumeric() function
Function IsNumeric(ByVal value As String) As Integer
    Static numericChars As cwstr
    numericChars = "0123456789.-"
    If Len(value) = 0 Then Return False

    Dim dotCount As Integer = 0
    For i As Integer = 1 To Len(value)
        Dim c As cwstr = Mid(value, i, 1)
        If InStr(numericChars, c) = 0 Then
            Return False
        ElseIf c = "." Then
            dotCount += 1
            If dotCount > 1 Then
                Return False
            End If
        End If
    Next

    Return True
End Function

' GetTokenType() function
Function GetTokenType(ByVal value As String) As TokenType
    If IsNumeric(value) Then
        Return TK_INTEGER
    ElseIf value = "+" Then
        Return TK_PLUS
    ElseIf value = "-" Then
        Return TK_MINUS
    ElseIf value = "*" Then
        Return TK_MULTIPLY
    ElseIf value = "/" Then
        Return TK_DIVIDE
    ElseIf value = "(" Then
        Return TK_LPAREN
    ElseIf value = ")" Then
        Return TK_RPAREN
    ElseIf value = "=" Then
        Return TK_ASSIGN
    ElseIf value = "print" Then
        Return TK_PRINT
    ElseIf value = "" Then
        Return TK_EOF
    Else
        Return TK_IDENTIFIER
    End If
End Function

' Split() function
Function Split(ByVal inputs As cwstr, tokens2() As Token) As Integer
    Dim token1 As String = ""
    Dim tokenCount As Integer = 0
    Dim i As Integer

    For i = 1 To Len(inputs)
        Dim c As String = Mid(inputs, i, 1)
        If c = " " Then
            If token1 <> "" Then
                ReDim Preserve tokens2(0 To tokenCount)
                tokens2(tokenCount).Value = token1
                tokens2(tokenCount).Type1 = GetTokenType(token1)
                tokenCount += 1
                token1 = ""
            End If
        Else
            token1 += c
        End If
    Next
    If token1 <> "" Then
        ReDim Preserve tokens2(0 To tokenCount)
        tokens2(tokenCount).Value = token1
        tokens2(tokenCount).Type1 = GetTokenType(token1)
    End If

    Return tokenCount
End Function

' EvaluateExpression function
Function EvaluateExpression(ByVal inputs As String) As Double
    Dim tokens() As Token
    Dim tokenCount As Integer = Split(inputs, tokens())

    Dim total As Double = 0
    Dim currentNumber As Double = 0
    Dim operators As cwstr = "+"

    For i As Integer = 0 To UBound(tokens)
        Dim token As Token = tokens(i)

        If token.Type1 = TK_INTEGER Then
            currentNumber = Val(token.Value)
            If operators = "+" Then
                total += currentNumber
            ElseIf operators = "-" Then
                total -= currentNumber
            ElseIf operators = "*" Then
                total *= currentNumber
            ElseIf operators = "/" Then
                If currentNumber <> 0 Then
                    total /= currentNumber
                Else
                    Print "Error: Division by zero"
                    Exit For
                End If
            End If

            operators = "+"
        ElseIf token.Type1 = TK_PLUS Then
            operators = "+"
        ElseIf token.Type1 = TK_MINUS Then
            operators = "-"
        ElseIf token.Type1 = TK_MULTIPLY Then
            operators = "*"
        ElseIf token.Type1 = TK_DIVIDE Then
            operators = "/"
        End If
    Next

    Return total
End Function

' findExpressionEnd()
Function FindExpressionEnd(tokens() As Token, start As Integer) As Integer
    Dim i As Integer
    For i = start To UBound(tokens)
        If tokens(i).Type1 = TK_EOF Or tokens(i).Type1 = TK_PRINT Then
            Return i - 1
        End If
    Next
    Return UBound(tokens)
End Function

Function JoinTokens(tokens() As Token, start As Integer, ends As Integer) As cwstr
    Dim expr As cwstr = ""
    Dim i As Integer
    For i = start To ends
        expr += tokens(i).Value + " "
    Next
    Return Trim(expr)
End Function

' mapTable
Type Map
    keys(any) As cwstr 
    values(Any) As cwstr 
    count As Integer
End Type

' Initialize the map
Function MapInit(ByRef maps As Map) As integer
    maps.count = 0
    ReDim maps.keys(100)
    Redim maps.values(100) 
    Function=1
End Function

' Add a key-value pair to the map
Function MapPut(ByRef maps As Map, key As cwstr, value As cwstr) As Integer
    maps.keys(maps.count) = key
    maps.values(maps.count) = value
    maps.count = maps.count + 1
    Return 0 ' Indicate success
End Function

' Retrieve a value from the map based on a key
Function MapGet(maps As Map, key As cwstr) As cwstr Ptr ' string ptr
    Dim i As Integer
    For i = 0 To maps.count - 1
        If maps.keys(i) = key Then
            Return StrPtr(maps.values(i))
        End If
    Next
    Return 0 ' Indicate failure
End Function

Function CreateMap() As Map
    Dim map As Map
    MapInit map
    Return map
End Function

Function StoreValue(map As Map, key As cwstr, value As Double) As Integer
    Dim result As Integer = MapPut(map, key, Str(value))
    Return result
End Function

' parse function
Function Parse(tokens() As Token) As Integer
    Dim i As Integer
    Dim SymbolTable As Map
    MapInit SymbolTable
    For i = 0 To UBound(tokens)
        Dim token As Token = tokens(i)
        If token.Type1 = TK_IDENTIFIER Then
            If tokens(i + 1).Type1 = TK_ASSIGN Then
                ' Handle variable assignment
                Dim varName As cwstr = token.Value
                Dim exprStart As Integer = i + 2
                Dim exprEnd As Integer = FindExpressionEnd(tokens(), exprStart)
                Dim expr As cwstr = JoinTokens(tokens(), exprStart, exprEnd)
                Dim result As Double = EvaluateExpression(expr)
                ' Store the result in a symbol table
                StoreValue(SymbolTable, varName, result)
                i = exprEnd
            Else
                Print "Error: Expected assignment operator"
                Return -1
            End If
        ElseIf token.Type1 = TK_PRINT Then
            ' Handle print statement Line 239:
            Dim exprStart As Integer
            Dim exprEnd As Integer = FindExpressionEnd(tokens(), exprStart)
            Dim expr As cwstr = JoinTokens(tokens(), exprStart, exprEnd)
            Dim result As Double = EvaluateExpression(expr)
            Print "result "; result
            i = exprEnd + 2
        End If
    Next
    Return 0
End Function

Function GetValue(map As Map, key As cwstr) As Double
    Dim value As cwstr Ptr = MapGet(map, key)
    If value = 0 Then
        Return 0
    Else
        Return Val(*value)
    End If
End Function

' -------------------------- // correct result 50 :-) -------- //
' afxInputBox
'
Dim inputs As cwstr '= "a = 2 + 3 * 10 print a" ' result 50 ok
'Input "make inputs and return: "; inputs
inputs=afxInputbox(0,0,0,"make inputs And Return: ",inputs,"") ';inputs
' b = 4 + 9 * 20 print b ' result: 260 ok
' c = 6 + 5 * 6 / 4 print c ' result ok 16.5
messagebox(NULL,inputs,"result on console output",mb_ok)

' -------------------------- // correct result 50 :-) -------- //

Dim tokens() As Token
Dim tokenCount As Integer = Split(inputs, tokens())

Dim result As Integer = Parse(tokens())

If result = 0 Then
    Print "Execution completed successfully"
Else
    Print "Error: Execution failed"
End If

' Wait for a key press before closing the console
Print "Press any key to continue..."
Sleep
While Inkey <> "" : Wend
' ends
'
'Dim st As cwstr
'st = afxInputBox(0,0,0,"type in","prog inputbox","")
'messagebox(NULL,st,"prog",mb_ok)

Frank Brübach


Made a little Update because I fixed a little substraction minus calculation. Add an Error Message too and a little more

' freebasic parser example by lionheart first edition 25-06-2024
' Parser example freebasic, 24+25-01-2025, by lionheart
' part five, running now all fine, many thanks to fxm for help
' complete code example with Input, 27-01-2025, 28-01-2025
' for example you are using for Input:
'
' b = 4 + 9 * 20 - 10 print b ' result: 250
' c = 6 + 5 * 6 / 4 print c ' 16.5
'
' afx style cWindow, 27-01-2025 with inputbox
' fixed a minus calculation

#define UNICODE
#INCLUDE ONCE "Afx/CWindow.inc"
USING Afx

' Define the Enum and Type
Enum TokenType
    TK_INTEGER
    TK_PLUS
    TK_MINUS
    TK_MULTIPLY
    TK_DIVIDE
    TK_LPAREN
    TK_RPAREN
    TK_ASSIGN
    TK_IDENTIFIER
    TK_PRINT
    TK_EOF
    TK_UNKNOWN
End Enum

Type Token
    Type1 As TokenType
    Value As String
End Type

' IsNumeric() function
Function IsNumeric(ByVal value As String) As Integer
    Static numericChars As cwstr
    numericChars = "0123456789.-"
    If Len(value) = 0 Then Return False

    Dim dotCount As Integer = 0
    For i As Integer = 1 To Len(value)
        Dim c As cwstr = Mid(value, i, 1)
        If InStr(numericChars, c) = 0 Then
            Return False
        ElseIf c = "." Then
            dotCount += 1
            If dotCount > 1 Then
                Return False
            End If
        End If
    Next

    Return True
End Function

' GetTokenType() function
Function GetTokenType(ByVal value As String) As TokenType
    If IsNumeric(value) Then
        Return TK_INTEGER
    ElseIf value = "+" Then
        Return TK_PLUS
    ElseIf value = "-" Then
        Return TK_MINUS
    ElseIf value = "*" Then
        Return TK_MULTIPLY
    ElseIf value = "/" Then
        Return TK_DIVIDE
    ElseIf value = "(" Then
        Return TK_LPAREN
    ElseIf value = ")" Then
        Return TK_RPAREN
    ElseIf value = "=" Then
        Return TK_ASSIGN
    ElseIf value = "print" Then
        Return TK_PRINT
    ElseIf value = "" Then
        Return TK_EOF
    Else
        Return TK_IDENTIFIER
    End If
End Function

' Split() function
Function Split(ByVal inputs As cwstr, tokens2() As Token) As Integer
    Dim token1 As String = ""
    Dim tokenCount As Integer = 0
    Dim i As Integer

    For i = 1 To Len(inputs)
        Dim c As String = Mid(inputs, i, 1)
        If c = " " Then
            If token1 <> "" Then
                ReDim Preserve tokens2(0 To tokenCount)
                tokens2(tokenCount).Value = token1
                tokens2(tokenCount).Type1 = GetTokenType(token1)
                tokenCount += 1
                token1 = ""
            End If
        Else
            token1 += c
        End If
    Next
    If token1 <> "" Then
        ReDim Preserve tokens2(0 To tokenCount)
        tokens2(tokenCount).Value = token1
        tokens2(tokenCount).Type1 = GetTokenType(token1)
    End If

    Return tokenCount
End Function

' EvaluateExpression function
Function EvaluateExpression(ByVal inputs As String) As Double
    Dim tokens() As Token
    Dim tokenCount As Integer = Split(inputs, tokens())

    Dim total As Double = 0
    Dim currentNumber As Double = 0
    Dim operators As cwstr = "+"

    For i As Integer = 0 To UBound(tokens)
        Dim token As Token = tokens(i)

        If token.Type1 = TK_INTEGER Then
            currentNumber = Val(token.Value)
            If operators = "+" Then
                total += currentNumber
            ElseIf operators = "-" Then
                total -= currentNumber
            ElseIf operators = "*" Then
                total *= currentNumber
            ElseIf operators = "/" Then
                If currentNumber <> 0 Then
                    total /= currentNumber
                Else
                    Print "Error: Division by zero"
                    Exit For
                End If
            End If

            operators = "-"
        ElseIf token.Type1 = TK_PLUS Then
            operators = "+"
        ElseIf token.Type1 = TK_MINUS Then
            operators = "-"
        ElseIf token.Type1 = TK_MULTIPLY Then
            operators = "*"
        ElseIf token.Type1 = TK_DIVIDE Then
            operators = "/"
        End If
    Next

    Return total
End Function

' findExpressionEnd()
Function FindExpressionEnd(tokens() As Token, start As Integer) As Integer
    Dim i As Integer
    For i = start To UBound(tokens)
        If tokens(i).Type1 = TK_EOF Or tokens(i).Type1 = TK_PRINT Then
            Return i - 1
        End If
    Next
    Return UBound(tokens)
End Function

Function JoinTokens(tokens() As Token, start As Integer, ends As Integer) As cwstr
    Dim expr As cwstr = ""
    Dim i As Integer
    For i = start To ends
        expr += tokens(i).Value + " "
    Next
    Return Trim(expr)
End Function

' mapTable
Type Map
    keys(any) As cwstr 
    values(Any) As cwstr 
    count As Integer
End Type

' Initialize the map
Function MapInit(ByRef maps As Map) As integer
    maps.count = 0
    ReDim maps.keys(100)
    Redim maps.values(100) 
    Function=1
End Function

' Add a key-value pair to the map
Function MapPut(ByRef maps As Map, key As cwstr, value As cwstr) As Integer
    maps.keys(maps.count) = key
    maps.values(maps.count) = value
    maps.count = maps.count + 1
    Return 0 ' Indicate success
End Function

' Retrieve a value from the map based on a key
Function MapGet(maps As Map, key As cwstr) As cwstr Ptr ' string ptr
    Dim i As Integer
    For i = 0 To maps.count - 1
        If maps.keys(i) = key Then
            Return StrPtr(maps.values(i))
        End If
    Next
    Return 0 ' Indicate failure
End Function

Function CreateMap() As Map
    Dim map As Map
    MapInit map
    Return map
End Function

Function StoreValue(map As Map, key As cwstr, value As Double) As Integer
    Dim result As Integer = MapPut(map, key, Str(value))
    Return result
End Function

' parse function
Function Parse(tokens() As Token) As Integer
    Dim i As Integer
    Dim SymbolTable As Map
    MapInit SymbolTable
    For i = 0 To UBound(tokens)
        Dim token As Token = tokens(i)
        If token.Type1 = TK_IDENTIFIER Then
            If tokens(i + 1).Type1 = TK_ASSIGN Then
                ' Handle variable assignment
                Dim varName As cwstr = token.Value
                Dim exprStart As Integer = i + 2
                Dim exprEnd As Integer = FindExpressionEnd(tokens(), exprStart)
                Dim expr As cwstr = JoinTokens(tokens(), exprStart, exprEnd)
                Dim result As Double = EvaluateExpression(expr)
                ' Store the result in a symbol table
                StoreValue(SymbolTable, varName, result)
                i = exprEnd
            Else
                Print "Error: Expected assignment operator"
                Return -1
            End If
        ElseIf token.Type1 = TK_PRINT Then
            ' Handle print statement Line 239:
            Dim exprStart As Integer
            Dim exprEnd As Integer = FindExpressionEnd(tokens(), exprStart)
            Dim expr As cwstr = JoinTokens(tokens(), exprStart, exprEnd)
            Dim result As Double = EvaluateExpression(expr)
            Print "result "; result
            i = exprEnd + 2
        End If
    Next
    Return 0
End Function

Function GetValue(map As Map, key As cwstr) As Double
    Dim value As cwstr Ptr = MapGet(map, key)
    If value = 0 Then
        Return 0
    Else
        Return Val(*value)
    End If
End Function

' -------------------------- // correct result 50 :-) -------- //
' afxInputBox
'
Dim inputs As cwstr '= "a = 2 + 3 * 10 print a" ' result 50 ok
'Input "make inputs and return: "; inputs
inputs=afxInputbox(0,0,0,"make inputs And Return: ",inputs,"") ';inputs
' b = 4 + 9 * 20 - 10 print b ' result: 250 ok
' c = 6 + 5 * 6 / 4 print c ' result ok 16.5
messagebox(NULL,inputs,"result on console output",mb_ok)

' -------------------------- // correct result 50 :-) -------- //

Dim tokens() As Token
Dim tokenCount As Integer = Split(inputs, tokens())

Dim result As Integer = Parse(tokens())

If result = 0 Then
    Print "Execution completed successfully"
Else
    Print "Error: Execution failed"
End If

' Wait for a key press before closing the console
Print "Press any key to continue..."
Sleep
While Inkey <> "" : Wend
' ends
'
'Dim st As cwstr
'st = afxInputBox(0,0,0,"type in","prog inputbox","")
'messagebox(NULL,st,"prog",mb_ok)


Frank Brübach

#2
hello all, after some weeks And working at freebasic again, I have updated
my freebasic parser example And transport it easily to afx cWindow class..
you can find testing example below in code example

If you want To test This parser Do it, have fun. I have learned New things again
so I am sharing This code example as other examples before too, thanks frank

but I don't expect any feedback as usual ;)
(in general this forum is absolutely dead except of four five well known users here.. that's a pity)

'
' freebasic '
' frankos parser example june 2024 - end of february 2025
' part eleven new and all is running fine :-)
' AFX update one 22-02-2025, frank brübach

'
' correct examples for testing:
'
' d = 9 * 20 - 10 print d ' 170
' g = 9 * 20 + 5 print g ' 185
' '' g = ( 9 * 20 ) + 25 print g ' 205
' a = 2 + 3 * 10 print a ' 50 ok
' b = ( 9 * 20 ) - 10 print b ' 170
' d = ( 9 * 20 ) + ( 9 - 10 ) print d ' 179
' f = 2 + 3 * 10 % 4 print f ' result should be 2 ok
'
' if 5 < 6 print 1 else print 0 ' result 1 ok
' if 5 > 6 print 0 else print 1 ' result 0 ok
'
'
#define UNICODE
#INCLUDE ONCE "Afx/CWindow.inc"
USING Afx

' '''''''''''''''''''''''''''''''''''''''
' Define the Enum and Type
Enum TokenType
    TK_INTEGER
    TK_PLUS
    TK_MINUS
    TK_MULTIPLY
    TK_DIVIDE
    TK_MODULUS ' new
    TK_LPAREN
    TK_RPAREN
    TK_ASSIGN
    TK_IDENTIFIER
    TK_PRINT
    TK_IF ' new
    TK_ELSE ' new
    TK_EOF
    TK_GREATER ' new
    TK_LESS ' new
    TK_UNKNOWN
End Enum

Type Token
    Type1 As TokenType
    Value As cwstr
End Type

' IsNumeric() function
Function IsNumeric(ByVal value As cwstr) As Integer
    Static numericChars As cwstr
    numericChars = "0123456789.-"
    If Len(value) = 0 Then Return False

    Dim dotCount As Integer = 0
    For i As Integer = 1 To Len(value)
        Dim c As cwstr = Mid(value, i, 1)
        If InStr(numericChars, c) = 0 Then
            Return False
        ElseIf c = "." Then
            dotCount += 1
            If dotCount > 1 Then
                Return False
            End If
        End If
    Next

    Return True
End Function

Function GetTokenType(ByVal value As cwstr) As TokenType
    If IsNumeric(value) Then
        Return TK_INTEGER
    ElseIf value = "+" Then
        Return TK_PLUS
    ElseIf value = "-" Then
        Return TK_MINUS
    ElseIf value = "*" Then
        Return TK_MULTIPLY
    ElseIf value = "/" Then
        Return TK_DIVIDE
    ElseIf value = "%" Then
        Return TK_MODULUS
    ElseIf value = "(" Then
        Return TK_LPAREN
    ElseIf value = ")" Then
        Return TK_RPAREN
    ElseIf value = "=" Then
        Return TK_ASSIGN
    ElseIf value = "print" Then
        Return TK_PRINT
    ElseIf value = "if" Then
        Return TK_IF
    ElseIf value = "else" Then
        Return TK_ELSE
    ElseIf value = ">" Then   
        Return TK_GREATER
    ElseIf value = "<" Then
        Return TK_LESS
    ElseIf value = "" Then
        Return TK_EOF
    Else
        Return TK_IDENTIFIER
    End If
End Function

' Split() function
Function Split(ByVal inputs As cwstr, tokens2() As Token) As Integer
    Dim token1 As cwstr = ""
    Dim tokenCount As Integer = 0
    Dim i As Integer

    For i = 1 To Len(inputs)
        Dim c As cwstr = Mid(inputs, i, 1)
        If c = " " Then
            If token1 <> "" Then
                ReDim Preserve tokens2(0 To tokenCount)
                tokens2(tokenCount).Value = token1
                tokens2(tokenCount).Type1 = GetTokenType(token1)
                tokenCount += 1
                token1 = ""
            End If
        Else
            token1 += c
        End If
    Next
    If token1 <> "" Then
        ReDim Preserve tokens2(0 To tokenCount)
        tokens2(tokenCount).Value = token1
        tokens2(tokenCount).Type1 = GetTokenType(token1)
    End If

    Return tokenCount
End Function

Function EvaluateExpression(ByVal inputs As cwstr) As Double
    Dim tokens() As Token
    Dim tokenCount As Integer = Split(inputs, tokens())

    Dim total As Double = 0
    Dim currentNumber As Double = 0
    Dim operators As cwstr = "+"
    Dim comparisonResult As Double 'Boolean
    comparisonResult = False

    For i As Integer = 0 To UBound(tokens)
        Dim token As Token = tokens(i)

        If token.Type1 = TK_INTEGER Then
            currentNumber = Val(token.Value)
            If operators = "+" Then
                total += currentNumber
            ElseIf operators = "-" Then
                total -= currentNumber
            ElseIf operators = "*" Then
                total *= currentNumber
            ElseIf operators = "/" Then
                If currentNumber <> 0 Then
                    total /= currentNumber
                Else
                    Print "Error: Division by zero"
                    Exit For
                End If
            ElseIf operators = "%" Then
                If currentNumber <> 0 Then
                    total = total Mod currentNumber
                Else
                    Print "Error: Division by zero"
                    Exit For
                End If
            ElseIf operators = ">" Then
                comparisonResult = (total > currentNumber)
                Return ABS(comparisonResult)
            ElseIf operators = "<" Then
                comparisonResult = (total < currentNumber)
                Return ABS(comparisonResult) ' ok with double but not with boolean !
            End If
            ' PRINT ABS(-1), ABS(-3.1415), ABS(42)
            operators = "-"
        ElseIf token.Type1 = TK_PLUS Then
            operators = "+"
        ElseIf token.Type1 = TK_MINUS Then
            operators = "-"
        ElseIf token.Type1 = TK_MULTIPLY Then
            operators = "*"
        ElseIf token.Type1 = TK_DIVIDE Then
            operators = "/"
        ElseIf token.Type1 = TK_MODULUS Then
            operators = "%"
        ElseIf token.Type1 = TK_GREATER Then
            operators = ">"
        ElseIf token.Type1 = TK_LESS Then
            operators = "<"
        End If
    Next

    Return total
End Function

' findExpressionEnd()
Function FindExpressionEnd(tokens() As Token, start As Integer) As Integer
    Dim i As Integer
    For i = start To UBound(tokens)
        If tokens(i).Type1 = TK_EOF Or tokens(i).Type1 = TK_PRINT Then
            Return i - 1
        End If
    Next
    Return UBound(tokens)
End Function

Function JoinTokens(tokens() As Token, start As Integer, ends As Integer) As cwstr
    Dim expr As cwstr = ""
    Dim i As Integer
    For i = start To ends
        expr += tokens(i).Value + " "
    Next
    Return Trim(expr)
End Function

' mapTable
Type Map
    keys(any) As cwstr
    values(Any) As cwstr
    count As Integer
End Type

' Initialize the map
Function MapInit(ByRef maps As Map) As integer
    maps.count = 0
    ReDim maps.keys(100)
    Redim maps.values(100)
    Function=1
End Function

' Add a key-value pair to the map
Function MapPut(ByRef maps As Map, key As cwstr, value As cwstr) As Integer
    maps.keys(maps.count) = key
    maps.values(maps.count) = value
    maps.count = maps.count + 1
    Return 0 ' Indicate success
End Function

' Retrieve a value from the map based on a key
Function MapGet(maps As Map, key As cwstr) As cwstr Ptr
    Dim i As Integer
    For i = 0 To maps.count - 1
        If maps.keys(i) = key Then
            'Return StrPtr(maps.values(i))
            Return @maps.values(i)
        End If
    Next
    Return 0 ' Indicate failure
End Function

Function CreateMap() As Map
    Dim map As Map
    MapInit map
    Return map
End Function

Function StoreValue(map As Map, key As cwstr, value As Double) As Integer
    Dim result As Integer = MapPut(map, key, Str(value))
    Return result
End Function

Function FindElseToken(tokens() As Token, start As Integer) As Integer
    Dim i As Integer
    For i = start To UBound(tokens)
        If tokens(i).Type1 = TK_ELSE Then
            Return i
        End If
    Next
    Return -1
End Function

Function Parse(tokens() As Token) As Integer
    Dim i As Integer
    Dim SymbolTable As Map
    MapInit SymbolTable
    For i = 0 To UBound(tokens)
        Dim token As Token = tokens(i)
        If token.Type1 = TK_IDENTIFIER Then
            If tokens(i + 1).Type1 = TK_ASSIGN Then
                ' Handle variable assignment
                Dim varName As cwstr = token.Value
                Dim exprStart As Integer = i + 2
                Dim exprEnd As Integer = FindExpressionEnd(tokens(), exprStart)
                Dim expr As cwstr = JoinTokens(tokens(), exprStart, exprEnd)
                Dim result As Double = EvaluateExpression(expr)
                ' Store the result in a symbol table
                StoreValue(SymbolTable, varName, result)
                i = exprEnd+2 ' this two lines were missing :-)
                Print "result "; result ' ' this two lines were missing :-)
            Else
                Print "Error: Expected assignment operator"
                Return -1
            End If
        ElseIf token.Type1 = TK_PRINT Then
            ' Handle print statement
            Dim exprStart As Integer '= i + 1
            Dim exprEnd As Integer = FindExpressionEnd(tokens(), exprStart)
            Dim expr As cwstr = JoinTokens(tokens(), exprStart, exprEnd)
            Dim result As Double = EvaluateExpression(expr)
            Print "result "; result
            'sleep
             'i = exprEnd + 2
        ElseIf token.Type1 = TK_IF Then
            ' Handle if statement
            Dim conditionStart As Integer = i + 1
            Dim conditionEnd As Integer = FindExpressionEnd(tokens(), conditionStart)
            Dim condition As cwstr = JoinTokens(tokens(), conditionStart, conditionEnd)
            Dim conditionResult As Double = EvaluateExpression(condition)
            If conditionResult <> 0 Then
                ' Execute the true branch
                Dim trueBranchStart As Integer = conditionEnd + 1
                Dim trueBranchEnd As Integer = FindExpressionEnd(tokens(), trueBranchStart)
                Dim trueBranch As cwstr = JoinTokens(tokens(), trueBranchStart, trueBranchEnd)
                Dim trueResult As Integer
            If trueResult <> 0 Then
                    Return trueResult
                End If
                i = trueBranchEnd
            Else
                ' Skip the true branch and look for the else branch
                Dim elseTokenIndex As Integer = FindElseToken(tokens(), conditionEnd + 1)
                If elseTokenIndex <> -1 Then
                    Dim elseBranchStart As Integer = elseTokenIndex + 1
                    Dim elseBranchEnd As Integer = FindExpressionEnd(tokens(), elseBranchStart)
                    Dim elseBranch As cwstr
                    elseBranch = JoinTokens(tokens(), elseBranchStart, elseBranchEnd)
                    Dim elseResult As Integer
                    If elseResult <> 0 Then
                        Return elseResult
                    End If
                    i = elseBranchEnd
                End If
            End If
        End If
    Next
    Return 0
End Function

Function GetValue(map As Map, key As cwstr) As Double
    Dim value As cwstr Ptr = MapGet(map, key)
    If value = 0 Then
        Return 0
    Else
        Return Val(*value)
    End If
End Function

' -------------------------- // correct result 50 :-) -------- //
Dim inputs As cwstr '= "a = 2 + 3 * 10 print a" ' 50
inputs = afxInputbox(0,0,0,"make inputs And Return: ",inputs,"")

' b = 4 + 9 * 20 - 10 print b ' result: 250 ok
' c = 6 + 5 * 6 / 4 print c ' result ok 16.5
' f = 2 + 3 * 10 % 4 print f" ' result should be 2 ok

messagebox(NULL,inputs,"result on console output",mb_ok)
'
' correct examples for testing:
' d = 9 * 20 - 10 print d ' 170
' g = 9 * 20 + 5 print g ' 185
' '' g = ( 9 * 20 ) + 25 print g ' 205
' a = 2 + 3 * 10 print a ' 50 ok
' b = ( 9 * 20 ) - 10 print b ' 170
' d = ( 9 * 20 ) + ( 9 - 10 ) print d ' 179
' f = 2 + 3 * 10 % 4 print f ' result should be 2 ok
'
' if 5 < 6 print 1 else print 0 ' result 1 ok
' if 5 > 6 print 0 else print 1 ' result 0 ok

' -------------------------- // correct result 50 :-) -------- //

Dim tokens() As Token
Dim tokenCount As Integer = Split(inputs, tokens())

Dim result As Integer = Parse(tokens())

If result = 0 Then
    Print "Execution completed successfully"
Else
    Print "Error: Execution failed"
End If

' Wait for a key press before closing the console
Print "Press any key to continue..."
Sleep
While InKey <> "" : Wend
' ends