diff options
author | nirav <nirav@teisuu.com> | 2021-10-17 10:41:25 +0000 |
---|---|---|
committer | nirav <nirav@teisuu.com> | 2021-10-17 10:41:25 +0000 |
commit | aa51be44817e42871218eb2a341ec894ec7a24c5 (patch) | |
tree | 794473bd3417deb19e1d8b35101db0f54d2848a0 /scanner.go | |
download | dc-aa51be44817e42871218eb2a341ec894ec7a24c5.tar.gz dc-aa51be44817e42871218eb2a341ec894ec7a24c5.zip |
Initial commit
Diffstat (limited to 'scanner.go')
-rw-r--r-- | scanner.go | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/scanner.go b/scanner.go new file mode 100644 index 0000000..a07981d --- /dev/null +++ b/scanner.go @@ -0,0 +1,92 @@ +package main + +//go:generate stringer -type=Token +type Token int + +const ( + INVALID Token = iota + EOF + NUM + ADD + SUB + MUL + DIV + EXP +) + +type scanner struct { + c byte + i int + buf []byte +} + +func newScanner(s []byte) *scanner { + return &scanner{ + buf: s, + } +} + +func (s *scanner) read() bool { + if len(s.buf) <= s.i { + return false + } + s.c = s.buf[s.i] + s.i++ + return true +} + +func (s *scanner) unread() { + s.i-- + s.c = s.buf[s.i] +} + +// Pos returns the index of the next character +func (s *scanner) Pos() int { + return s.i +} + +func (s *scanner) Scan() (t Token, d []byte) { +read: + ok := s.read() + if !ok { + return EOF, []byte{} + } + switch s.c { + case '+': + return ADD, nil + case '-': + return SUB, nil + case '*': + return MUL, nil + case '/': + return DIV, nil + case '^': + return EXP, nil + case ' ', '\n', '\t': + goto read + default: + if (s.c >= '0' && s.c <= '9') { + s.unread() + return s.scanNumber(false) + } + if s.c == '-' { + return s.scanNumber(true) + } + } + return INVALID, []byte{s.c} +} + +func (s *scanner) scanNumber(neg bool) (t Token, d []byte) { + if neg { + d = append(d, '-') + } + for s.read() { + if (s.c >= '0' && s.c <= '9') { + d = append(d, s.c) + } else { + s.unread() + break + } + } + return NUM, d +} |