module ExpressionProcessing export expr_to_postfix, is_binary_operator export PostfixType export Operator, ADD, SUBTRACT, MULTIPLY, DIVIDE, POWER, ABS, LOG, EXP, SQRT export ElementType, EMPTY, FLOAT32, OPERATOR, INDEX export ExpressionElement @enum Operator ADD=1 SUBTRACT=2 MULTIPLY=3 DIVIDE=4 POWER=5 ABS=6 LOG=7 EXP=8 SQRT=9 @enum ElementType EMPTY=0 FLOAT32=1 OPERATOR=2 INDEX=3 struct ExpressionElement Type::ElementType Value::Int32 # Reinterpret the stored value to type "ElementType" when using it end const PostfixType = Vector{ExpressionElement} " Converts a julia expression to its postfix notation. NOTE: All 64-Bit values will be converted to 32-Bit. Be aware of the lost precision " function expr_to_postfix(expr::Expr)::PostfixType postfix = PostfixType() @inbounds operator = get_operator(expr.args[1]) @inbounds for j in 2:length(expr.args) arg = expr.args[j] if typeof(arg) === Expr append!(postfix, expr_to_postfix(arg)) elseif typeof(arg) === Symbol # variables/parameters # maybe TODO: replace the parameters with their respective values, as this might make the expr evaluation faster exprElement = convert_to_ExpressionElement(convert_var_to_int(arg)) push!(postfix, exprElement) else exprElement = convert_to_ExpressionElement(convert(Float32, arg)) push!(postfix, exprElement) end # only add operator if at least 2 values are added. For the case where another expression is added first, we check if we are at the first iteration or not ( j != 2) if length(postfix) >= 2 && j != 2 exprElement = convert_to_ExpressionElement(operator) push!(postfix, exprElement) end end # For the case this expression has an operator that only takes in a single value like "abs(x)" if length(postfix) == 1 push!(postfix, convert_to_ExpressionElement(operator)) end return postfix end function get_operator(op::Symbol)::Operator if op == :+ return ADD elseif op == :- return SUBTRACT elseif op == :* return MULTIPLY elseif op == :/ return DIVIDE elseif op == :^ return POWER elseif op == :abs return ABS elseif op == :log return LOG elseif op == :exp return EXP elseif op == :sqrt return SQRT elseif op == :powabs return POWER # TODO: Fix this else throw("Operator unknown") end end "Extracts the number from a variable/parameter and returns it. If the symbol is a parameter ```pn```, the resulting value will be negativ. ```x0 and p0``` are not allowed." function convert_var_to_int(var::Symbol)::Int32 varStr = String(var) number = parse(Int32, SubString(varStr, 2)) if varStr[1] == 'p' number = -number end return number end function convert_to_ExpressionElement(element::Int32)::ExpressionElement value = reinterpret(Int32, element) return ExpressionElement(INDEX, value) end function convert_to_ExpressionElement(element::Int64)::ExpressionElement value = reinterpret(Int32, convert(Int32, element)) return ExpressionElement(INDEX, value) end function convert_to_ExpressionElement(element::Float32)::ExpressionElement value = reinterpret(Int32, element) return ExpressionElement(FLOAT32, value) end function convert_to_ExpressionElement(element::Float64)::ExpressionElement value = reinterpret(Int32, convert(Float32, element)) return ExpressionElement(FLOAT32, value) end function convert_to_ExpressionElement(element::Operator)::ExpressionElement value = reinterpret(Int32, element) return ExpressionElement(OPERATOR, value) end function is_binary_operator(operator::Operator)::Bool if operator == ADD return true elseif operator == SUBTRACT return true elseif operator == MULTIPLY return true elseif operator == DIVIDE return true elseif operator == POWER return true elseif operator == ABS return false elseif operator == LOG return false elseif operator == EXP return false elseif operator == SQRT return false else throw(ArgumentError("Unknown operator '$operator'. Cannot determine if it is binary or not.")) end end end