Parser example problem

New to FreeBASIC? Post your questions here.
Post Reply
Löwenherz
Posts: 227
Joined: Aug 27, 2008 6:26
Location: Bad Sooden-Allendorf, Germany

Parser example problem

Post by Löwenherz »

hello all, need a little help. end of june I had made a simple parser example and that's
running fine.
now I wanted to include some enums with TokenTypes... but my example doesn't work anymore
perhaps somebody can help.
thanks, lionheart

Code: Select all

' 1) FreeBASIC parser example by lionheart 25-06-2024 go
' 2) add enums... 24-01-2025, lionheart
' example doesn't work anymore, need little help
'
' 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

' Split() function 
Function Split(ByVal inputs As String, ByRef tokens2() As token) As Integer '' error
 
    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) '' error
                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) '' error
    End If

    Return tokenCount
End Function

' 
Function GetTokenType(ByVal value As String) As TokenType
    If IsNumeric(value) Then '' error
        Return TK_INTEGER
    ElseIf value = "+" Then '' error
        Return TK_PLUS
    ElseIf value = "-" Then '' error
        Return TK_MINUS
    ElseIf value = "*" Then '' error
        Return TK_MULTIPLY 
    ElseIf value = "/" Then '' error
        Return TK_DIVIDE
    ElseIf value = "(" Then '' error
        Return TK_LPAREN
    ElseIf value = ")" Then '' error
        Return TK_RPAREN
    Else
        Return TK_UNKNOWN
    End If
End Function

' IsNumeric() function
Function IsNumeric(ByVal value As String) As Integer
    Static numericChars As String
    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 String = 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

' 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 String = "+"

    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

' Test the code with different inputs
Dim inputs As String = "2 + 3 * 10" ' 50 result ok
Dim result As Double = EvaluateExpression(inputs)

If result <> 0 Then
    Print "The total is "; result
Else
    Print "Error: Invalid input"
End If

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

fxm
Moderator
Posts: 12468
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Parser example problem

Post by fxm »

- Declaration to pass an array to a procedure must not use either 'Byref' or 'Byval'.
- Procedures must be declared or defined before they are called.

Code: Select all

' 1) FreeBASIC parser example by lionheart 25-06-2024 go
' 2) add enums... 24-01-2025, lionheart
' example doesn't work anymore, need little help
'
' 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 String
    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 String = 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 String) As TokenType
    If IsNumeric(value) Then '' error
        Return TK_INTEGER
    ElseIf value = "+" Then '' error
        Return TK_PLUS
    ElseIf value = "-" Then '' error
        Return TK_MINUS
    ElseIf value = "*" Then '' error
        Return TK_MULTIPLY 
    ElseIf value = "/" Then '' error
        Return TK_DIVIDE
    ElseIf value = "(" Then '' error
        Return TK_LPAREN
    ElseIf value = ")" Then '' error
        Return TK_RPAREN
    Else
        Return TK_UNKNOWN
    End If
End Function

' Split() function 
Function Split(ByVal inputs As String, 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) '' error
                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) '' error
    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 String = "+"

    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

' Test the code with different inputs
Dim inputs As String = "2 + 3 * 10" ' 50 result ok
Dim result As Double = EvaluateExpression(inputs)

If result <> 0 Then
    Print "The total is "; result
Else
    Print "Error: Invalid input"
End If

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

Löwenherz
Posts: 227
Joined: Aug 27, 2008 6:26
Location: Bad Sooden-Allendorf, Germany

Re: Parser example problem

Post by Löwenherz »

- Declaration to pass an array to a procedure must not use either 'Byref' or 'Byval'.
- Procedures must be declared or defined before they are called.
Many thanks fxm.. all is running fine again. The Array Handling for a procedure I still Had to learn without byref or byval... Thats new for me.
Löwenherz
Posts: 227
Joined: Aug 27, 2008 6:26
Location: Bad Sooden-Allendorf, Germany

Re: Parser example problem

Post by Löwenherz »

Hello fxm.. one more question.. sorry..

Array dimension possible in a Type ?

