Fix parsing bugs + boolean impl

This commit is contained in:
Thomas Pelletier
2021-02-06 08:54:40 -05:00
parent a466f0ca79
commit 540c2a7b59
3 changed files with 68 additions and 36 deletions
+22 -3
View File
@@ -23,6 +23,25 @@ var scanFollowsFalse = scanFollows([]byte{'f', 'a', 'l', 's', 'e'})
var scanFollowsArrayTableBegin = scanFollows([]byte{arrayOrTableBegin, arrayOrTableBegin}) var scanFollowsArrayTableBegin = scanFollows([]byte{arrayOrTableBegin, arrayOrTableBegin})
var scanFollowsArrayTableEnd = scanFollows([]byte{arrayOrTableEnd, arrayOrTableEnd}) var scanFollowsArrayTableEnd = scanFollows([]byte{arrayOrTableEnd, arrayOrTableEnd})
func scanNewline(b []byte) ([]byte, []byte, error) {
if len(b) == 0 {
return nil, nil, fmt.Errorf("not enough bytes for new line")
}
if b[0] == '\n' {
return b[:1], b[1:], nil
}
if b[0] == '\r' {
if len(b) < 2 {
return nil, nil, fmt.Errorf("not enough bytes for windows newline")
}
if b[1] == '\n' {
return b[:2], b[2:], nil
}
return nil, nil, unexpectedCharacter{r: '\n', b: b[2:]}
}
return nil, nil, unexpectedCharacter{b: b}
}
const ( const (
dot = '.' dot = '.'
equal = '=' equal = '='
@@ -94,7 +113,7 @@ func scan(b []byte) ([]byte, []byte, error) {
func scanUnquotedKey(b []byte) ([]byte, []byte, error) { func scanUnquotedKey(b []byte) ([]byte, []byte, error) {
//unquoted-key = 1*( ALPHA / DIGIT / %x2D / %x5F ) ; A-Z / a-z / 0-9 / - / _ //unquoted-key = 1*( ALPHA / DIGIT / %x2D / %x5F ) ; A-Z / a-z / 0-9 / - / _
for i := 1; i < len(b); i++ { for i := 0; i < len(b); i++ {
if !isUnquotedKeyChar(b[i]) { if !isUnquotedKeyChar(b[i]) {
return b[:i], b[i:], nil return b[:i], b[i:], nil
} }
@@ -153,7 +172,7 @@ func scanWindowsNewline(b []byte) ([]byte, []byte, error) {
} }
func scanWhitespace(b []byte) ([]byte, []byte) { func scanWhitespace(b []byte) ([]byte, []byte) {
for i := 1; i < len(b); i++ { for i := 0; i < len(b); i++ {
switch b[i] { switch b[i] {
case ' ', '\t': case ' ', '\t':
continue continue
@@ -176,7 +195,7 @@ func scanComment(b []byte) ([]byte, []byte, error) {
for i := 1; i < len(b); i++ { for i := 1; i < len(b); i++ {
switch b[i] { switch b[i] {
case '\n': case '\n':
return b[:i+1], b[i+1:], nil return b[:i], b[i:], nil
} }
} }
return b, nil, nil return b, nil, nil
+24 -11
View File
@@ -51,12 +51,20 @@ func parseExpression(b []byte) ([]byte, error) {
_, rest, err := scanComment(b) _, rest, err := scanComment(b)
return rest, err return rest, err
} }
if b[0] == '\n' || b[0] == '\r' {
_, rest, err := scanNewline(b)
return rest, err
}
var err error
if b[0] == '[' { if b[0] == '[' {
// TODO: parse 'table' // TODO: parse 'table'
panic("todo")
} else { } else {
rest, err := parseKeyval(b) b, err = parseKeyval(b)
return rest, err }
if err != nil {
return nil, err
} }
b = parseWhitespace(b) b = parseWhitespace(b)
@@ -107,11 +115,20 @@ func parseVal(b []byte) ([]byte, error) {
case '\'': case '\'':
if scanFollowsMultilineLiteralStringDelimiter(b) { if scanFollowsMultilineLiteralStringDelimiter(b) {
_, b, err = parseMultilineLiteralString(b) _, b, err = parseMultilineLiteralString(b)
} else {
_, b, err = scanLiteralString(b)
} }
_, b, err = scanLiteralString(b)
return b, err return b, err
// TODO boolean case 't':
if !scanFollowsTrue(b) {
return nil, fmt.Errorf("expected 'true'")
}
return b[4:], nil
case 'f':
if !scanFollowsFalse(b) {
return nil, fmt.Errorf("expected 'false'")
}
return b[5:], nil
// TODO array // TODO array
// TODO inline-table // TODO inline-table
@@ -247,8 +264,8 @@ func parseKey(b []byte) ([]byte, error) {
} }
for { for {
if len(b) > 0 && (b[0] == '.' || isWhitespace(b[0])) { b = parseWhitespace(b)
b = parseWhitespace(b) if len(b) > 0 && b[0] == '.' {
b, err = expect('.', b) b, err = expect('.', b)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -266,10 +283,6 @@ func parseKey(b []byte) ([]byte, error) {
return b, nil return b, nil
} }
func isWhitespace(b byte) bool {
return b == ' ' || b == '\t'
}
func parseSimpleKey(b []byte) ([]byte, error) { func parseSimpleKey(b []byte) ([]byte, error) {
//simple-key = quoted-key / unquoted-key //simple-key = quoted-key / unquoted-key
//unquoted-key = 1*( ALPHA / DIGIT / %x2D / %x5F ) ; A-Z / a-z / 0-9 / - / _ //unquoted-key = 1*( ALPHA / DIGIT / %x2D / %x5F ) ; A-Z / a-z / 0-9 / - / _
+22 -22
View File
@@ -35,7 +35,7 @@ var inputs = []string{
`[ test ]`, `[ test ]`,
`[ "hello".world ]`, `[ "hello".world ]`,
`[test] `[test]
a = false`, a = false`,
`[[foo]]`, `[[foo]]`,
} }
@@ -66,27 +66,27 @@ func TestParse(t *testing.T) {
} }
} }
type noopParser struct { //type noopParser struct {
} //}
//
func (n noopParser) ArrayTableBegin() {} //func (n noopParser) ArrayTableBegin() {}
func (n noopParser) ArrayTableEnd() {} //func (n noopParser) ArrayTableEnd() {}
func (n noopParser) StandardTableBegin() {} //func (n noopParser) StandardTableBegin() {}
func (n noopParser) StandardTableEnd() {} //func (n noopParser) StandardTableEnd() {}
func (n noopParser) InlineTableSeparator() {} //func (n noopParser) InlineTableSeparator() {}
func (n noopParser) InlineTableBegin() {} //func (n noopParser) InlineTableBegin() {}
func (n noopParser) InlineTableEnd() {} //func (n noopParser) InlineTableEnd() {}
func (n noopParser) ArraySeparator() {} //func (n noopParser) ArraySeparator() {}
func (n noopParser) ArrayBegin() {} //func (n noopParser) ArrayBegin() {}
func (n noopParser) ArrayEnd() {} //func (n noopParser) ArrayEnd() {}
func (n noopParser) Whitespace(b []byte) {} //func (n noopParser) Whitespace(b []byte) {}
func (n noopParser) Comment(b []byte) {} //func (n noopParser) Comment(b []byte) {}
func (n noopParser) UnquotedKey(b []byte) {} //func (n noopParser) UnquotedKey(b []byte) {}
func (n noopParser) LiteralString(b []byte) {} //func (n noopParser) LiteralString(b []byte) {}
func (n noopParser) BasicString(b []byte) {} //func (n noopParser) BasicString(b []byte) {}
func (n noopParser) Dot(b []byte) {} //func (n noopParser) Dot(b []byte) {}
func (n noopParser) Boolean(b []byte) {} //func (n noopParser) Boolean(b []byte) {}
func (n noopParser) Equal(b []byte) {} //func (n noopParser) Equal(b []byte) {}
// //
//func BenchmarkParseAll(b *testing.B) { //func BenchmarkParseAll(b *testing.B) {