a4a3d05ddd3cdf98462bbc3116bc1e464ca38538
- Author
- TheEdgeOfRage <git@theedgeofrage.com>
- Committer
- TheEdgeOfRage <git@theedgeofrage.com>
- Date
Message
Diff
This diff is truncated to protect this page.
1diff --git a/rpn/lexer.go b/rpn/lexer.go
2index 1a01c15ec9fb20071821a45958e6f622e43637c5..6dbcc8833d634c0136618640419ec4f3cf41a0ee 100644
3--- a/rpn/lexer.go
4+++ b/rpn/lexer.go
5@@ -11,7 +11,7 @@ type Lexer struct {
6 input *Input
7 }
8
9-func (l *Lexer) parseNumber() (float64, error) {
10+func (l *Lexer) parseNumber(negative bool) (*Token, error) {
11 numStr := ""
12 char := l.input.NextChar()
13 for {
14@@ -25,10 +25,14 @@ func (l *Lexer) parseNumber() (float64, error) {
15
16 num, err := strconv.ParseFloat(numStr, 64)
17 if err != nil {
18- return 0, err
19+ return nil, err
20+ }
21+ if negative {
22+ numStr = "-" + numStr
23+ num = -num
24 }
25
26- return num, nil
27+ return &Token{number, 0, num, numStr}, nil
28 }
29
30 func (l *Lexer) parseWord() (*Token, error) {
31@@ -45,25 +49,25 @@ func (l *Lexer) parseWord() (*Token, error) {
32
33 switch word {
34 case "sqrt":
35- return &Token{unaryOp, sqrt, 0}, nil
36+ return &Token{unaryOp, sqrt, 0, word}, nil
37 case "dec":
38- return &Token{dec, 0, 0}, nil
39+ return &Token{dec, 0, 0, word}, nil
40 case "bin":
41- return &Token{bin, 0, 0}, nil
42+ return &Token{bin, 0, 0, word}, nil
43 case "hex":
44- return &Token{hex, 0, 0}, nil
45+ return &Token{hex, 0, 0, word}, nil
46 case "pi":
47- return &Token{number, 0, math.Pi}, nil
48+ return &Token{number, 0, math.Pi, word}, nil
49 case "pop":
50- return &Token{pop, 0, 0}, nil
51+ return &Token{pop, 0, 0, word}, nil
52 case "swap":
53- return &Token{swap, 0, 0}, nil
54+ return &Token{swap, 0, 0, word}, nil
55 case "clr":
56- return &Token{clr, 0, 0}, nil
57+ return &Token{clr, 0, 0, word}, nil
58 case "help":
59- return &Token{help, 0, 0}, nil
60+ return &Token{help, 0, 0, word}, nil
61 case "exit":
62- return &Token{exit, 0, 0}, nil
63+ return &Token{exit, 0, 0, word}, nil
64 default:
65 return nil, fmt.Errorf("Unknown input: %s", word)
66 }
67@@ -71,7 +75,6 @@ func (l *Lexer) parseWord() (*Token, error) {
68
69 func (l *Lexer) Parse(input string) ([]*Token, error) {
70 var err error
71- var num float64
72 var token *Token
73 l.input = NewInput(input)
74 tokens := []*Token{}
75@@ -84,30 +87,29 @@ func (l *Lexer) Parse(input string) ([]*Token, error) {
76 switch char {
77 case '+':
78 l.input.Eat()
79- token = &Token{binaryOp, plus, 0}
80+ token = &Token{binaryOp, plus, 0, string(char)}
81 case '-':
82 char = l.input.Eat()
83 if unicode.IsNumber(char) {
84- num, err = l.parseNumber()
85- token = &Token{number, 0, -num}
86+ token, err = l.parseNumber(true)
87 if err != nil {
88 return nil, err
89 }
90 } else {
91- token = &Token{binaryOp, minus, 0}
92+ token = &Token{binaryOp, minus, 0, string(char)}
93 }
94 case '*':
95 l.input.Eat()
96- token = &Token{binaryOp, multiply, 0}
97+ token = &Token{binaryOp, multiply, 0, string(char)}
98 case '/':
99 l.input.Eat()
100- token = &Token{binaryOp, divide, 0}
101+ token = &Token{binaryOp, divide, 0, string(char)}
102 case '%':
103 l.input.Eat()
104- token = &Token{binaryOp, mod, 0}
105diff --git a/rpn/rpn.go b/rpn/rpn.go
106index 558c8d5f6db0d706fb8df65062410019b1a0e004..0b5620378105ac6595ecfc55de7eb7884b0e244c 100644
107--- a/rpn/rpn.go
108+++ b/rpn/rpn.go
109@@ -1,12 +1,10 @@
110 package rpn
111
112 import (
113- "errors"
114+ "fmt"
115 "math"
116 )
117
118-var ErrExit = errors.New("exit")
119-
120 type RPN struct {
121 stack *Stack
122 lexer *Lexer
123@@ -62,10 +60,15 @@ func (r *RPN) Eval(input string) error {
124 if a == 0 {
125 r.stack.Push(b)
126 r.stack.Push(a)
127- return errors.New("can't divide by zero")
128+ return fmt.Errorf("Can't divide by zero")
129 }
130 r.stack.Push(b / a)
131 case mod:
132+ if a == 0 {
133+ r.stack.Push(b)
134+ r.stack.Push(a)
135+ return fmt.Errorf("Can't divide by zero")
136+ }
137 r.stack.Push(float64(int64(b) % int64(a)))
138 case power:
139 r.stack.Push(math.Pow(b, a))
140@@ -94,9 +97,9 @@ func (r *RPN) Eval(input string) error {
141 case help:
142 printHelp()
143 case exit:
144- return ErrExit
145+ return fmt.Errorf("exit")
146 default:
147- return errors.New("Unknown operation")
148+ return fmt.Errorf("Operation not implemented: %s", token.Original)
149 }
150 }
151
152diff --git a/rpn/stack.go b/rpn/stack.go
153index 318334905bf475a5590168b26de4f2ca8faffe62..c937c14aaf6102229ae91a807d5ae80e69c5adc7 100644
154--- a/rpn/stack.go
155+++ b/rpn/stack.go
156@@ -1,15 +1,11 @@
157 package rpn
158
159 import (
160- "errors"
161 "fmt"
162 "math"
163 )
164
165-var (
166- ErrStackEmpty = errors.New("stack is empty")
167- ErrNotEnoughValues = errors.New("not enough values on stack")
168-)
169+var ErrNotEnoughValuesTmpl = "Need at least %d values on the stack to perform this operation"
170
171 type Stack struct {
172 values []float64
173@@ -22,7 +18,7 @@ func (s *Stack) Push(value float64) {
174 func (s *Stack) Pop() (float64, error) {
175 count := s.Len()
176 if count == 0 {
177- return 0, ErrStackEmpty
178+ return 0, fmt.Errorf(ErrNotEnoughValuesTmpl, 1)
179 }
180 value := s.values[count-1]
181 s.values = s.values[:count-1]
182@@ -32,7 +28,7 @@ func (s *Stack) Pop() (float64, error) {
183 func (s *Stack) Pop2() (float64, float64, error) {
184 count := s.Len()
185 if count < 2 {
186- return 0, 0, ErrNotEnoughValues
187+ return 0, 0, fmt.Errorf(ErrNotEnoughValuesTmpl, 2)
188 }
189 a := s.values[count-1]
190 b := s.values[count-2]
191@@ -47,7 +43,7 @@ func (s *Stack) Len() int {
192 func (s *Stack) Swap() error {
193 count := s.Len()
194 if count < 2 {
195- return ErrNotEnoughValues
196+ return fmt.Errorf(ErrNotEnoughValuesTmpl, 2)
197 }
198 a := s.values[count-1]
199 b := s.values[count-2]
200diff --git a/rpn/token.go b/rpn/token.go
201index 1d0623ca4115f20a14a6997c3440eef3c198ad93..d6d899ff68ce4eab52b11e8c5772b8f91925c542 100644
202--- a/rpn/token.go
203+++ b/rpn/token.go
204@@ -32,4 +32,5 @@ type Token struct {
205 Type TokenType
206 Operator Operator
207 Value float64
208+ Original string
209 }