diff --git a/parser/comma_array.go b/parser/comma_array.go new file mode 100644 index 0000000..ba8a3c6 --- /dev/null +++ b/parser/comma_array.go @@ -0,0 +1,90 @@ +package parser + +import ( + "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 == RuneEscape: + // escaped + r2, _, err := p.ReadRune() + switch { + case err != nil: + // incomplete + return nil, NewErrIncompleteEscaped(&p.TextParser) + case IsNewLine(r2): + // escaped new line + p.UnreadRune() + p.AcceptNewLine() + } + } + } +} + +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 +func SplitCommaArray(s string) ([]string, error) { + if s != "" { + var p commaArrayParser + p.InitString(s) + return p.Run() + } + return nil, nil +}