Fix parsing bugs + boolean impl
This commit is contained in:
+22
-3
@@ -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
|
||||||
|
|||||||
@@ -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 / - / _
|
||||||
|
|||||||
+21
-21
@@ -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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user