diff --git a/scanners.go b/scanners.go index b5811af..efe803f 100644 --- a/scanners.go +++ b/scanners.go @@ -23,3 +23,24 @@ func ScanAlphaNum(l *Lexer) bool { l.AcceptWhile(alpha + digits) return true } + +// ScanQuotedString returns true if next input tokens is quoted string. Can be used with any type of quotes. +func ScanQuotedString(l *Lexer, quote rune) bool { + start := l.Pos + if l.Next() != quote { + l.Back() + return false + } + for { + ch := l.Next() + switch ch { + case EOF: + l.Pos = start // Return position to start + return false // Unclosed quote string? + case '\\': + l.Next() // Skip next char + case quote: + return true // Closing quote + } + } +} diff --git a/scanners_test.go b/scanners_test.go index cab697e..851d284 100644 --- a/scanners_test.go +++ b/scanners_test.go @@ -51,3 +51,25 @@ func TestScanAlphaNum(t *testing.T) { } } } + +func TestScanQuotedString(t *testing.T) { + testCases := []struct { + Input string + Expected bool + Pos int + }{ + {`asd`, false, 0}, + {`"asd`, false, 0}, + {`"asd"qwe`, true, 5}, + } + for _, tc := range testCases { + l := New(tc.Input) + actual := ScanQuotedString(l, '"') + if actual != tc.Expected { + t.Errorf("Input: %s expected scan result: %v actual: %v", tc.Input, tc.Expected, actual) + } + if l.Pos != tc.Pos { + t.Errorf("Input: %s expected scan position: %d actual: %d", tc.Input, tc.Pos, l.Pos) + } + } +}