70 lines
2 KiB
AutoHotkey
70 lines
2 KiB
AutoHotkey
SetBatchLines -1
|
|
#NoEnv
|
|
|
|
expr := "3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3"
|
|
|
|
output := "Testing string '" expr "'`r`n`r`nToken`tOutput Queue"
|
|
. Space(StrLen(expr)-StrLen("Output Queue")+2) "OP Stack"
|
|
|
|
; define a stack with semantic .push() and .pop() funcs
|
|
stack := {push: func("ObjInsert"), pop: func("ObjRemove"), peek: func("Peek")}
|
|
|
|
Loop Parse, expr, %A_Space%
|
|
{
|
|
token := A_LoopField
|
|
if token is number
|
|
Q .= token A_Space
|
|
if isOp(token){
|
|
o1 := token
|
|
while isOp(o2 := stack.peek())
|
|
and ((isLeft(o1) and Precedence(o1) <= Precedence(o2))
|
|
or (isRight(o1) and Precedence(o1) < Precedence(o2)))
|
|
Q .= stack.pop() A_Space
|
|
stack.push(o1)
|
|
}
|
|
If ( token = "(" )
|
|
stack.push(token)
|
|
If ( token = ")" )
|
|
{
|
|
While ((t := stack.pop()) != "(") && (t != "")
|
|
Q .= t A_Space
|
|
if (t = "")
|
|
throw Exception("Unmatched parenthesis. "
|
|
. "Character number " A_Index)
|
|
}
|
|
output .= "`r`n" token Space(7) Q Space(StrLen(expr)+2-StrLen(Q))
|
|
. Disp(stack)
|
|
}
|
|
output .= "`r`n(empty stack to output)"
|
|
While (t := stack.pop()) != ""
|
|
if InStr("()", t)
|
|
throw Exception("Unmatched parenthesis.")
|
|
else Q .= t A_Space, output .= "`r`n" Space(8) Q
|
|
. Space(StrLen(expr)+2-StrLen(Q)) Disp(stack)
|
|
output .= "`r`n`r`nFinal string: '" Q "'"
|
|
clipboard := output
|
|
|
|
isOp(t){
|
|
return (!!InStr("+-*/^", t) && t)
|
|
}
|
|
Peek(this){
|
|
r := this.Remove(), this.Insert(r)
|
|
return r
|
|
}
|
|
IsLeft(o){
|
|
return !!InStr("*/+-", o)
|
|
}
|
|
IsRight(o){
|
|
return o = "^"
|
|
}
|
|
Precedence(o){
|
|
return (InStr("+-/*^", o)+3)//2
|
|
}
|
|
Disp(obj){
|
|
for each, val in obj
|
|
o := val . o
|
|
return o
|
|
}
|
|
Space(n){
|
|
return n>0 ? A_Space Space(n-1) : ""
|
|
}
|