Better error messages
This commit is contained in:
parent
b247f025d5
commit
17e7453fff
31
assembler.go
31
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
|
||||
}
|
||||
|
|
27
main.go
27
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)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue