RosettaCodeData/Task/Parsing-Shunting-yard-algorithm/Sidef/parsing-shunting-yard-algorithm.sidef

59 lines
1.3 KiB
Text
Raw Permalink Normal View History

2016-12-05 23:44:36 +01:00
var prec = Hash(
'^' => 4,
'*' => 3,
'/' => 3,
'+' => 2,
'-' => 2,
'(' => 1,
2017-09-23 10:01:46 +02:00
)
2016-12-05 23:44:36 +01:00
var assoc = Hash(
'^' => 'right',
'*' => 'left',
'/' => 'left',
'+' => 'left',
'-' => 'left',
2017-09-23 10:01:46 +02:00
)
2016-12-05 23:44:36 +01:00
func shunting_yard(prog) {
2017-09-23 10:01:46 +02:00
var inp = prog.words
var ops = []
var res = []
 
func report (op) {
printf("%25s  %-7s %10s %s\n",
res.join(' '), ops.join(' '), op, inp.join(' '))
}
2016-12-05 23:44:36 +01:00
func shift (t) { report( "shift #{t}"); ops << t }
func reduce (t) { report("reduce #{t}"); res << t }
2017-09-23 10:01:46 +02:00
 
2016-12-05 23:44:36 +01:00
while (inp) {
given(var t = inp.shift) {
when (/\d/) { reduce(t) }
when ('(') { shift(t) }
2017-09-23 10:01:46 +02:00
when (')') {
while (ops) {
(var x = ops.pop) == '(' ? break : reduce(x)
}
}
2016-12-05 23:44:36 +01:00
default {
2017-09-23 10:01:46 +02:00
var newprec = prec{t}
2016-12-05 23:44:36 +01:00
while (ops) {
2017-09-23 10:01:46 +02:00
var oldprec = prec{ops[-1]}
 
2016-12-05 23:44:36 +01:00
break if (newprec > oldprec)
break if ((newprec == oldprec) && (assoc{t} == 'right'))
2017-09-23 10:01:46 +02:00
 
reduce(ops.pop)
2016-12-05 23:44:36 +01:00
}
2017-09-23 10:01:46 +02:00
shift(t)
2016-12-05 23:44:36 +01:00
}
}
}
while (ops) { reduce(ops.pop) }
return res
}
2017-09-23 10:01:46 +02:00
 
say shunting_yard('3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3').join(' ')