June 2018 Update

This commit is contained in:
Ingy döt Net 2018-06-22 20:57:24 +00:00
parent ba8067c3b7
commit 22f33d4004
5278 changed files with 84726 additions and 14379 deletions

View file

@ -0,0 +1,130 @@
\ Convert infix expression to postfix, using 'shunting-yard' algorithm
\ https://en.wikipedia.org/wiki/Shunting-yard_algorithm
\ precedence of infix tokens. negative means 'right-associative', otherwise left:
with: n
{
"+" : 2,
"-" : 2,
"/" : 3,
"*" : 3,
"^" : -4,
"(" : 1,
")" : -1
} var, tokens
: precedence \ s -- s n
tokens @ over m:@ nip
null? if drop 0 then ;
var ops
var out
: >out \ x --
out @ swap
a:push drop ;
: >ops \ op prec --
2 a:close
ops @ swap
a:push drop ;
: a:peek -1 a:@ ;
\ Check the array for items with greater or equal precedence,
\ and move them to the out queue:
: pop-ops \ op prec ops -- op prec ops
\ empty array, do nothing:
a:len not if ;; then
\ Look at top of ops stack:
a:peek a:open \ op p ops[] op2 p2
\ if the 'p2' is not less p (meaning item on top of stack is greater or equal
\ in precedence), then pop the item from the ops stack and push onto the out:
3 pick \ p2 p
< not if
\ op p ops[] op2
>out a:pop drop recurse ;;
then
drop ;
: right-paren
"RIGHTPAREN" . cr
2drop
\ move non-left-paren from ops and move to out:
ops @
repeat
a:len not if
break
else
a:pop a:open
1 = if
2drop ;;
else
>out
then
then
again drop ;
: .state \ n --
drop \ "Token: %s\n" s:strfmt .
"Out: " .
out @ ( . space drop ) a:each drop cr
"ops: " . ops @ ( 0 a:@ . space 2drop ) a:each drop cr cr ;
: handle-number \ s n --
"NUMBER " . over . cr
drop >out ;
: left-paren \ s n --
"LEFTPAREN" . cr
>ops ;
: handle-op \ s n --
"OPERATOR " . over . cr
\ op precedence
\ Is the current op left-associative?
dup sgn 1 = if
\ it is, so check the ops array for items with greater or equal precedence,
\ and move them to the out queue:
ops @ pop-ops drop
then
\ push the operator
>ops ;
: handle-token \ s --
precedence dup not if
\ it's a number:
handle-number
else
dup 1 = if left-paren
else dup -1 = if right-paren
else handle-op
then then
then ;
: infix>postfix \ s -- s
/\s+/ s:/ \ split to indiviual whitespace-delimited tokens
\ Initialize our data structures
a:new ops ! a:new out !
(
nip dup >r
handle-token
r> .state
) a:each drop
\ remove all remaining ops and put on output:
out @
ops @ a:rev
( nip a:open drop a:push ) a:each drop
\ final string:
" " a:join ;
"3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3" infix>postfix . cr
"Expected: \n" . "3 4 2 * 1 5 - 2 3 ^ ^ / +" . cr
bye