package parser import ( "strings" "asciigoat.org/core/lexer" ) // AcceptQuotedString consumes a quoted string from the source // and returns it unquoted and unescaped func (p *TextParser) AcceptQuotedString() (string, bool, error) { r, _, err := p.ReadRune() switch { case err != nil: // nothing here return "", false, err case r != RuneQuotes: // not for us p.UnreadRune() return "", false, nil default: // let's roll s, err := lexQuotedString(p) switch { case err != nil: // bad quoted string return "", false, err default: // success return s, true, nil } } } func lexQuotedString(p *TextParser) (string, *lexer.Error) { for { r, _, err := p.ReadRune() switch { case err != nil: // incomplete return "", NewErrIncompleteQuotedString(p) case r == RuneQuotes: // end, remove quotes and process escaped characters return lexReturnUnescapedQuotedString(p) case r == RuneEscape: // escaped, take another _, _, err := p.ReadRune() if err != nil { // incomplete return "", NewErrIncompleteQuotedString(p) } case IsNewLine(r): // new lines within quoted values are acceptable p.UnreadRune() p.AcceptNewLine() default: // continue } } } func lexReturnUnescapedQuotedString(p *TextParser) (string, *lexer.Error) { // remove quotes s := p.String() l := len(s) s = s[1 : l-1] if strings.ContainsRune(s, RuneEscape) { // TODO: implement unescaping err := NewError(p.Position(), s, "escaped characters", lexer.ErrNotImplemented) return "", err } return s, nil } // Unquoted removes quotes the content and unescapes the content func Unquoted(s string) (string, error) { var p TextParser if s == "" { return "", nil } p.InitString(s) unquoted, ok, err := p.AcceptQuotedString() switch { case err != nil: // bad string return "", err case ok: // success return unquoted, nil default: // not quoted return s, nil } }