Backup work.

This commit is contained in:
Maurice Makaay 2019-07-22 23:27:59 +00:00
parent 5815a93a01
commit 5ccb16f38f
7 changed files with 294 additions and 20 deletions

View File

@ -6,8 +6,18 @@ a:
go build go build
mv burntsushi-tester A mv burntsushi-tester A
a-l:
go build -gcflags=all=-l
mv burntsushi-tester A
b-l:
go build -gcflags=all=-l
mv burntsushi-tester B
test: test-a test-b test-sushi test: test-a test-b test-sushi
profile: profile-a profile-b
test-a: test-a:
numactl --physcpubind=+1 bash -c "time ./A < testfile.toml" numactl --physcpubind=+1 bash -c "time ./A < testfile.toml"

View File

@ -0,0 +1,245 @@
################################################################################
## Comment
# Speak your mind with the hash symbol. They go from the symbol to the end of
# the line.
################################################################################
## Table
# Tables (also known as hash tables or dictionaries) are collections of
# key/value pairs. They appear in square brackets on a line by themselves.
[table]
key = "value" # Yeah, you can do this.
# Nested tables are denoted by table names with dots in them. Name your tables
# whatever crap you please, just don't use #, ., [ or ].
[table.subtable]
key = "another value"
# You don't need to specify all the super-tables if you don't want to. TOML
# knows how to do it for you.
# [x] you
# [x.y] don't
# [x.y.z] need these
[x.y.z.w] # for this to work
################################################################################
## Inline Table
# Inline tables provide a more compact syntax for expressing tables. They are
# especially useful for grouped data that can otherwise quickly become verbose.
# Inline tables are enclosed in curly braces `{` and `}`. No newlines are
# allowed between the curly braces unless they are valid within a value.
[table.inline]
name = { first = "Tom", last = "Preston-Werner" }
point = { x = 1, y = 2 }
################################################################################
## String
# 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.
[string.basic]
basic = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."
[string.multiline]
# The following strings are byte-for-byte equivalent:
key1 = "One\nTwo"
key2 = """One\nTwo"""
key3 = """
One
Two"""
[string.multiline.continued]
# The following strings are byte-for-byte equivalent:
key1 = "The quick brown fox jumps over the lazy dog."
key2 = """
The quick brown \
fox jumps over \
the lazy dog."""
key3 = """\
The quick brown \
fox jumps over \
the lazy dog.\
"""
[string.literal]
# What you see is what you get.
winpath = 'C:\Users\nodejs\templates'
winpath2 = '\\ServerX\admin$\system32\'
quoted = 'Tom "Dubs" Preston-Werner'
regex = '<\i\c*\s*>'
[string.literal.multiline]
regex2 = '''I [dw]on't need \d{2} apples'''
lines = '''
The first newline is
trimmed in raw strings.
All other whitespace
is preserved.
'''
################################################################################
## Integer
# Integers are whole numbers. Positive numbers may be prefixed with a plus sign.
# Negative numbers are prefixed with a minus sign.
[integer]
key1 = +99
key2 = 42
key3 = 0
key4 = -17
[integer.underscores]
# For large numbers, you may use underscores to enhance readability. Each
# underscore must be surrounded by at least one digit.
key1 = 1_000
key2 = 5_349_221
key3 = 1_2_3_4_5 # valid but inadvisable
################################################################################
## Float
# A float consists of an integer part (which may be prefixed with a plus or
# minus sign) followed by a fractional part and/or an exponent part.
[float.fractional]
key1 = +1.0
key2 = 3.1415
key3 = -0.01
[float.exponent]
key1 = 5e+22
key2 = 1e6
key3 = -2E-2
[float.both]
key = 6.626e-34
[float.underscores]
key1 = 9_224_617.445_991_228_313
key2 = 1e0_1_0
################################################################################
## Boolean
# Booleans are just the tokens you're used to. Always lowercase.
[boolean]
True = true
False = false
################################################################################
## Datetime
# Datetimes are RFC 3339 dates.
[datetime]
key1 = 1979-05-27T07:32:00Z
key2 = 1979-05-27T00:32:00-07:00
key3 = 1979-05-27T00:32:00.999999-07:00
################################################################################
## Array
# Arrays are square brackets with other primitives inside. Whitespace is
# ignored. Elements are separated by commas. Data types may not be mixed.
[array]
key1 = [ 1, 2, 3 ]
key2 = [ "red", "yellow", "green" ]
key3 = [ [ 1, 2 ], [3, 4, 5] ]
key4 = [ [ 1, 2 ], ["a", "b", "c"] ] # this is ok
# Arrays can also be multiline. So in addition to ignoring whitespace, arrays
# also ignore newlines between the brackets. Terminating commas are ok before
# the closing bracket.
key5 = [
1, 2, 3
]
key6 = [
1,
2, # this is ok
]
################################################################################
## Array of Tables
# These can be expressed by using a table name in double brackets. Each table
# with the same double bracketed name will be an element in the array. The
# tables are inserted in the order encountered.
[[products]]
name = "Hammer"
sku = 738594937
[[products]]
[[products]]
name = "Nail"
sku = 284758393
color = "gray"
# You can create nested arrays of tables as well.
[[fruit]]
name = "apple"
[fruit.physical]
color = "red"
shape = "round"
[[fruit.variety]]
name = "red delicious"
[[fruit.variety]]
name = "granny smith"
[[fruit]]
name = "banana"
[[fruit.variety]]
name = "plantain"

