aboutsummaryrefslogtreecommitdiffstats
path: root/calc.go
diff options
context:
space:
mode:
authorSam Anthony <sam@samanthony.xyz>2023-10-01 20:02:22 -0400
committerSam Anthony <sam@samanthony.xyz>2023-10-01 20:02:22 -0400
commit4f9e220638ea62443db25d252c4e12ede2c7f9c5 (patch)
treeed40edf989f2907e58e3d5fd0fd0a85cde919386 /calc.go
parent6e3073f5e835b19b39d0853dece386067218b1ce (diff)
downloadpfc-4f9e220638ea62443db25d252c4e12ede2c7f9c5.zip
error handling and tidying
Diffstat (limited to 'calc.go')
-rw-r--r--calc.go83
1 files changed, 58 insertions, 25 deletions
diff --git a/calc.go b/calc.go
index e6897fe..1edfc9e 100644
--- a/calc.go
+++ b/calc.go
@@ -26,50 +26,83 @@ type Calculator struct {
// the buffer is empty this simply pops from the stack. If the stack is empty,
// this simply pushes to the stack.
func (c *Calculator) swap() {
- st := c.stack.pop()
- if con := parseConstant(c.buf); con != nil {
- c.stack.push(*con)
- } else if f, err := strconv.ParseFloat(c.buf, 64); err == nil {
- c.stack.push(f)
+ stackVal, err := c.stack.pop()
+ stackIsEmpty := err != nil
+
+ if v, err := c.parseBuffer(); err == nil {
+ c.stack.push(v)
}
- if st != nil {
- c.buf = printNum(*st)
- } else {
+
+ if stackIsEmpty {
c.buf = ""
+ } else {
+ c.buf = printNum(stackVal)
}
}
// negate negates the number in the buffer, if any; or the bottom number on the
// stack, if any.
func (c *Calculator) negate() {
- if con := parseConstant(c.buf); con != nil {
- c.buf = printNum(-*con)
- } else if f, err := strconv.ParseFloat(c.buf, 64); err == nil {
- c.buf = printNum(-f)
+ if v, err := c.parseBuffer(); err == nil {
+ c.buf = printNum(-v)
} else if len(c.buf) == 0 && len(c.stack) > 0 {
c.stack[len(c.stack)-1] = -c.stack[len(c.stack)-1]
}
}
-// 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 nil
+// performOp performs the specified arithmetic operation.
+func (c *Calculator) performOperation(operator byte) error {
+ fn, err := parseOperator(operator)
+ if err != nil {
+ return err
}
- fn, err := parseOp(op)
+ lhs, rhs, err := c.operands()
if err != nil {
return err
}
- if con := parseConstant(c.buf); con != nil {
- 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 {
- fn(&c.stack[len(c.stack)-2], *c.stack.pop())
- }
+ c.stack.push(fn(lhs, rhs))
c.buf = ""
return nil
}
+
+// operands returns the operands of an arithmetic operation.
+func (c *Calculator) operands() (lhs, rhs float64, err error) {
+ if buf, err := c.parseBuffer(); err == nil {
+ rhs = buf
+ lhs, err = c.stack.pop()
+ return lhs, rhs, nil
+ } else if stk, err := c.stack.pop(); err == nil {
+ rhs = stk
+ if lhs, err = c.stack.pop(); err == nil {
+ return lhs, rhs, nil
+ }
+ c.stack.push(rhs)
+ } // not enough operands
+ return 0, 0, OperandErr{}
+}
+
+// parseBuffer returns the numerical value of the contents of the buffer.
+func (c Calculator) parseBuffer() (float64, error) {
+ if con, err := parseConstant(c.buf); err == nil {
+ return con, nil
+ } else if fl, err := strconv.ParseFloat(c.buf, 64); err == nil {
+ return fl, nil
+ }
+ return 0, InvalidBufferContentErr{c.buf}
+}
+
+type InvalidBufferContentErr struct {
+ buf string
+}
+
+func (e InvalidBufferContentErr) Error() string {
+ return "invalid buffer contents: " + e.buf
+}
+
+type OperandErr struct{}
+
+func (e OperandErr) Error() string {
+ return "not enough operands"
+}