Bits of code cleanup, no functional changes.

This commit is contained in:
Maurice Makaay 2019-06-28 08:23:43 +00:00
parent b1484cb690
commit febe1ff568
10 changed files with 44 additions and 46 deletions

View File

@ -65,8 +65,8 @@ const (
// TypeFloat identifies a floating point number (10.1234, 143E-12, 43.28377e+4, +inf, -inf, nan). // TypeFloat identifies a floating point number (10.1234, 143E-12, 43.28377e+4, +inf, -inf, nan).
TypeFloat ValueType = "float" TypeFloat ValueType = "float"
// TypeBoolean identifies a boolean value (true or false). // TypeBool identifies a boolean value (true or false).
TypeBoolean ValueType = "boolean" TypeBool ValueType = "bool"
// TypeOffsetDateTime identifies a date/time value, including timezone info (2019-06-18 10:32:15.173645362+0200). // TypeOffsetDateTime identifies a date/time value, including timezone info (2019-06-18 10:32:15.173645362+0200).
TypeOffsetDateTime ValueType = "datetime" TypeOffsetDateTime ValueType = "datetime"

View File

@ -12,8 +12,8 @@ func Test_ConstructSlightlyComplexStructure(t *testing.T) {
p.SetKeyValuePair(ast.NewKey("ding"), ast.NewValue(ast.TypeInteger, 10)) p.SetKeyValuePair(ast.NewKey("ding"), ast.NewValue(ast.TypeInteger, 10))
p.SetKeyValuePair(ast.NewKey("dong"), ast.NewValue(ast.TypeString, "not a song")) p.SetKeyValuePair(ast.NewKey("dong"), ast.NewValue(ast.TypeString, "not a song"))
p.OpenTable(ast.NewKey("key1", "key2 a")) p.OpenTable(ast.NewKey("key1", "key2 a"))
p.SetKeyValuePair(ast.NewKey("dooh"), ast.NewValue(ast.TypeBoolean, true)) p.SetKeyValuePair(ast.NewKey("dooh"), ast.NewValue(ast.TypeBool, true))
p.SetKeyValuePair(ast.NewKey("dah"), ast.NewValue(ast.TypeBoolean, false)) p.SetKeyValuePair(ast.NewKey("dah"), ast.NewValue(ast.TypeBool, false))
p.OpenTable(ast.NewKey("key1", "key2 b")) p.OpenTable(ast.NewKey("key1", "key2 b"))
p.SetKeyValuePair(ast.NewKey("dieh"), ast.NewValue(ast.TypeFloat, 1.111)) p.SetKeyValuePair(ast.NewKey("dieh"), ast.NewValue(ast.TypeFloat, 1.111))
p.SetKeyValuePair(ast.NewKey("duh"), ast.NewValue(ast.TypeFloat, 1.18e-12)) p.SetKeyValuePair(ast.NewKey("duh"), ast.NewValue(ast.TypeFloat, 1.18e-12))
@ -188,7 +188,7 @@ func Test_GivenExistingValueAtDeepKeyFromSubTable_CreatingTableAtSameKey_Returns
p := ast.NewDocument() p := ast.NewDocument()
p.OpenTable(ast.NewKey("deep", "table")) p.OpenTable(ast.NewKey("deep", "table"))
p.SetKeyValuePair(ast.NewKey("key1", "key2"), ast.NewValue(ast.TypeInteger, 0)) p.SetKeyValuePair(ast.NewKey("key1", "key2"), ast.NewValue(ast.TypeInteger, 0))
return p.SetKeyValuePair(ast.NewKey("key1", "key2"), ast.NewValue(ast.TypeBoolean, true)), p return p.SetKeyValuePair(ast.NewKey("key1", "key2"), ast.NewValue(ast.TypeBool, true)), p
}, },
// This test mainly tests the formatting of [deep->table->key1->key2], being a concatenation // This test mainly tests the formatting of [deep->table->key1->key2], being a concatenation
// of the currently active table plus the multipart key for SetKeyValuePair(). // of the currently active table plus the multipart key for SetKeyValuePair().

View File

