From ed154369ee1e9de3b43ce6a5be77d42b873175c7 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Sat, 22 Sep 2018 20:25:41 +0200 Subject: refactor lexer --- go/forth/forth.go | 83 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 32 deletions(-) diff --git a/go/forth/forth.go b/go/forth/forth.go index 8675941..9059168 100644 --- a/go/forth/forth.go +++ b/go/forth/forth.go @@ -2,7 +2,7 @@ package forth import ( "errors" - "log" + "io" "strconv" "strings" ) @@ -35,11 +35,11 @@ func (s *stack) values() []int { } func pop2(s stacker) (int, int, error) { - tos, err := s.pop() + tos, err := s.pop() // top on stack if err != nil { return 0, 0, err } - nos, err := s.pop() + nos, err := s.pop() // next on stack if err != nil { return 0, 0, err } @@ -141,41 +141,42 @@ func number(word string) (int, bool) { return n, err == nil } -func index(s []string, r string) int { - for i, v := range s { - if v == r { - return i - } +func colon(dict dictionary, l *lexer) error { + name, err := l.Next() + if err != nil { + return err + } + if _, ok := number(name); ok { + return errors.New("name cannot be a number") + } + w, err := compile(dict, l) + if err != nil { + return err } - return -1 + dict.add(name, w...) + return nil } -func compile(dict dictionary, s []string) ([]func(stacker) error, error) { - log.Println("compile", s) +func compile(dict dictionary, l *lexer) ([]func(stacker) error, error) { var words []func(stacker) error - for i := 0; i < len(s); i++ { - v := s[i] - // lookup dictionary first - if w, ok := dict.find(v); ok { - words = append(words, w...) - continue + for { + v, err := l.Next() + if err == io.EOF { + return words, nil } + // colon operator if v == ":" { - next := index(s[i+1:], ";") - if next == -1 { - return nil, errors.New("unterminated colon operator") - } - name := s[i+1] - if _, ok := number(name); ok { - return nil, errors.New("name cannot be a number") - } - w, err := compile(dict, s[i+2:i+next+1]) - if err != nil { + if err := colon(dict, l); err != nil { return nil, err } - log.Println("add", name) - dict.add(name, w...) - i += next + 1 + continue + } + if v == ";" { + return words, nil + } + // lookup dictionary first + if w, ok := dict.find(v); ok { + words = append(words, w...) continue } // try to parse literal @@ -185,7 +186,24 @@ func compile(dict dictionary, s []string) ([]func(stacker) error, error) { } return nil, errors.New("unknown word") } - return words, nil +} + +type lexer struct { + fields []string + pos int +} + +func NewLexer(line string) *lexer { + return &lexer{fields: strings.Fields(line)} +} + +func (l *lexer) Next() (string, error) { + if l.pos >= len(l.fields) { + return "", io.EOF + } + s := l.fields[l.pos] + l.pos++ + return s, nil } func Forth(v []string) ([]int, error) { @@ -202,7 +220,8 @@ func Forth(v []string) ([]int, error) { var words []func(stacker) error for _, line := range v { - w, err := compile(dict, strings.Split(line, " ")) + l := NewLexer(line) + w, err := compile(dict, l) if err != nil { return nil, err } -- cgit v1.2.3