Revised error formatting, fixed tests
diff --git a/parser.go b/parser.go index d02c42b..4d3927c 100644 --- a/parser.go +++ b/parser.go
@@ -20,6 +20,11 @@ type parserStateFn func(*parser) parserStateFn +// Formats and panics an error message based on a token +func (p *parser) raiseError(tok *token, msg string, args... interface{}) { + panic(tok.Pos() + ": " + fmt.Sprintf(msg, args...)) +} + func (p *parser) run() { for state := parseStart; state != nil; { state = state(p) @@ -42,10 +47,10 @@ func (p *parser) assume(typ tokenType) { tok := p.getToken() if tok == nil { - panic(fmt.Sprintf("%s: was expecting token %s, but token stream is empty", tok.Pos(), typ)) + p.raiseError(tok, "was expecting token %s, but token stream is empty", tok.typ) } if tok.typ != typ { - panic(fmt.Sprintf("%s: was expecting token %s, but got %s", tok.Pos(), typ, tok.typ)) + p.raiseError(tok, "was expecting token %s, but got %s", typ, tok.typ) } } @@ -80,7 +85,7 @@ case tokenEOF: return nil default: - panic(tok.Pos() + ": unexpected token") + p.raiseError(tok, "unexpected token") } return nil } @@ -89,7 +94,7 @@ p.getToken() // discard the [[ key := p.getToken() if key.typ != tokenKeyGroupArray { - panic(fmt.Sprintf("%s: unexpected token %s, was expecting a key group array", key.Pos(), key)) + p.raiseError(key, "unexpected token %s, was expecting a key group array", key) } // get or create group array element at the indicated part in the path @@ -101,7 +106,7 @@ } else if dest_tree.([]*TomlTree) != nil { array = dest_tree.([]*TomlTree) } else { - panic(fmt.Sprintf("%s: key %s is already assigned and not of type group array", key.Pos(), key)) + p.raiseError(key, "key %s is already assigned and not of type group array", key) } // add a new tree to the end of the group array @@ -121,11 +126,11 @@ p.getToken() // discard the [ key := p.getToken() if key.typ != tokenKeyGroup { - panic(fmt.Sprintf("%s: unexpected token %s, was expecting a key group", key.Pos(), key)) + p.raiseError(key, "unexpected token %s, was expecting a key group", key) } for _, item := range p.seenGroupKeys { if item == key.val { - panic(key.Pos() + ": duplicated tables") + p.raiseError(key, "duplicated tables") } } p.seenGroupKeys = append(p.seenGroupKeys, key.val) @@ -154,14 +159,14 @@ case *TomlTree: target_node = node default: - panic(fmt.Sprintf("%s: Unknown group type for path %v", key.Pos(), group_key)) + p.raiseError(key, "Unknown group type for path %s", 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("%s: the following key was defined twice: %s", key.Pos(), strings.Join(final_key, "."))) + p.raiseError(key, "the following key was defined twice: %s", strings.Join(final_key, ".")) } target_node.SetPath(local_key, value) return parseStart(p) @@ -170,7 +175,7 @@ func parseRvalue(p *parser) interface{} { tok := p.getToken() if tok == nil || tok.typ == tokenEOF { - panic(tok.Pos() + ": expecting a value") + p.raiseError(tok, "expecting a value") } switch tok.typ { @@ -183,28 +188,28 @@ case tokenInteger: val, err := strconv.ParseInt(tok.val, 10, 64) if err != nil { - panic(err) + p.raiseError(tok, "%s", err) } return val case tokenFloat: val, err := strconv.ParseFloat(tok.val, 64) if err != nil { - panic(err) + p.raiseError(tok, "%s", err) } return val case tokenDate: val, err := time.Parse(time.RFC3339, tok.val) if err != nil { - panic(err) + p.raiseError(tok, "%s", err) } return val case tokenLeftBracket: return parseArray(p) case tokenError: - panic(tok.val) + p.raiseError(tok, "%s", tok) } - panic(tok.Pos() + ": never reached") + p.raiseError(tok, "never reached") return nil } @@ -215,7 +220,7 @@ for { follow := p.peek() if follow == nil || follow.typ == tokenEOF { - panic(follow.Pos() + ": unterminated array") + p.raiseError(follow, "unterminated array") } if follow.typ == tokenRightBracket { p.getToken() @@ -226,15 +231,15 @@ arrayType = reflect.TypeOf(val) } if reflect.TypeOf(val) != arrayType { - panic(follow.Pos() + ": mixed types in array") + p.raiseError(follow, "mixed types in array") } array = append(array, val) follow = p.peek() if follow == nil { - panic(follow.Pos() + ": unterminated array") + p.raiseError(follow, "unterminated array") } if follow.typ != tokenRightBracket && follow.typ != tokenComma { - panic(follow.Pos() + ": missing comma") + p.raiseError(follow, "missing comma") } if follow.typ == tokenComma { p.getToken()
diff --git a/parser_test.go b/parser_test.go index 06510c0..b73fcce 100644 --- a/parser_test.go +++ b/parser_test.go
@@ -249,12 +249,12 @@ func TestFloatsWithoutLeadingZeros(t *testing.T) { _, err := Load("a = .42") - if err.Error() != "cannot start float with a dot" { + if err.Error() != "(1, 4): cannot start float with a dot" { t.Error("Bad error message:", err.Error()) } _, err = Load("a = -.42") - if err.Error() != "cannot start float with a dot" { + if err.Error() != "(1, 5): cannot start float with a dot" { t.Error("Bad error message:", err.Error()) } }