go-nestedtext

NestedText in Go (alpha)
Log | Files | Refs | README | LICENSE

commit 2f3a44489405719c60f6bd9c29de99f17f0e947b
parent 0a5905e8e6dda95a77cb337806aad4cdbc8116cc
Author: Byron Torres <b@torresjrjr.com>
Date:   Sun,  2 May 2021 23:40:32 +0100

Fixed empty key bug, error msg bug

Diffstat:
Mnestedtext.go | 41+++++++++++++++++++++++++----------------
1 file changed, 25 insertions(+), 16 deletions(-)

diff --git a/nestedtext.go b/nestedtext.go @@ -17,7 +17,7 @@ var ( reLeadingWs = regexp.MustCompile(`^\s*`) reComment = regexp.MustCompile(`^\s*(#.*)?$`) reKeyValue = regexp.MustCompile(`^\s*[^:]*: .*$`) - reKeyEmpty = regexp.MustCompile(`^\s*[^:]*: ?$`) + reKeyEmpty = regexp.MustCompile(`^\s*[^:]*:$`) reListValue = regexp.MustCompile(`^\s*- .*$`) reListEmpty = regexp.MustCompile(`^\s*- ?$`) reMultiline = regexp.MustCompile(`^\s*>( .*)?$`) @@ -43,11 +43,11 @@ func main() { func UnmarshalNestedText(r io.Reader) (interface{}, error) { scanner := bufio.NewScanner(r) lineNumber := 0 - return parseNestedText(scanner, "", &lineNumber, true) + return parseNestedText(scanner, &lineNumber, "", Unknown) } func parseNestedText( - scanner *bufio.Scanner, parentIndent string, lineNum *int, root bool, + scanner *bufio.Scanner, lineNum *int, parentIndent string, parentType BlockType, ) (interface{}, error) { var blockType BlockType = Unknown var dict map[string]interface{} @@ -56,16 +56,17 @@ func parseNestedText( var localIndentDefined bool var localIndent string - var skip bool + var skipNextScan bool for { - if !skip { - if !scanner.Scan() { + if skipNextScan { + skipNextScan = false + } else { + ok := scanner.Scan() + if !ok { break } *lineNum++ - } else { - skip = false } rawLine := scanner.Text() @@ -78,12 +79,20 @@ func parseNestedText( if !localIndentDefined { localIndent = currentIndent localIndentDefined = true - } else if (currentIndent != localIndent) || - !strings.HasPrefix(localIndent, parentIndent) { + } else if currentIndent != localIndent { // indented leftwards, leaf has finished. break } + if parentType != Unknown && currentIndent == parentIndent { + // previous line was a list '-\n' or key ':\n' marker + // but this line is not the value of the previous line + // as it is on the same indentation level. + // As such, that list element or key's value should be + // interpreted as "". + return "", nil + } + // the effective current line line := strings.TrimPrefix(rawLine, localIndent) @@ -135,24 +144,24 @@ func parseNestedText( } key = strings.TrimSpace(key) - child, err := parseNestedText(scanner, localIndent, lineNum, false) + child, err := parseNestedText(scanner, lineNum, localIndent, blockType) if err != nil { return nil, err } dict[key] = child - skip = true + skipNextScan = true case reListValue.MatchString(line): value := strings.TrimPrefix(line, "- ") list = append(list, value) case reListEmpty.MatchString(line): - child, err := parseNestedText(scanner, localIndent, lineNum, false) + child, err := parseNestedText(scanner, lineNum, localIndent, blockType) if err != nil { return nil, err } list = append(list, child) - skip = true + skipNextScan = true case reMultiline.MatchString(line): var oneline string @@ -163,7 +172,7 @@ func parseNestedText( default: errmsg := "Internal error - unknown linetype of line %d" - return nil, fmt.Errorf(errmsg, &lineNum) + return nil, fmt.Errorf(errmsg, *lineNum) } } @@ -179,7 +188,7 @@ func parseNestedText( case Multiline: return multiline, nil default: - return nil, fmt.Errorf("Internal error - line %d", &lineNum) + return nil, fmt.Errorf("Internal error - line %d", *lineNum) } }