RosettaCodeData/Task/Parsing-Shunting-yard-algorithm/AutoHotkey/parsing-shunting-yard-algorithm.ahk
Ingy döt Net b83f433714 tasks a-s
2013-04-10 23:57:08 -07:00

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) : ""
}