From cc4c01c69c238c92602b393ed87575ba5edad352 Mon Sep 17 00:00:00 2001 From: Alexander Kiryukhin Date: Fri, 1 Jul 2022 02:16:07 +0300 Subject: first commit --- infixrpn.go | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 infixrpn.go (limited to 'infixrpn.go') diff --git a/infixrpn.go b/infixrpn.go new file mode 100644 index 0000000..18dde39 --- /dev/null +++ b/infixrpn.go @@ -0,0 +1,104 @@ +package expression + +import ( + "fmt" + "go/token" +) + +func (e *Evaluator) ToPRN(in <-chan Token) chan Token { + out := make(chan Token) + stack := &Stack{} + + go func() { + defer func() { + for !stack.Empty() { + tok := stack.Pop() + if tok.LP() { + out <- Token{ + Token: token.ILLEGAL, + Literal: "no closing parenthesis", + Pos: tok.Pos, + } + } else { + out <- tok + } + } + close(out) + }() + for tok := range in { + switch { + case tok.Token == token.ILLEGAL: + return + case tok.IsNumber(): + out <- tok + case tok.IsFunc(): + stack.Push(tok) + case tok.IsSeparator(): + for { + if stack.Empty() { + out <- Token{ + Token: token.ILLEGAL, + Literal: "no opening parenthesis", + Pos: tok.Pos, + } + return + } + if stack.Head().LP() { + break + } + out <- tok + } + case tok.IsOperator(): + op1 := e.operators[tok.Token] + for { + if stack.Empty() { + break + } + if stack.Head().IsOperator() { + op2, hasOp := e.operators[stack.Head().Token] + if !hasOp { + out <- Token{ + Token: token.ILLEGAL, + Literal: fmt.Sprintf("unknown operator: %s", stack.Head().Literal), + Pos: tok.Pos, + } + return + } + if op2.priority > op1.priority { + out <- stack.Pop() + continue + } else { + break + } + } else { + break + } + } + stack.Push(tok) + case tok.LP(): + stack.Push(tok) + case tok.RP(): + for { + if stack.Empty() { + out <- Token{ + Token: token.ILLEGAL, + Literal: "no opening parenthesis", + Pos: tok.Pos, + } + return + } + if stack.Head().LP() { + break + } + out <- tok + } + stack.Pop() + if stack.Head().IsFunc() { + out <- stack.Pop() + } + } + } + }() + + return out +} -- cgit v1.2.3