From 17e7453fff5e60763a1fab88038f1253790e34a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Janouch?= Date: Thu, 20 Oct 2016 01:47:07 +0200 Subject: [PATCH] Better error messages --- assembler.go | 31 +++++++++++++++++-------------- main.go | 27 ++++++++++----------------- 2 files changed, 27 insertions(+), 31 deletions(-) diff --git a/assembler.go b/assembler.go index 5221040..a366929 100644 --- a/assembler.go +++ b/assembler.go @@ -125,7 +125,7 @@ func (t *tokenizer) eat() (byte, error) { if c == '\n' { t.location.line++ - t.location.column = 0 + t.location.column = 1 } else { t.location.column++ } @@ -210,7 +210,7 @@ func (t *tokenizer) step() error { func tokenize(r io.Reader, tokens chan<- token) { t := tokenizer{ - location: location{line: 1, column: 0}, + location: location{line: 1, column: 1}, tokens: tokens, reader: bufio.NewReader(r), } @@ -218,8 +218,7 @@ func tokenize(r io.Reader, tokens chan<- token) { if err := t.step(); err == io.EOF { break } else if err != nil { - t.tokens <- token{t.location, fmt.Sprintf("line %d, column %d: %s", - t.location.line, t.location.column, err.Error()), 0, ERROR} + t.tokens <- token{t.location, err.Error(), 0, ERROR} break } } @@ -246,19 +245,23 @@ func (a *assembler) step() (bool, error) { return false, nil } - // TODO: add token location information to returned errors + mkerr := func(format string, a ...interface{}) error { + prefix := fmt.Sprintf("line %d, column %d: ", + token.location.line, token.location.column) + return errors.New(prefix + fmt.Sprintf(format, a...)) + } switch token.kind { case WORD: if _, dup := a.labels[token.value]; dup { - return false, fmt.Errorf("Duplicate label: %s", token.value) + return false, mkerr("duplicate label: %s", token.value) } a.labels[token.value] = len(a.output) if token, ok = <-a.tokens; !ok { - return false, errors.New("Unexpected end of file") + return false, mkerr("unexpected end of file") } if token.kind != INSTRUCTION { - return false, errors.New("Expected instruction name after label") + return false, mkerr("expected instruction name after label") } fallthrough case INSTRUCTION: @@ -288,17 +291,17 @@ func (a *assembler) step() (bool, error) { case !ok: case token.kind == NEWLINE: case token.kind == ERROR: - return false, errors.New(token.value) + return false, mkerr("%s", token.value) default: - return false, errors.New("Expected end of line") + return false, mkerr("expected end of line") } } case NEWLINE: // Ignore empty lines case NUMBER: - return false, errors.New("Unexpected number") + return false, mkerr("unexpected number") case ERROR: - return false, errors.New(token.value) + return false, mkerr("%s", token.value) } return true, nil } @@ -318,7 +321,7 @@ func Assemble(r io.Reader) (code []int16, err error) { code = make([]int16, 100) for i, x := range a.output { if i >= len(code) { - return nil, errors.New("Program too long") + return nil, errors.New("program too long") } n := x.id switch { @@ -327,7 +330,7 @@ func Assemble(r io.Reader) (code []int16, err error) { case len(x.target) != 0: // Resolve targets to code locations if resolved, ok := a.labels[x.target]; !ok { - return nil, errors.New("Unknown label") + return nil, errors.New("unknown label") } else { n += resolved } diff --git a/main.go b/main.go index 6fbd3f9..d08e114 100644 --- a/main.go +++ b/main.go @@ -7,22 +7,15 @@ import ( func main() { if len(os.Args) != 2 { - fmt.Printf("usage: %s file", os.Args[0]) - os.Exit(1) - } - file, err := os.Open(os.Args[1]) - if err != nil { - fmt.Printf("Cannot open file: %s", err) - os.Exit(1) - } - code, err := Assemble(file) - if err != nil { - fmt.Printf("Assembly failed: %s", err) - os.Exit(1) - } - err = Run(code) - if err != nil { - fmt.Printf("Runtime error: %s", err) - os.Exit(1) + fmt.Printf("usage: %s file\n", os.Args[0]) + } else if file, err := os.Open(os.Args[1]); err != nil { + fmt.Printf("Cannot open file: %s\n", err) + } else if code, err := Assemble(file); err != nil { + fmt.Printf("Assembly failed: %s\n", err) + } else if err = Run(code); err != nil { + fmt.Printf("Runtime error: %s\n", err) + } else { + os.Exit(0) } + os.Exit(1) }