package main import ( "fmt" "os" "gitty.informatik.hs-mannheim.de/steger/pr3-code/go/04-design-pattern/patterns" ) type ConstValueCalculator float64 func NewConstValueCalculator(valueString string) *ConstValueCalculator { var value float64 if _, err := fmt.Sscanf(valueString, "%f", &value); err != nil { return nil } cvc := ConstValueCalculator(value) return &cvc } func (c ConstValueCalculator) Calc() float64 { return float64(c) } /* parses the expression and builds a binary calculation tree. Returns the tree, the remaining expression after parsing, and an error example Input: 1. [2] => 2 2. [+ 2 3] => 5 3. [* 2 3] => 6 4. [+ * 2 3 4] == [+ 6 4] => 10 */ func buildBinaryCalculationTree(expression []string) (patterns.Calculator, []string, error) { if len(expression) == 0 { return nil, nil, fmt.Errorf("empty argument") } //1. attempt: try a composite calculator from an operator composite := patterns.NewCompositeCalculatorFromOperator(expression[0]) if composite != nil { expression = expression[1:] for i := 0; i < 2; i++ { arg, remaining, err := buildBinaryCalculationTree(expression) if err != nil { return nil, nil, err } expression = remaining composite.Add(arg) } return composite, expression, nil } //2. attempt: try a const value calculator from a value constValue := NewConstValueCalculator(expression[0]) if constValue != nil { return constValue, expression[1:], nil } //3. failure, no valid symbol return nil, nil, fmt.Errorf("invalid symbol: %s", expression[0]) } // run for example with go run . + "*" 2 2 4 // note the "*" because * would otherwise expand func main() { calc, remainingArgs, err := buildBinaryCalculationTree(os.Args[1:]) if err != nil { fmt.Println(err) return } if len(remainingArgs) != 0 { fmt.Println("Invalid Input - remaining arguments", remainingArgs) return } fmt.Println(calc.Calc()) }