78 lines
1.4 KiB
Go
78 lines
1.4 KiB
Go
package lexpr
|
|
|
|
import "context"
|
|
|
|
func infixToRpn(ctx context.Context, tokens <-chan Token) <-chan Token {
|
|
out := make(chan Token)
|
|
stack := TokenStack{}
|
|
go func() {
|
|
defer func() {
|
|
if len(stack) > 0 {
|
|
for {
|
|
if stack.Head().typ == lp {
|
|
out <- Token{
|
|
typ: tokError,
|
|
value: "invalid brakets",
|
|
}
|
|
break
|
|
}
|
|
out <- stack.Pop()
|
|
if len(stack) == 0 {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
close(out)
|
|
}()
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
return
|
|
case tkn, ok := <-tokens:
|
|
if !ok {
|
|
return
|
|
}
|
|
switch tkn.typ {
|
|
case number, word, str, tokError:
|
|
out <- tkn
|
|
case funct:
|
|
stack.Push(tkn)
|
|
case sep:
|
|
for stack.Head().typ != lp {
|
|
if len(stack) == 0 {
|
|
out <- Token{
|
|
typ: tokError,
|
|
value: "no arg separator or opening braket",
|
|
}
|
|
return
|
|
}
|
|
out <- stack.Pop()
|
|
}
|
|
case op:
|
|
for len(stack) > 0 && (stack.Head().typ != op || (stack.Head().priority >= tkn.priority)) {
|
|
out <- stack.Pop()
|
|
}
|
|
stack.Push(tkn)
|
|
case lp:
|
|
stack.Push(tkn)
|
|
case rp:
|
|
for stack.Head().typ != lp {
|
|
if len(stack) == 0 {
|
|
out <- Token{
|
|
typ: tokError,
|
|
value: "no opening braket",
|
|
}
|
|
return
|
|
}
|
|
out <- stack.Pop()
|
|
}
|
|
stack.Pop()
|
|
if stack.Head().typ == funct {
|
|
out <- stack.Pop()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}()
|
|
return out
|
|
}
|