Better error messages

This commit is contained in:
Přemysl Eric Janouch 2016-10-20 01:47:07 +02:00
parent b247f025d5
commit 17e7453fff
Signed by: p
GPG Key ID: B715679E3A361BE6
2 changed files with 27 additions and 31 deletions

View File

@ -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
}

25
main.go
View File

@ -7,22 +7,15 @@ import (
func main() {
if len(os.Args) != 2 {
fmt.Printf("usage: %s file", os.Args[0])
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)
}
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)
}
}