Code: Select all

'
Type Map
    keys() As String ' error 
    values() As String ' error 
    count As Integer
End Type

' Initialize the map
Function MapInit(ByRef maps As Map) As integer 
    maps.count = 0
    ReDim maps.keys(100) ' error
    Redim maps.values(100) ' error 
End Function
fxm
Moderator
Posts: 12468
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Parser example problem

Post by fxm »

Code: Select all

'
Type Map
    keys(Any) As String ' error 
    values(Any) As String ' error 
    count As Integer
End Type

' Initialize the map
Function MapInit(ByRef maps As Map) As integer 
    maps.count = 0
    ReDim maps.keys(100) ' error
    Redim maps.values(100) ' error 
End Function
Löwenherz
Posts: 227
Joined: Aug 27, 2008 6:26
Location: Bad Sooden-Allendorf, Germany

Re: Parser example problem

Post by Löwenherz »

Hello.. and thanks fxm for your correction..

I have expand my Parser example a little and I can Compile and make Run it but Got a wrong result 0.

Code: Select all

' Parser example freebasic, 24+25-01-2025, lionheart
' part three
'
' 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 String
    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 String = 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 String, 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 String = "+"

    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 String
    Dim expr As String = ""
    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 String  
    values(Any) As String  
    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 String, value As String) 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 String) As 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

'Dim SymbolTable As Map
'MapInit SymbolTable

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

Function StoreValue(map As Map, key As String, 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 String = token.Value
                Dim exprStart As Integer = i + 2
                Dim exprEnd As Integer = FindExpressionEnd(tokens(), exprStart)
                Dim expr As String = 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
            Dim exprStart As Integer = i + 1
            Dim exprEnd As Integer = FindExpressionEnd(tokens(), exprStart)
            Dim expr As String = JoinTokens(tokens(), exprStart, exprEnd)
            Dim result As Double = EvaluateExpression(expr)
            Print result
            i = exprEnd
        End If
    Next
    Return 0
End Function

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

Print "here's a result" 
' -------------------------- // wrong result 0 -------- //
Dim inputs As String = "a = 2 + 3 * 10 print a"
' -------------------------- // wrong result 0 -------- //
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
fxm
Moderator
Posts: 12468
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Parser example problem

Post by fxm »

In Parse(tokens() As Token) As Integer:

Line 239:
Dim exprStart As Integer = i + 1
'i+1' is not the right value

Line 244:
i = exprEnd
rather:
i = exprEnd + 2
or better:
Exit For
Löwenherz
Posts: 227
Joined: Aug 27, 2008 6:26
Location: Bad Sooden-Allendorf, Germany

Re: Parser example problem

Post by Löwenherz »

I have Got correct result :-)
Great, I learned something
new about Freebasic, thank you
very much for that fxm

Code: Select all

' 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
'
' 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 String
    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 String = 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 String, 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 String = "+"

    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 String
    Dim expr As String = ""
    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 String  
    values(Any) As String  
    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 String, value As String) 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 String) As 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

'Dim SymbolTable As Map
'MapInit SymbolTable

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

Function StoreValue(map As Map, key As String, 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 String = token.Value
                Dim exprStart As Integer = i + 2
                Dim exprEnd As Integer = FindExpressionEnd(tokens(), exprStart)
                Dim expr As String = 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 = i + 1 '' wrong value I have deleted = i+1
            Dim exprStart As Integer 
            Dim exprEnd As Integer = FindExpressionEnd(tokens(), exprStart)
            Dim expr As String = JoinTokens(tokens(), exprStart, exprEnd)
            Dim result As Double = EvaluateExpression(expr)
            Print result
            i = exprEnd + 2
        End If
    Next
    Return 0
End Function

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

Print "here's a result" 
' -------------------------- // correct result 50 :-) -------- //
Dim inputs As String = "a = 2 + 3 * 10 print a"
' -------------------------- // 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
Second edit:

You can use Input for making new calculations
Include These lines at the end of example after Parse function ...

For example: b= 4+9 * 20 Print b

Code: Select all

 

' -------------------------- // correct result 50 :-) -------- // 
Dim inputs As String = "a = 2 + 3 * 10 print a"
Input "make inputs and return: "; inputs 

' b = 4 + 9 * 20 print b ' result: 260

' -------------------------- // 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
Löwenherz
Posts: 227
Joined: Aug 27, 2008 6:26
Location: Bad Sooden-Allendorf, Germany

Re: Parser example problem

Post by Löwenherz »

Hello I Send a complete Code example. i add Here for better using. Feedback ist Welcome. Thanks.

Code: Select all

' 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:
'
' b = 4 + 9 * 20 print b ' result: 260
'
' 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 String
    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 String = 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 String, 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 String = "+"

    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 String
    Dim expr As String = ""
    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 String  
    values(Any) As String  
    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 String, value As String) 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 String) As 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

