func TestStack(t *testing.T) { count := 1 var aStack stack.Stack assertTrue(t, aStack.Len() == 0, "expected empty Stack", count) // 1 count++ assertTrue(t, aStack.Cap() == 0, "expected empty Stack", count) // 2 count++ assertTrue(t, aStack.IsEmpty(), "expected empty Stack", count) // 3 count++ value, err := aStack.Pop() assertTrue(t, value == nil, "expected nil value", count) // 4 count++ assertTrue(t, err != nil, "expected error", count) // 5 count++ value1, err := aStack.Top() assertTrue(t, value1 == nil, "expected nil value", count) // 6 count++ assertTrue(t, err != nil, "expected error", count) // 7 count++ aStack.Push(1) aStack.Push(2) aStack.Push("three") assertTrue(t, aStack.Len() == 3, "expected nonempty Stack", count) // 8 count++ assertTrue(t, aStack.IsEmpty() == false, "expected nonempty Stack", count) // 9 count++ value2, err := aStack.Pop() assertEqualString(t, value2.(string), "three", "unexpected text", count) // 10 count++ assertTrue(t, err == nil, "no error expected", count) // 11 count++ value3, err := aStack.Top() assertTrue(t, value3 == 2, "unexpected number", count) // 12 count++ assertTrue(t, err == nil, "no error expected", count) // 13 count++ aStack.Pop() assertTrue(t, aStack.Len() == 1, "expected nonempty Stack", count) //14 count++ assertTrue(t, aStack.IsEmpty() == false, "expected nonempty Stack", count) // 15 count++ value4, err := aStack.Pop() assertTrue(t, value4 == 1, "unexpected number", count) // 16 count++ assertTrue(t, err == nil, "no error expected", count) // 17 count++ assertTrue(t, aStack.Len() == 0, "expected empty Stack", count) // 18 count++ assertTrue(t, aStack.IsEmpty(), "expected empty Stack", count) // 19 count++ }
// convert2postfix converts an infix expression to postfix func convert2postfix(tokens []string) []string { var stack stack.Stack var result []string for _, token := range tokens { if isOperator(token) { OPERATOR: for { top, err := stack.Top() if err == nil && top != "(" { if opGTE(top.(string), token) { pop, _ := stack.Pop() result = append(result, pop.(string)) } else { break OPERATOR } } break OPERATOR } stack.Push(token) } else if token == "(" { stack.Push(token) } else if token == ")" { PAREN: for { top, err := stack.Top() if err == nil && top != "(" { pop, _ := stack.Pop() result = append(result, pop.(string)) } else { stack.Pop() // pop off "(" break PAREN } } } else if isOperand(token) { result = append(result, token) } } for !stack.IsEmpty() { pop, _ := stack.Pop() result = append(result, pop.(string)) } return result }
// evaluatePostfix takes a postfix expression and evaluates it func evaluatePostfix(postfix []string) (*big.Rat, error) { var stack stack.Stack result := new(big.Rat) // note: a new(big.Rat) has value "0/1" ie zero for _, token := range postfix { if isOperand(token) { bigrat := new(big.Rat) if _, err := fmt.Sscan(token, bigrat); err != nil { return nil, fmt.Errorf("unable to scan %s", token) } stack.Push(bigrat) } else if isOperator(token) { op2, err2 := stack.Pop() if err2 != nil { return nil, err2 } var op1 interface{} if token != "@" { var err1 error if op1, err1 = stack.Pop(); err1 != nil { return nil, err1 } } dummy := new(big.Rat) switch token { case "**": float1 := BigratToFloat(op1.(*big.Rat)) float2 := BigratToFloat(op2.(*big.Rat)) float_result := math.Pow(float1, float2) stack.Push(FloatToBigrat(float_result)) case "*": result := dummy.Mul(op1.(*big.Rat), op2.(*big.Rat)) stack.Push(result) case "/": result := dummy.Quo(op1.(*big.Rat), op2.(*big.Rat)) stack.Push(result) case "+": result = dummy.Add(op1.(*big.Rat), op2.(*big.Rat)) stack.Push(result) case "-": result = dummy.Sub(op1.(*big.Rat), op2.(*big.Rat)) stack.Push(result) case "<": if op1.(*big.Rat).Cmp(op2.(*big.Rat)) <= -1 { stack.Push(big.NewRat(1, 1)) } else { stack.Push(new(big.Rat)) } case ">": if op1.(*big.Rat).Cmp(op2.(*big.Rat)) >= 1 { stack.Push(big.NewRat(1, 1)) } else { stack.Push(new(big.Rat)) } case "@": result := dummy.Mul(big.NewRat(-1, 1), op2.(*big.Rat)) stack.Push(result) } } else { return nil, fmt.Errorf("unknown token %v", token) } } retval, err := stack.Pop() if err != nil { return nil, err } return retval.(*big.Rat), nil }