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