'Dim SymbolTable As Map
'MapInit SymbolTable

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

Function StoreValue(map As Map, key As String, 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 String = token.Value
                Dim exprStart As Integer = i + 2
                Dim exprEnd As Integer = FindExpressionEnd(tokens(), exprStart)
                Dim expr As String = 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 = i + 1 '' wrong value I have deleted = i+1
            Dim exprStart As Integer 
            Dim exprEnd As Integer = FindExpressionEnd(tokens(), exprStart)
            Dim expr As String = 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 String) As Double
    Dim value As String Ptr = MapGet(map, key)
    If value = 0 Then
        Return 0
    Else
        Return Val(*value)
    End If
End Function

' -------------------------- // correct result 50 :-) -------- // 
Dim inputs As String = "a = 2 + 3 * 10 print a"
Input "make inputs and return: "; inputs 

' b = 4 + 9 * 20 print b ' result: 260

' -------------------------- // 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
Löwenherz
Posts: 227
Joined: Aug 27, 2008 6:26
Location: Bad Sooden-Allendorf, Germany

Re: Parser example problem

Post by Löwenherz »

Little Update fixed a minus calculation :-)

Code: Select all

' freebasic parser example by lionheart first edition 25-06-2024
' Parser example freebasic, 24+25-01-2025, by lionheart
' part five, running all fine, many thanks to fxm for help
' complete code example with Input, 28-01-2025
' --> fixed a minus calc problem ;)
' add a error message too
'
' for example you are using for Input:
'
' b = 4 + 9 * 20 print b ' result: 260
' c = 6 + 5 * 6 / 4 print c ' 16.5
'
' for example you are using for Input:
'
' b = 4 + 9 * 20 - 10 print b ' result: 250
'
' 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 String
    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 String = 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 String, 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 String = "+"

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

        If token.Type1 = TK_INTEGER Then
            currentNumber = Val(token.Value)
            Select Case operators
                Case "+"
                    total += currentNumber
                Case "-"
                    total -= currentNumber
                Case "*"
                    total *= currentNumber
                Case "/"
                    If currentNumber <> 0 Then
                        total /= currentNumber
                    Else
                        Print "Error: Division by zero"
                        Return 0
                    End If
            End Select
       
            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 String
    Dim expr As String = ""
    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 String  
    values(Any) As String  
    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 String, value As String) As Integer
    If maps.count >= UBound(maps.keys) Then
        ReDim Preserve maps.keys(UBound(maps.keys) * 2)
        ReDim Preserve maps.values(UBound(maps.values) * 2)
    End If
    maps.keys(maps.count) = key
    maps.values(maps.count) = value
    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 String) As 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 String, 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 String = token.Value
                Dim exprStart As Integer = i + 2
                Dim exprEnd As Integer = FindExpressionEnd(tokens(), exprStart)
                Dim expr As String = JoinTokens(tokens(), exprStart, exprEnd)
                Dim result As Double = EvaluateExpression(expr)
                ' Store the result in a symbol table
                StoreValue(SymbolTable, varName, result)
                i = exprEnd
            Else
                Dim errorMsg As String = "Error: Expected assignment operator for identifier " & token.Value
                Print errorMsg
                Return -1
            End If
        ElseIf token.Type1 = TK_PRINT Then
            ' Handle print statement
            Dim exprStart As Integer 
            Dim exprEnd As Integer = FindExpressionEnd(tokens(), exprStart)
            Dim expr As String = JoinTokens(tokens(), exprStart, exprEnd)
            Dim result As Double = EvaluateExpression(expr)
            Print "result " & STR(result)
            i = exprEnd + 2
        End If
    Next
    Return 0