View File

@ -10,12 +10,14 @@ var (
// Both [tables] and [[arrays of tables]] start with a square open bracket. // Both [tables] and [[arrays of tables]] start with a square open bracket.
detectTable = a.SquareOpen detectTable = a.SquareOpen
whiteSpaceNewlinesAndComments = whitespaceInclNewlines.Or(comment)
) )
func (t *parser) startDocument(p *parse.API) { func (t *parser) startDocument(p *parse.API) {
for { for {
switch { switch {
case p.Accept(whitespaceInclNewlines.Or(comment)): case p.Accept(whiteSpaceNewlinesAndComments):
// NOOP // NOOP
case p.Peek(detectTable): case p.Peek(detectTable):
p.Handle(t.startTable) p.Handle(t.startTable)

View File

@ -5,15 +5,19 @@ import (
"git.makaay.nl/mauricem/go-toml/ast" "git.makaay.nl/mauricem/go-toml/ast"
) )
var falseValue = ast.NewValue(ast.TypeBool, false) var (
var trueValue = ast.NewValue(ast.TypeBool, true) trueStr = a.Str("true")
falseStr = a.Str("false")
falseValue = ast.NewValue(ast.TypeBool, false)
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) {
switch { switch {
case p.Accept(a.Str("true")): case p.Accept(trueStr):
return trueValue, true return trueValue, true
case p.Accept(a.Str("false")): case p.Accept(falseStr):
return falseValue, true return falseValue, true
default: default:
p.Expected("true or false") p.Expected("true or false")

View File

@ -20,6 +20,7 @@ var (
underscoreDigits = m.Drop(a.Underscore).Then(a.Digits) underscoreDigits = m.Drop(a.Underscore).Then(a.Digits)
integerSuffix = c.ZeroOrMore(underscoreDigits) integerSuffix = c.ZeroOrMore(underscoreDigits)
integer = integerPrefix.Then(integerSuffix) integer = integerPrefix.Then(integerSuffix)
integerToken = tok.Int64(nil, integer)
// Integer values -0 and +0 are valid and identical to an unprefixed zero. // Integer values -0 and +0 are valid and identical to an unprefixed zero.
plusZero = a.Plus.Then(a.Zero) plusZero = a.Plus.Then(a.Zero)
@ -59,6 +60,7 @@ var (
// fractional part must precede the exponent part. // fractional part must precede the exponent part.
fractAndOrExp = c.Any(fractionalPart.Then(c.Optional(exponentPart)), exponentPart) fractAndOrExp = c.Any(fractionalPart.Then(c.Optional(exponentPart)), exponentPart)
float = integer.Then(fractAndOrExp) float = integer.Then(fractAndOrExp)
floatToken = tok.Float64(nil, float)
// Float values -0.0 and +0.0 are valid and should map according to IEEE 754. // Float values -0.0 and +0.0 are valid and should map according to IEEE 754.
zeroFloat = a.Signed(a.Str("0.0")) zeroFloat = a.Signed(a.Str("0.0"))
@ -70,7 +72,7 @@ var (
func (t *parser) parseNumber(p *parse.API) (*ast.Value, bool) { func (t *parser) parseNumber(p *parse.API) (*ast.Value, bool) {
switch { switch {
case p.Accept(tok.Float64(nil, float)): case p.Accept(floatToken):
return ast.NewValue(ast.TypeFloat, p.Result.Tokens[0].Value.(float64)), true return ast.NewValue(ast.TypeFloat, p.Result.Tokens[0].Value.(float64)), true
case p.Accept(nan): case p.Accept(nan):
return ast.NewValue(ast.TypeFloat, math.NaN()), true return ast.NewValue(ast.TypeFloat, math.NaN()), true
@ -81,7 +83,7 @@ func (t *parser) parseNumber(p *parse.API) (*ast.Value, bool) {
return ast.NewValue(ast.TypeFloat, math.Inf(+1)), true return ast.NewValue(ast.TypeFloat, math.Inf(+1)), true
case p.Accept(a.Zero): case p.Accept(a.Zero):
return t.parseIntegerStartingWithZero(p) return t.parseIntegerStartingWithZero(p)
case p.Accept(tok.Int64(nil, integer)): case p.Accept(integerToken):
return ast.NewValue(ast.TypeInteger, p.Result.Tokens[0].Value.(int64)), true return ast.NewValue(ast.TypeInteger, p.Result.Tokens[0].Value.(int64)), true
default: default:
p.Expected("a number") p.Expected("a number")

View File

@ -14,11 +14,21 @@ var (
// Multi-line basic strings are surrounded by three quotation marks on each // Multi-line basic strings are surrounded by three quotation marks on each
// side and allow newlines. // side and allow newlines.
doubleQuote3 = a.Str(`"""`) doubleQuote3 = a.Str(`"""`)
openingMultiLineBasicString = doubleQuote3.Then(newline.Optional())
closingMultiLineBasicString = m.Drop(doubleQuote3)
// Multi-line literal strings are surrounded by three single quotes on each side and allow newlines. // Multi-line literal strings are surrounded by three single quotes on each side and allow newlines.
singleQuote3 = a.Str(`'''`) singleQuote3 = a.Str(`'''`)
openingMultiLineLiteralString = singleQuote3.Then(newline.Optional())
closingMultiLineLiteralString = m.Drop(singleQuote3)
// Closing character for basic strings.
closingDoubleQuote = m.Drop(a.DoubleQuote)
// Closing character for literal strings.
closingSingleQuote = m.Drop(a.SingleQuote)
// Control characters as defined by TOML (U+0000 to U+001F, U+007F) // Control characters as defined by TOML (U+0000 to U+001F, U+007F)
@ -93,7 +103,7 @@ func (t *parser) parseBasicString(name string, p *parse.API) (string, bool) {
sb := &strings.Builder{} sb := &strings.Builder{}
for { for {
switch { switch {
case p.Peek(controlCharacter): case p.PeekWithResult(controlCharacter):
p.Error("invalid character in %s: %q (must be escaped)", name, p.Result.Runes[0]) p.Error("invalid character in %s: %q (must be escaped)", name, p.Result.Runes[0])
return sb.String(), false return sb.String(), false
case p.Accept(validEscape): case p.Accept(validEscape):
@ -103,7 +113,7 @@ func (t *parser) parseBasicString(name string, p *parse.API) (string, bool) {
case p.Peek(a.Backslash): case p.Peek(a.Backslash):
p.Error("invalid escape sequence") p.Error("invalid escape sequence")
return sb.String(), false return sb.String(), false
case p.Accept(m.Drop(a.DoubleQuote)): case p.Accept(closingDoubleQuote):
return sb.String(), true return sb.String(), true
case p.Peek(a.InvalidRune): case p.Peek(a.InvalidRune):
p.Error("invalid UTF8 rune") p.Error("invalid UTF8 rune")
@ -132,11 +142,11 @@ func (t *parser) parseLiteralString(name string, p *parse.API) (string, bool) {
sb := &strings.Builder{} sb := &strings.Builder{}
for { for {
switch { switch {
case p.Accept(m.Drop(a.SingleQuote)): case p.Accept(closingSingleQuote):
return sb.String(), true return sb.String(), true
case p.Accept(a.Tab): case p.Accept(a.Tab):
sb.WriteString("\t") sb.WriteString("\t")
case p.Peek(controlCharacter): case p.PeekWithResult(controlCharacter):
p.Error("invalid character in %s: %q (no control chars allowed, except for tab)", name, p.Result.Runes[0]) p.Error("invalid character in %s: %q (no control chars allowed, except for tab)", name, p.Result.Runes[0])
return sb.String(), false return sb.String(), false
case p.Peek(a.InvalidRune): case p.Peek(a.InvalidRune):
@ -175,7 +185,7 @@ func (t *parser) parseLiteralString(name string, p *parse.API) (string, bool) {
// 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.
func (t *parser) parseMultiLineBasicString(p *parse.API) (string, bool) { func (t *parser) parseMultiLineBasicString(p *parse.API) (string, bool) {
if !p.Accept(doubleQuote3.Then(newline.Optional())) { if !p.Accept(openingMultiLineBasicString) {
p.Expected("opening three quotation marks") p.Expected("opening three quotation marks")
return "", false return "", false
} }
@ -184,7 +194,7 @@ func (t *parser) parseMultiLineBasicString(p *parse.API) (string, bool) {
switch { switch {
case p.Accept(newline): case p.Accept(newline):
sb.WriteString("\n") sb.WriteString("\n")
case p.Peek(controlCharacter): case p.PeekWithResult(controlCharacter):
p.Error("invalid character in multi-line basic string: %q (must be escaped)", p.Result.Runes[0]) p.Error("invalid character in multi-line basic string: %q (must be escaped)", p.Result.Runes[0])
return sb.String(), false return sb.String(), false
case p.Accept(validEscape): case p.Accept(validEscape):
@ -196,7 +206,7 @@ func (t *parser) parseMultiLineBasicString(p *parse.API) (string, bool) {
case p.Peek(a.Backslash): case p.Peek(a.Backslash):
p.Error("invalid escape sequence") p.Error("invalid escape sequence")
return sb.String(), false return sb.String(), false
case p.Accept(m.Drop(doubleQuote3)): case p.Accept(closingMultiLineBasicString):
return sb.String(), true return sb.String(), true
case p.Accept(a.ValidRune): case p.Accept(a.ValidRune):
sb.WriteString(p.Result.String()) sb.WriteString(p.Result.String())
@ -255,20 +265,20 @@ func appendEscapedRune(p *parse.API, sb *strings.Builder) bool {
// //
// • Control characters other than tab and newline are not permitted in a multi-line literal string. // • Control characters other than tab and newline are not permitted in a multi-line literal string.
func (t *parser) parseMultiLineLiteralString(p *parse.API) (string, bool) { func (t *parser) parseMultiLineLiteralString(p *parse.API) (string, bool) {
if !p.Accept(singleQuote3.Then(newline.Optional())) { if !p.Accept(openingMultiLineLiteralString) {
p.Expected("opening three single quotes") p.Expected("opening three single quotes")
return "", false return "", false
} }
sb := &strings.Builder{} sb := &strings.Builder{}
for { for {
switch { switch {
case p.Accept(m.Drop(singleQuote3)): case p.Accept(closingMultiLineLiteralString):
return sb.String(), true return sb.String(), true
case p.Accept(a.Tab): case p.Accept(a.Tab):
sb.WriteString("\t") sb.WriteString("\t")
case p.Accept(newline): case p.Accept(newline):
sb.WriteString("\n") sb.WriteString("\n")
case p.Peek(controlCharacter): case p.PeekWithResult(controlCharacter):
p.Error("invalid character in literal string: %q (no control chars allowed, except for tab and newline)", p.Result.Runes[0]) p.Error("invalid character in literal string: %q (no control chars allowed, except for tab and newline)", p.Result.Runes[0])
return sb.String(), false return sb.String(), false
case p.Accept(a.ValidRune): case p.Accept(a.ValidRune):

View File

@ -9,7 +9,8 @@
#ppfile=` | ./parse2 2>&1 | grep "cpu profiling enabled" | cut -d, -f2` #ppfile=` | ./parse2 2>&1 | grep "cpu profiling enabled" | cut -d, -f2`
go build #go build -gcflags=all=-l -v
go build -v
ppfile=`cat long.toml | ./parse2 -p 25 2>&1 | grep "profiling enabled" | cut -d, -f2` ppfile=`cat long.toml | ./parse2 -p 25 2>&1 | grep "profiling enabled" | cut -d, -f2`
go tool pprof -http 0.0.0.0:8888 ./parse2 $ppfile go tool pprof -http 0.0.0.0:8888 ./parse2 $ppfile