RosettaCodeData/Task/Parsing-Shunting-yard-algor.../UNIX-Shell/parsing-shunting-yard-algor...

104 lines
2.7 KiB
Bash

#!/bin/sh
getopprec() {
case "$1" in
'+') echo 2;;
'-') echo 2;;
'*') echo 3;;
'/') echo 4;;
'%') echo 4;;
'^') echo 4;;
'(') echo 5;;
esac
}
getopassoc() {
case "$1" in
'^') echo r;;
*) echo l;;
esac
}
showstacks() {
[ -n "$1" ] && echo "Token: $1" || echo "End parsing"
echo -e "\tOutput: `tr $'\n' ' ' <<< "$out"`"
echo -e "\tOperators: `tr $'\n' ' ' <<< "$ops"`"
}
infix() {
local out="" ops=""
while [ "$#" -gt 0 ]; do
grep -qE '^[0-9]+$' <<< "$1"
if [ "$?" -eq 0 ]; then
out="`sed -e '$a'"$1" -e '/^$/d' <<< "$out"`"
showstacks "$1"
shift && continue
fi
grep -q '^[-+*/^%]$' <<< "$1"
if [ "$?" -eq 0 ]; then
if [ -n "$ops" ]; then
thispred=`getopprec "$1"`
thisassoc=`getopassoc "$1"`
topop="`sed -n '$p' <<< "$ops"`"
thatpred=`getopprec "$topop"`
thatassoc=`getopassoc "$topop"`
while [ $thatpred -gt $thispred ] 2> /dev/null || ( [ \
$thatpred -eq $thispred ] 2> /dev/null && [ $thisassoc = \
'l' ] 2> /dev/null ); do # To /dev/null 'cus u r fake news
[ "$topop" = '(' ] && break
op="`sed -n '$p' <<< "$ops"`"
out="`sed -e '$a'"$op" -e '/^$/d' <<< "$out"`"
ops="`sed '$d' <<< "$ops"`"
topop="`sed -n '$p' <<< "$ops"`"
thatpred=`getopprec "$topop"`
thatassoc=`getopassoc "$topop"`
done
fi
ops="`sed -e '$a'"$1" -e '/^$/d' <<< "$ops"`"
showstacks "$1"
shift && continue
fi
if [ "$1" = '(' ]; then
ops="`sed -e '$a'"$1" -e '/^$/d' <<< "$ops"`"
showstacks "$1"
shift && continue
fi
if [ "$1" = ')' ]; then
grep -q '^($' <<< "`sed -n '$p' <<< "$ops"`"
while [ "$?" -ne 0 ]; do
op="`sed -n '$p' <<< "$ops"`"
out="`sed -e '$a'"$op" -e '/^$/d' <<< "$out"`"
ops="`sed '$d' <<< "$ops"`"
grep -q '^($' <<< "`sed '$p' <<< "$ops"`"
done
ops="`sed '$d' <<< "$ops"`"
showstacks "$1"
shift && continue
fi
shift
done
while [ -n "$ops" ]; do
op="`sed -n '$p' <<< "$ops"`"
out="`sed -e '$a'"$op" -e '/^$/d' <<< "$out"`"
ops="`sed '$d' <<< "$ops"`"
done
showstacks "$1"
}
infix 3 + 4 \* 2 / \( 1 - 5 \) ^ 2 ^ 3