End Function

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

' -------------------------- // correct result 50 :) -------- // 
Dim inputs As String = "a = 2 + 3 * 10 print a"
Input "make inputs and return: "; inputs 

' b = 4 + 9 * 20 print b ' result: 260

' -------------------------- // 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, 28-01-2025
' fixed minus calculation, add error message
Luxan
Posts: 261
Joined: Feb 18, 2009 12:47
Location: New Zealand

Re: Parser example problem

Post by Luxan »

I wish you luck with this.

Some decades ago, I wrote a mathematical expression parser and evaluator,
written in a version of BASIC.

To construct this, I drew up Backus-Naur diagrams.
Even large exponents were catered for.

The code must be here somewhere.
Löwenherz
Posts: 227
Joined: Aug 27, 2008 6:26
Location: Bad Sooden-Allendorf, Germany

Re: Parser example problem

Post by Löwenherz »

I wish you luck with this.

Some decades ago, I wrote a mathematical expression parser and evaluator,
written in a version of BASIC.

To construct this, I drew up Backus-Naur diagrams.
Even large exponents were catered for.

Thanks luxan, I am learning still With freebasic that's making fun at all to program,
especially learning by mistakes ;)
a little update I have already made some days ago... but there weren't any feedback after my last example.. so I have stopped sharing it..

'
' examples for testing:
'
' a = 2 + 3 * 10 print a
' b = 4 + 9 * 20 - 10 print b ' result: 250
' d = 5 + 9 * 20 + ( 9 - 10 ) print d ' 279
' "f = 2 + 3 * 10 % 4 print f" ' result should be 2 ok

Code: Select all


' frankos parser example june 2024- jan2025
' part six new
' update one 28-01-2025, lionheart
' freebasic
' % if .. else.., update two: 10-02-2025
'
' '''''''''''''''''''''''''''''''''''''''
' 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_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 String
    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 String = 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 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_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_EOF
    Else
        Return TK_IDENTIFIER
    End If
End Function

' Split() function
Function Split(ByVal inputs As String, 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

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 String = "+"

    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
            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 = "/"
        ElseIf token.Type1 = TK_MODULUS 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 String
    Dim expr As String = ""
    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 String
    values(Any) As String
    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 String, value As String) 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 String) As 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 String, 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 String = token.Value
                Dim exprStart As Integer = i + 2
                Dim exprEnd As Integer = FindExpressionEnd(tokens(), exprStart)
                Dim expr As String = 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
            Dim exprStart As Integer ''= i + 1
            Dim exprEnd As Integer = FindExpressionEnd(tokens(), exprStart)
            Dim expr As String = JoinTokens(tokens(), exprStart, exprEnd)
            Dim result As Double = EvaluateExpression(expr)
            Print "result "; result
            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 String = 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 String = 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 String = JoinTokens(tokens(), elseBranchStart, elseBranchEnd)
                    Dim elseResult As Integer '= Parse(Split(elseBranch, tokens()))
                    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 String) As Double
    Dim value As String Ptr = MapGet(map, key)
    If value = 0 Then
        Return 0
    Else
        Return Val(*value)
    End If
End Function

' -------------------------- // correct result 50 :-) -------- //
Dim inputs As String '= "a = 2 + 3 * 10 print a"
Input "make inputs and return: "; inputs
'
' examples for testing:
'
' a = 2 + 3 * 10 print a
' b = 4 + 9 * 20 - 10 print b ' result: 250
' d = 5 + 9 * 20 + ( 9 - 10 ) print d ' 279
' "f = 2 + 3 * 10 % 4 print f" ' result should be 2 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

Post Reply