From d41cd781d9216b7de0b2f8aaa0b09f9ef9577885 Mon Sep 17 00:00:00 2001 From: Alejandro Mery Date: Mon, 4 Sep 2023 15:37:14 +0000 Subject: [PATCH] parser: introduce SplitCommaArray to splits comma separated strings removing whitespace and respecting quoted literals. Signed-off-by: Alejandro Mery --- parser/comma_array.go | 88 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 parser/comma_array.go diff --git a/parser/comma_array.go b/parser/comma_array.go new file mode 100644 index 0000000..2503172 --- /dev/null +++ b/parser/comma_array.go @@ -0,0 +1,88 @@ +package parser + +import ( + "strings" + + "asciigoat.org/core/lexer" +) + +type commaArrayParser struct { + TextParser + + out []string +} + +func (p *commaArrayParser) lexStart() (lexer.StateFn, error) { + for { + r, _, err := p.ReadRune() + switch { + case err != nil: + // EOF + return nil, err + case r == RuneQuotes: + // Quoted Value + return p.lexQuotedString, nil + case IsNewLine(r): + // new lines are acceptable when parsing a string for + // comma delimited arrays. but make sure we discard it + // complete + p.UnreadRune() + p.AcceptNewLine() + p.Discard() + case lexer.IsSpace(r): + // discard whitespace outside quotes + p.Discard() + default: + p.UnreadRune() + return p.lexWord, nil + } + } +} + +func (p *commaArrayParser) lexWord() (lexer.StateFn, error) { + for { + r, _, err := p.ReadRune() + switch { + case err != nil: + // done. store what we got and move on + _, s := p.Emit() + p.out = append(p.out, s) + return nil, err + case r == ',': + // done + _, s := p.Emit() + // remove comma, trim and append to output + s = strings.TrimRightFunc(s[:len(s)-1], IsSpace) + p.out = append(p.out, s) + return p.lexStart, nil + } + } +} + +func (p *commaArrayParser) lexQuotedString() (lexer.StateFn, error) { + s, err := lexQuotedString(&p.TextParser) + if err != nil { + return nil, err + } + + p.Discard() + p.out = append(p.out, s) + return p.lexStart, nil +} + +func (p *commaArrayParser) Run() ([]string, error) { + err := lexer.Run(p.lexStart) + + return p.out, err +} + +// SplitCommaArray splits comma separated strings, removing whitespace +// and respecting quoted literals. +func SplitCommaArray(s string) ([]string, error) { + if s != "" { + var p commaArrayParser + p.InitString(s) + return p.Run() + } + return nil, nil +}