diff options
| author | Sam Anthony <sam@samanthony.xyz> | 2023-07-28 20:46:24 -0230 |
|---|---|---|
| committer | Sam Anthony <sam@samanthony.xyz> | 2023-07-28 20:46:24 -0230 |
| commit | 3516ab494570f077df967bfe1222acc0dfcdf5da (patch) | |
| tree | 4464b0c8e5b93e3ba62b4be3e2bd4c92b0cad1dd /calculator.go | |
| parent | 04ba853e7b9ad245865b6e9b4387d2efc144fc72 (diff) | |
| download | pfc-3516ab494570f077df967bfe1222acc0dfcdf5da.zip | |
arithmetic operators
Diffstat (limited to 'calculator.go')
| -rw-r--r-- | calculator.go | 62 |
1 files changed, 54 insertions, 8 deletions
diff --git a/calculator.go b/calculator.go index 08193b4..d2371b7 100644 --- a/calculator.go +++ b/calculator.go @@ -1,6 +1,9 @@ package main -import "strconv" +import ( + "fmt" + "strconv" +) type Stack []float64 @@ -9,18 +12,61 @@ type Calculator struct { buf string } -// add performs addition when the user inputs the '+' operator. -func (c *Calculator) add() { +// performOp performs the specified arithmetic operation and returns nil or +// OpError if op is not a valid operator. +func (c *Calculator) performOp(op byte) error { if len(c.stack) < 1 { - return + return nil } + + fn, err := parseOp(op) + if err != nil { + return err + } + if con := parseConstant(c.buf); con != nil { - c.stack[len(c.stack)-1] += *con - } else if f, err := strconv.ParseFloat(c.buf, 64); err == nil { - c.stack[len(c.stack)-1] += f + fn(&c.stack[len(c.stack)-1], *con) + } else if fl, err := strconv.ParseFloat(c.buf, 64); err == nil { + fn(&c.stack[len(c.stack)-1], fl) } else if len(c.stack) > 1 { - c.stack[len(c.stack)-2] += c.stack[len(c.stack)-1] + fn(&c.stack[len(c.stack)-2], c.stack[len(c.stack)-1]) c.stack = c.stack[:len(c.stack)-1] } c.buf = "" + return nil +} + +// parseOp returns a closure that performs the specified arithmetic operation, +// or OpError if op is not a valid operator. +func parseOp(op byte) (func(lhs *float64, rhs float64), error) { + switch op { + case '+': + return func(lhs *float64, rhs float64) { *lhs += rhs }, nil + case '-': + return func(lhs *float64, rhs float64) { *lhs -= rhs }, nil + case '*': + return func(lhs *float64, rhs float64) { *lhs *= rhs }, nil + case '/': + return func(lhs *float64, rhs float64) { + if rhs != 0 { + *lhs /= rhs + } + }, nil + case '%': + return func(lhs *float64, rhs float64) { + if rhs != 0 { + *lhs = float64(int64(*lhs) % int64(rhs)) + } + }, nil + } + return nil, OpError{op} +} + +// OpError records an invalid arithmetic operator. +type OpError struct { + c byte +} + +func (e OpError) Error() string { + return fmt.Sprintf("invalid operator: %c", e.c) } |