@ -10,13 +10,13 @@ import (
func Test_StringFormatting(t *testing.T) { func Test_StringFormatting(t *testing.T) {
testAST(t, func() (error, *ast.Document) { testAST(t, func() (error, *ast.Document) {
tableData := make(ast.Table) tableData := make(ast.Table)
tableData["x"] = ast.NewValue(ast.TypeBoolean, true) tableData["x"] = ast.NewValue(ast.TypeBool, true)
tableData["y"] = ast.NewValue(ast.TypeInteger, 42) tableData["y"] = ast.NewValue(ast.TypeInteger, 42)
dateTime, _ := time.Parse(time.RFC3339Nano, "2003-11-01T01:02:03.999999999+10:00") dateTime, _ := time.Parse(time.RFC3339Nano, "2003-11-01T01:02:03.999999999+10:00")
doc := ast.NewDocument() doc := ast.NewDocument()
doc.SetKeyValuePair(ast.NewKey("a"), ast.NewValue(ast.TypeInteger, 1)) doc.SetKeyValuePair(ast.NewKey("a"), ast.NewValue(ast.TypeInteger, 1))
doc.SetKeyValuePair(ast.NewKey("b"), ast.NewValue(ast.TypeFloat, 2.3)) doc.SetKeyValuePair(ast.NewKey("b"), ast.NewValue(ast.TypeFloat, 2.3))
doc.SetKeyValuePair(ast.NewKey("c"), ast.NewValue(ast.TypeBoolean, true)) doc.SetKeyValuePair(ast.NewKey("c"), ast.NewValue(ast.TypeBool, true))
doc.SetKeyValuePair(ast.NewKey("d"), ast.NewValue(ast.TypeString, "foo")) doc.SetKeyValuePair(ast.NewKey("d"), ast.NewValue(ast.TypeString, "foo"))
doc.SetKeyValuePair(ast.NewKey("e"), ast.NewValue(ast.TypeArray, ast.NewValue(ast.TypeInteger, 1), ast.NewValue(ast.TypeInteger, 2))) doc.SetKeyValuePair(ast.NewKey("e"), ast.NewValue(ast.TypeArray, ast.NewValue(ast.TypeInteger, 1), ast.NewValue(ast.TypeInteger, 2)))
doc.SetKeyValuePair(ast.NewKey("f"), ast.NewValue(ast.TypeTable, tableData)) doc.SetKeyValuePair(ast.NewKey("f"), ast.NewValue(ast.TypeTable, tableData))

View File

@ -53,7 +53,7 @@ func makeSushi(value *ast.Value) string {
return renderValue("integer", fmt.Sprintf("%d", value.Data[0].(int64))) return renderValue("integer", fmt.Sprintf("%d", value.Data[0].(int64)))
case ast.TypeFloat: case ast.TypeFloat:
return renderValue("float", fmt.Sprintf("%v", value.Data[0].(float64))) return renderValue("float", fmt.Sprintf("%v", value.Data[0].(float64)))
case ast.TypeBoolean: case ast.TypeBool:
return renderValue("bool", fmt.Sprintf("%t", value.Data[0].(bool))) return renderValue("bool", fmt.Sprintf("%t", value.Data[0].(bool)))
case ast.TypeOffsetDateTime: case ast.TypeOffsetDateTime:
return renderValue("datetime", value.Data[0].(time.Time).Format(time.RFC3339Nano)) return renderValue("datetime", value.Data[0].(time.Time).Format(time.RFC3339Nano))

View File

@ -12,7 +12,7 @@ var (
// Blank is ignored around key names and values. The key, equals // Blank is ignored around key names and values. The key, equals
// sign, and value must be on the same line (though some values can be // sign, and value must be on the same line (though some values can be
// broken over multiple lines). // broken over multiple lines).
keyAssignment = c.Seq(dropBlanks, a.Equal, dropBlanks) keyAssignment = c.Seq(optionalBlanks, a.Equal, optionalBlanks)
// A key may be either bare, quoted or dotted. Bare keys may only // A key may be either bare, quoted or dotted. Bare keys may only
// contain ASCII letters, ASCII digits, underscores, and dashes // contain ASCII letters, ASCII digits, underscores, and dashes
@ -31,10 +31,7 @@ var (
// This allows for grouping similar properties together. Blanks // This allows for grouping similar properties together. Blanks
// around dot-separated parts are ignored, however, best practice is to // around dot-separated parts are ignored, however, best practice is to
// not use any extraneous blanks. // not use any extraneous blanks.
keySeparatorDot = c.Seq(dropBlanks, a.Dot, dropBlanks) keySeparatorDot = c.Seq(optionalBlanks, a.Dot, optionalBlanks)
// After a value, the line must end. There can be an optional comment.
endOfLineAfterValue = c.Seq(dropBlanks, a.EndOfLine.Or(comment))
) )
func (t *parser) startKeyValuePair(p *parse.API) { func (t *parser) startKeyValuePair(p *parse.API) {
@ -44,7 +41,7 @@ func (t *parser) startKeyValuePair(p *parse.API) {
err := t.SetKeyValuePair(key, value) err := t.SetKeyValuePair(key, value)
if err != nil { if err != nil {
p.Error("%s", err) p.Error("%s", err)
} else if !p.Accept(endOfLineAfterValue) { } else if !p.Accept(endOfLineOrComment) {
p.Expected("end of line") p.Expected("end of line")
} }
} }

View File

@ -16,7 +16,6 @@ var (
blank = a.Runes('\t', ' ') blank = a.Runes('\t', ' ')
blanks = c.OneOrMore(blank) blanks = c.OneOrMore(blank)
optionalBlanks = c.ZeroOrMore(blank) optionalBlanks = c.ZeroOrMore(blank)
dropBlanks = m.Drop(optionalBlanks)
// Newline means LF (0x0A) or CRLF (0x0D0A). // Newline means LF (0x0A) or CRLF (0x0D0A).
// This matches the default newline as defined by parsekit. // This matches the default newline as defined by parsekit.
@ -25,15 +24,15 @@ var (
// Whitespace is defined as blanks + newlines. // Whitespace is defined as blanks + newlines.
whitespace = c.OneOrMore(blank.Or(newline)) whitespace = c.OneOrMore(blank.Or(newline))
optionalWhitespace = c.ZeroOrMore(blank.Or(newline)) optionalWhitespace = c.ZeroOrMore(blank.Or(newline))
dropWhitespace = m.Drop(optionalWhitespace)
// A '#' hash symbol marks the rest of the line as a comment. // A '#' hash symbol marks the rest of the line as a comment.
// All characters up to the end of the line are included in the comment. // All characters up to the end of the line are included in the comment.
comment = c.Seq(a.Hash, c.ZeroOrMore(c.Not(a.EndOfLine)), m.Drop(a.EndOfLine)) comment = c.Seq(a.Hash, c.ZeroOrMore(c.Not(a.EndOfLine)))
optionalComment = c.Optional(comment)
endOfLineOrComment = optionalBlanks.Then(a.EndOfLine.Or(comment)) endOfLineOrComment = c.Seq(optionalBlanks, optionalComment, a.EndOfLine)
whitespaceOrComment = c.OneOrMore(c.Any(blank, newline, comment)) whitespaceOrComment = whitespace.Or(comment)
optionalWhitespaceOrComment = c.Optional(whitespaceOrComment) optionalWhitespaceOrComment = c.ZeroOrMore(whitespaceOrComment)
) )
// parser embeds the TOML ast.Document, so it can be extended with methods // parser embeds the TOML ast.Document, so it can be extended with methods

View File

@ -33,7 +33,7 @@ import (
var ( var (
arrayOpen = a.SquareOpen.Then(optionalWhitespaceOrComment) arrayOpen = a.SquareOpen.Then(optionalWhitespaceOrComment)
arraySeparator = c.Seq(optionalWhitespaceOrComment, a.Comma, optionalWhitespaceOrComment) arraySeparator = c.Seq(optionalWhitespaceOrComment, a.Comma, optionalWhitespaceOrComment)
arrayClose = c.Seq(c.Optional(optionalWhitespaceOrComment.Then(a.Comma)), optionalWhitespaceOrComment, a.SquareClose) arrayClose = c.Seq(optionalWhitespaceOrComment, a.Comma.Optional(), optionalWhitespaceOrComment, a.SquareClose)
) )
func (t *parser) parseArray(p *parse.API) (*ast.Value, bool) { func (t *parser) parseArray(p *parse.API) (*ast.Value, bool) {

View File

@ -5,8 +5,8 @@ import (
"git.makaay.nl/mauricem/go-toml/ast" "git.makaay.nl/mauricem/go-toml/ast"
) )
var falseValue = ast.NewValue(ast.TypeBoolean, false) var falseValue = ast.NewValue(ast.TypeBool, false)
var trueValue = ast.NewValue(ast.TypeBoolean, true) var trueValue = ast.NewValue(ast.TypeBool, true)
// Booleans are just the tokens you're used to. Always lowercase. // Booleans are just the tokens you're used to. Always lowercase.
func (t *parser) parseBoolean(p *parse.API) (*ast.Value, bool) { func (t *parser) parseBoolean(p *parse.API) (*ast.Value, bool) {

View File

@ -40,11 +40,11 @@ var (
// "line ending backslash". When the last non-whitespace character on a line is // "line ending backslash". When the last non-whitespace character on a line is
// a \, it will be trimmed along with all whitespace (including newlines) up to // a \, it will be trimmed along with all whitespace (including newlines) up to
// the next non-whitespace character or closing delimiter. // the next non-whitespace character or closing delimiter.
lineEndingBackslash = a.Backslash.Then(dropBlanks).Then(newline).Then(dropWhitespace) lineEndingBackslash = c.Seq(a.Backslash, optionalBlanks, newline, optionalWhitespace)
) )
// There are four ways to express strings: basic, multi-line basic, literal and // There are four ways to express strings: basic, multi-line basic, literal and
// multi-line literal. All strings must contain only valid UTF-8 characters. // multi-line literal. All strings must parse/value_array.gocontain only valid UTF-8 characters.
func (t *parser) parseString(p *parse.API) (*ast.Value, bool) { func (t *parser) parseString(p *parse.API) (*ast.Value, bool) {
var value string var value string
var ok bool var ok bool
@ -89,13 +89,8 @@ func (t *parser) parseBasicString(name string, p *parse.API) (string, bool) {
p.Error("invalid character in %s: %q (must be escaped)", name, p.Result().Rune(0)) p.Error("invalid character in %s: %q (must be escaped)", name, p.Result().Rune(0))
return sb.String(), false return sb.String(), false
case p.Accept(tok.StrInterpreted(nil, validEscape)): case p.Accept(tok.StrInterpreted(nil, validEscape)):
s := p.Result().Value(0).(string) if !appendStrInterpreted(p, sb) {
for _, r := range s { return sb.String(), false
if r == utf8.RuneError {
p.Error("invalid UTF8 rune")
return sb.String(), false
}
sb.WriteRune(r)
} }
case p.Peek(a.Backslash): case p.Peek(a.Backslash):
p.Error("invalid escape sequence") p.Error("invalid escape sequence")
@ -185,13 +180,8 @@ func (t *parser) parseMultiLineBasicString(p *parse.API) (string, bool) {
p.Error("invalid character in multi-line basic string: %q (must be escaped)", p.Result().Rune(0)) p.Error("invalid character in multi-line basic string: %q (must be escaped)", p.Result().Rune(0))
return sb.String(), false return sb.String(), false
case p.Accept(tok.StrInterpreted(nil, c.OneOrMore(validEscape))): case p.Accept(tok.StrInterpreted(nil, c.OneOrMore(validEscape))):
s := p.Result().Value(0).(string) if !appendStrInterpreted(p, sb) {
for _, r := range s { return sb.String(), false
if r == utf8.RuneError {
p.Error("invalid UTF8 rune")
return sb.String(), false
}
sb.WriteRune(r)
} }
case p.Accept(lineEndingBackslash): case p.Accept(lineEndingBackslash):
// NOOP, the line-ending backslash sequence is skipped. // NOOP, the line-ending backslash sequence is skipped.
@ -212,6 +202,18 @@ func (t *parser) parseMultiLineBasicString(p *parse.API) (string, bool) {
} }
} }
func appendStrInterpreted(p *parse.API, sb *strings.Builder) bool {
s := p.Result().Value(0).(string)
for _, r := range s {
if r == utf8.RuneError {
p.Error("invalid UTF8 rune")
return false
}
sb.WriteRune(r)
}
return true
}
// Specific handling of input for multi-line literal strings. // Specific handling of input for multi-line literal strings.
// //
// • Multi-line literal strings are surrounded by three single quotes on // • Multi-line literal strings are surrounded by three single quotes on

View File

@ -7,17 +7,17 @@ import (
var ( var (
// Opener and closer for [table]. // Opener and closer for [table].
tableOpen = c.Seq(dropBlanks, a.SquareOpen, dropBlanks) tableOpen = c.Seq(optionalBlanks, a.SquareOpen, optionalBlanks)
tableClose = c.Seq(dropBlanks, a.SquareClose, dropBlanks) tableClose = c.Seq(optionalBlanks, a.SquareClose, optionalBlanks)
// Opener and closer for [[array.of.tables]]. // Opener and closer for [[array.of.tables]].
tableArrayOpen = c.Seq(dropBlanks, a.SquareOpen, a.SquareOpen, dropBlanks) tableArrayOpen = c.Seq(optionalBlanks, a.SquareOpen, a.SquareOpen, optionalBlanks)
tableArrayClose = c.Seq(dropBlanks, a.SquareClose, a.SquareClose, dropBlanks) tableArrayClose = c.Seq(optionalBlanks, a.SquareClose, a.SquareClose, optionalBlanks)
// Opener, separator and closer for { inline: "tables" }. // Opener, separator and closer for { inline: "tables" }.
inlineTableOpen = c.Seq(dropBlanks, a.CurlyOpen, dropBlanks) inlineTableOpen = c.Seq(optionalBlanks, a.CurlyOpen, optionalBlanks)
inlineTableSeparator = c.Seq(dropBlanks, a.Comma, dropBlanks) inlineTableSeparator = c.Seq(optionalBlanks, a.Comma, optionalBlanks)
inlineTableClose = c.Seq(dropBlanks, a.CurlyClose, dropBlanks) inlineTableClose = c.Seq(optionalBlanks, a.CurlyClose, optionalBlanks)
) )
func (t *parser) startTable(p *parse.API) { func (t *parser) startTable(p *parse.API) {