Fixes #32 : Ensure keys are correctly parsed
diff --git a/lexer.go b/lexer.go index 001049d..41b8af7 100644 --- a/lexer.go +++ b/lexer.go
@@ -138,7 +138,7 @@ return l.lexRvalue } - if isKeyChar(next) { + if isKeyStartChar(next) { return l.lexKey } @@ -250,7 +250,10 @@ func (l *tomlLexer) lexKey() tomlLexStateFn { l.ignore() - for isKeyChar(l.next()) { + for r := l.next(); isKeyChar(r); r = l.next() { + if (r == '#') { + return l.errorf("keys cannot contain # character") + } } l.backup() l.emit(tokenKey)
diff --git a/lexer_test.go b/lexer_test.go index 019a496..176abf8 100644 --- a/lexer_test.go +++ b/lexer_test.go
@@ -118,19 +118,16 @@ func TestKeyWithSharpAndEqual(t *testing.T) { testFlow(t, "key#name = 5", []token{ - token{Position{1, 1}, tokenKey, "key#name"}, - token{Position{1, 10}, tokenEqual, "="}, - token{Position{1, 12}, tokenInteger, "5"}, - token{Position{1, 13}, tokenEOF, ""}, + token{Position{1, 1}, tokenError, "keys cannot contain # character"}, }) } func TestKeyWithSymbolsAndEqual(t *testing.T) { - testFlow(t, "~!@#$^&*()_+-`1234567890[]\\|/?><.,;:' = 5", []token{ - token{Position{1, 1}, tokenKey, "~!@#$^&*()_+-`1234567890[]\\|/?><.,;:'"}, - token{Position{1, 39}, tokenEqual, "="}, - token{Position{1, 41}, tokenInteger, "5"}, - token{Position{1, 42}, tokenEOF, ""}, + testFlow(t, "~!@$^&*()_+-`1234567890[]\\|/?><.,;:' = 5", []token{ + token{Position{1, 1}, tokenKey, "~!@$^&*()_+-`1234567890[]\\|/?><.,;:'"}, + token{Position{1, 38}, tokenEqual, "="}, + token{Position{1, 40}, tokenInteger, "5"}, + token{Position{1, 41}, tokenEOF, ""}, }) }
diff --git a/parser_test.go b/parser_test.go index 238ca2f..136c795 100644 --- a/parser_test.go +++ b/parser_test.go
@@ -54,9 +54,9 @@ // NOTE: from the BurntSushi test suite // NOTE: this test is pure evil due to the embedded '.' func TestSpecialKV(t *testing.T) { - tree, err := Load("~!@#$^&*()_+-`1234567890[]\\|/?><.,;: = 1") + tree, err := Load("~!@$^&*()_+-`1234567890[]\\|/?><.,;: = 1") assertTree(t, tree, err, map[string]interface{}{ - "~!@#$^&*()_+-`1234567890[]\\|/?><.,;:": int64(1), + "~!@$^&*()_+-`1234567890[]\\|/?><.,;:": int64(1), }) }
diff --git a/token.go b/token.go index 22ad37a..6c0bcc6 100644 --- a/token.go +++ b/token.go
@@ -117,11 +117,16 @@ } func isKeyChar(r rune) bool { - // "Keys start with the first non-whitespace character and end with the last - // non-whitespace character before the equals sign." + // Keys start with the first character that isn't whitespace or [ and end + // with the last non-whitespace character before the equals sign. Keys + // cannot contain a # character." return !(isSpace(r) || r == '\r' || r == '\n' || r == eof || r == '=') } +func isKeyStartChar(r rune) bool { + return !(isSpace(r) || r == '\r' || r == '\n' || r == eof || r == '[') +} + func isDigit(r rune) bool { return unicode.IsNumber(r) }