Revised error reporting
diff --git a/lexer.go b/lexer.go index ce0f2f6..e668962 100644 --- a/lexer.go +++ b/lexer.go
@@ -64,6 +64,10 @@ return fmt.Sprintf("%q", i.val) } +func (i token) Pos() string { + return fmt.Sprintf("(%d, %d)", i.line + 1, i.col + 1) +} + func isSpace(r rune) bool { return r == ' ' || r == '\t' }
diff --git a/parser.go b/parser.go index b9a3f5f..d02c42b 100644 --- a/parser.go +++ b/parser.go
@@ -42,10 +42,10 @@ func (p *parser) assume(typ tokenType) { tok := p.getToken() if tok == nil { - panic(fmt.Sprintf("was expecting token %s, but token stream is empty", typ)) + panic(fmt.Sprintf("%s: was expecting token %s, but token stream is empty", tok.Pos(), typ)) } if tok.typ != typ { - panic(fmt.Sprintf("was expecting token %s, but got %s", typ, tok.typ)) + panic(fmt.Sprintf("%s: was expecting token %s, but got %s", tok.Pos(), typ, tok.typ)) } } @@ -80,7 +80,7 @@ case tokenEOF: return nil default: - panic("unexpected token") + panic(tok.Pos() + ": unexpected token") } return nil } @@ -89,7 +89,7 @@ p.getToken() // discard the [[ key := p.getToken() if key.typ != tokenKeyGroupArray { - panic(fmt.Sprintf("unexpected token %s, was expecting a key group array", key)) + panic(fmt.Sprintf("%s: unexpected token %s, was expecting a key group array", key.Pos(), key)) } // get or create group array element at the indicated part in the path @@ -101,7 +101,7 @@ } else if dest_tree.([]*TomlTree) != nil { array = dest_tree.([]*TomlTree) } else { - panic(fmt.Sprintf("key %s is already assigned and not of type group array", key)) + panic(fmt.Sprintf("%s: key %s is already assigned and not of type group array", key.Pos(), key)) } // add a new tree to the end of the group array @@ -121,11 +121,11 @@ p.getToken() // discard the [ key := p.getToken() if key.typ != tokenKeyGroup { - panic(fmt.Sprintf("unexpected token %s, was expecting a key group", key)) + panic(fmt.Sprintf("%s: unexpected token %s, was expecting a key group", key.Pos(), key)) } for _, item := range p.seenGroupKeys { if item == key.val { - panic("duplicated tables") + panic(key.Pos() + ": duplicated tables") } } p.seenGroupKeys = append(p.seenGroupKeys, key.val) @@ -154,14 +154,14 @@ case *TomlTree: target_node = node default: - panic(fmt.Sprintf("Unknown group type for path %v", group_key)) + panic(fmt.Sprintf("%s: Unknown group type for path %v", key.Pos(), group_key)) } // assign value to the found group local_key := []string{key.val} final_key := append(group_key, key.val) if target_node.GetPath(local_key) != nil { - panic(fmt.Sprintf("the following key was defined twice: %s", strings.Join(final_key, "."))) + panic(fmt.Sprintf("%s: the following key was defined twice: %s", key.Pos(), strings.Join(final_key, "."))) } target_node.SetPath(local_key, value) return parseStart(p) @@ -170,7 +170,7 @@ func parseRvalue(p *parser) interface{} { tok := p.getToken() if tok == nil || tok.typ == tokenEOF { - panic("expecting a value") + panic(tok.Pos() + ": expecting a value") } switch tok.typ { @@ -204,7 +204,7 @@ panic(tok.val) } - panic("never reached") + panic(tok.Pos() + ": never reached") return nil } @@ -215,7 +215,7 @@ for { follow := p.peek() if follow == nil || follow.typ == tokenEOF { - panic("unterminated array") + panic(follow.Pos() + ": unterminated array") } if follow.typ == tokenRightBracket { p.getToken() @@ -226,15 +226,15 @@ arrayType = reflect.TypeOf(val) } if reflect.TypeOf(val) != arrayType { - panic("mixed types in array") + panic(follow.Pos() + ": mixed types in array") } array = append(array, val) follow = p.peek() if follow == nil { - panic("unterminated array") + panic(follow.Pos() + ": unterminated array") } if follow.typ != tokenRightBracket && follow.typ != tokenComma { - panic("missing comma") + panic(follow.Pos() + ": missing comma") } if follow.typ == tokenComma { p.getToken()
diff --git a/parser_test.go b/parser_test.go index dcdd3d1..06510c0 100644 --- a/parser_test.go +++ b/parser_test.go
@@ -160,12 +160,12 @@ func TestArrayMixedTypes(t *testing.T) { _, err := Load("a = [42, 16.0]") - if err.Error() != "mixed types in array" { + if err.Error() != "(1, 10): mixed types in array" { t.Error("Bad error message:", err.Error()) } _, err = Load("a = [42, \"hello\"]") - if err.Error() != "mixed types in array" { + if err.Error() != "(1, 11): mixed types in array" { t.Error("Bad error message:", err.Error()) } } @@ -179,14 +179,14 @@ func TestMissingValue(t *testing.T) { _, err := Load("a = ") - if err.Error() != "expecting a value" { + if err.Error() != "(1, 4): expecting a value" { t.Error("Bad error message:", err.Error()) } } func TestUnterminatedArray(t *testing.T) { _, err := Load("a = [1,") - if err.Error() != "unterminated array" { + if err.Error() != "(1, 8): unterminated array" { t.Error("Bad error message:", err.Error()) } } @@ -214,14 +214,14 @@ func TestDuplicateGroups(t *testing.T) { _, err := Load("[foo]\na=2\n[foo]b=3") - if err.Error() != "duplicated tables" { + if err.Error() != "(3, 2): duplicated tables" { t.Error("Bad error message:", err.Error()) } } func TestDuplicateKeys(t *testing.T) { _, err := Load("foo = 2\nfoo = 3") - if err.Error() != "the following key was defined twice: foo" { + if err.Error() != "(2, 1): the following key was defined twice: foo" { t.Error("Bad error message:", err.Error()) } }