.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / honnef.co / go / tools@v0.1.1 / pattern / lexer.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/honnef.co/go/tools@v0.1.1/pattern/lexer.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/honnef.co/go/tools@v0.1.1/pattern/lexer.go
new file mode 100644 (file)
index 0000000..fb72e39
--- /dev/null
@@ -0,0 +1,221 @@
+package pattern
+
+import (
+       "fmt"
+       "go/token"
+       "unicode"
+       "unicode/utf8"
+)
+
+type lexer struct {
+       f *token.File
+
+       input string
+       start int
+       pos   int
+       width int
+       items chan item
+}
+
+type itemType int
+
+const eof = -1
+
+const (
+       itemError itemType = iota
+       itemLeftParen
+       itemRightParen
+       itemLeftBracket
+       itemRightBracket
+       itemTypeName
+       itemVariable
+       itemAt
+       itemColon
+       itemBlank
+       itemString
+       itemEOF
+)
+
+func (typ itemType) String() string {
+       switch typ {
+       case itemError:
+               return "ERROR"
+       case itemLeftParen:
+               return "("
+       case itemRightParen:
+               return ")"
+       case itemLeftBracket:
+               return "["
+       case itemRightBracket:
+               return "]"
+       case itemTypeName:
+               return "TYPE"
+       case itemVariable:
+               return "VAR"
+       case itemAt:
+               return "@"
+       case itemColon:
+               return ":"
+       case itemBlank:
+               return "_"
+       case itemString:
+               return "STRING"
+       case itemEOF:
+               return "EOF"
+       default:
+               return fmt.Sprintf("itemType(%d)", typ)
+       }
+}
+
+type item struct {
+       typ itemType
+       val string
+       pos int
+}
+
+type stateFn func(*lexer) stateFn
+
+func (l *lexer) run() {
+       for state := lexStart; state != nil; {
+               state = state(l)
+       }
+       close(l.items)
+}
+
+func (l *lexer) emitValue(t itemType, value string) {
+       l.items <- item{t, value, l.start}
+       l.start = l.pos
+}
+
+func (l *lexer) emit(t itemType) {
+       l.items <- item{t, l.input[l.start:l.pos], l.start}
+       l.start = l.pos
+}
+
+func lexStart(l *lexer) stateFn {
+       switch r := l.next(); {
+       case r == eof:
+               l.emit(itemEOF)
+               return nil
+       case unicode.IsSpace(r):
+               l.ignore()
+       case r == '(':
+               l.emit(itemLeftParen)
+       case r == ')':
+               l.emit(itemRightParen)
+       case r == '[':
+               l.emit(itemLeftBracket)
+       case r == ']':
+               l.emit(itemRightBracket)
+       case r == '@':
+               l.emit(itemAt)
+       case r == ':':
+               l.emit(itemColon)
+       case r == '_':
+               l.emit(itemBlank)
+       case r == '"':
+               l.backup()
+               return lexString
+       case unicode.IsUpper(r):
+               l.backup()
+               return lexType
+       case unicode.IsLower(r):
+               l.backup()
+               return lexVariable
+       default:
+               return l.errorf("unexpected character %c", r)
+       }
+       return lexStart
+}
+
+func (l *lexer) next() (r rune) {
+       if l.pos >= len(l.input) {
+               l.width = 0
+               return eof
+       }
+       r, l.width = utf8.DecodeRuneInString(l.input[l.pos:])
+
+       if r == '\n' {
+               l.f.AddLine(l.pos)
+       }
+
+       l.pos += l.width
+
+       return r
+}
+
+func (l *lexer) ignore() {
+       l.start = l.pos
+}
+
+func (l *lexer) backup() {
+       l.pos -= l.width
+}
+
+func (l *lexer) errorf(format string, args ...interface{}) stateFn {
+       // TODO(dh): emit position information in errors
+       l.items <- item{
+               itemError,
+               fmt.Sprintf(format, args...),
+               l.start,
+       }
+       return nil
+}
+
+func isAlphaNumeric(r rune) bool {
+       return r >= '0' && r <= '9' ||
+               r >= 'a' && r <= 'z' ||
+               r >= 'A' && r <= 'Z'
+}
+
+func lexString(l *lexer) stateFn {
+       l.next() // skip quote
+       escape := false
+
+       var runes []rune
+       for {
+               switch r := l.next(); r {
+               case eof:
+                       return l.errorf("unterminated string")
+               case '"':
+                       if !escape {
+                               l.emitValue(itemString, string(runes))
+                               return lexStart
+                       } else {
+                               runes = append(runes, '"')
+                               escape = false
+                       }
+               case '\\':
+                       if escape {
+                               runes = append(runes, '\\')
+                               escape = false
+                       } else {
+                               escape = true
+                       }
+               default:
+                       runes = append(runes, r)
+               }
+       }
+}
+
+func lexType(l *lexer) stateFn {
+       l.next()
+       for {
+               if !isAlphaNumeric(l.next()) {
+                       l.backup()
+                       l.emit(itemTypeName)
+                       return lexStart
+               }
+       }
+}
+
+func lexVariable(l *lexer) stateFn {
+       l.next()
+       for {
+               if !isAlphaNumeric(l.next()) {
+                       l.backup()
+                       l.emit(itemVariable)
+                       return lexStart
+               }
+       }
+}