.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / honnef.co / go / tools@v0.1.1 / pattern / parser.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/honnef.co/go/tools@v0.1.1/pattern/parser.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/honnef.co/go/tools@v0.1.1/pattern/parser.go
new file mode 100644 (file)
index 0000000..009238b
--- /dev/null
@@ -0,0 +1,455 @@
+package pattern
+
+import (
+       "fmt"
+       "go/ast"
+       "go/token"
+       "reflect"
+)
+
+type Pattern struct {
+       Root Node
+       // Relevant contains instances of ast.Node that could potentially
+       // initiate a successful match of the pattern.
+       Relevant []reflect.Type
+}
+
+func MustParse(s string) Pattern {
+       p := &Parser{AllowTypeInfo: true}
+       pat, err := p.Parse(s)
+       if err != nil {
+               panic(err)
+       }
+       return pat
+}
+
+func roots(node Node) []reflect.Type {
+       switch node := node.(type) {
+       case Or:
+               var out []reflect.Type
+               for _, el := range node.Nodes {
+                       out = append(out, roots(el)...)
+               }
+               return out
+       case Not:
+               return roots(node.Node)
+       case Binding:
+               return roots(node.Node)
+       case Nil, nil:
+               // this branch is reached via bindings
+               return allTypes
+       default:
+               Ts, ok := nodeToASTTypes[reflect.TypeOf(node)]
+               if !ok {
+                       panic(fmt.Sprintf("internal error: unhandled type %T", node))
+               }
+               return Ts
+       }
+}
+
+var allTypes = []reflect.Type{
+       reflect.TypeOf((*ast.RangeStmt)(nil)),
+       reflect.TypeOf((*ast.AssignStmt)(nil)),
+       reflect.TypeOf((*ast.IndexExpr)(nil)),
+       reflect.TypeOf((*ast.Ident)(nil)),
+       reflect.TypeOf((*ast.ValueSpec)(nil)),
+       reflect.TypeOf((*ast.GenDecl)(nil)),
+       reflect.TypeOf((*ast.BinaryExpr)(nil)),
+       reflect.TypeOf((*ast.ForStmt)(nil)),
+       reflect.TypeOf((*ast.ArrayType)(nil)),
+       reflect.TypeOf((*ast.DeferStmt)(nil)),
+       reflect.TypeOf((*ast.MapType)(nil)),
+       reflect.TypeOf((*ast.ReturnStmt)(nil)),
+       reflect.TypeOf((*ast.SliceExpr)(nil)),
+       reflect.TypeOf((*ast.StarExpr)(nil)),
+       reflect.TypeOf((*ast.UnaryExpr)(nil)),
+       reflect.TypeOf((*ast.SendStmt)(nil)),
+       reflect.TypeOf((*ast.SelectStmt)(nil)),
+       reflect.TypeOf((*ast.ImportSpec)(nil)),
+       reflect.TypeOf((*ast.IfStmt)(nil)),
+       reflect.TypeOf((*ast.GoStmt)(nil)),
+       reflect.TypeOf((*ast.Field)(nil)),
+       reflect.TypeOf((*ast.SelectorExpr)(nil)),
+       reflect.TypeOf((*ast.StructType)(nil)),
+       reflect.TypeOf((*ast.KeyValueExpr)(nil)),
+       reflect.TypeOf((*ast.FuncType)(nil)),
+       reflect.TypeOf((*ast.FuncLit)(nil)),
+       reflect.TypeOf((*ast.FuncDecl)(nil)),
+       reflect.TypeOf((*ast.ChanType)(nil)),
+       reflect.TypeOf((*ast.CallExpr)(nil)),
+       reflect.TypeOf((*ast.CaseClause)(nil)),
+       reflect.TypeOf((*ast.CommClause)(nil)),
+       reflect.TypeOf((*ast.CompositeLit)(nil)),
+       reflect.TypeOf((*ast.EmptyStmt)(nil)),
+       reflect.TypeOf((*ast.SwitchStmt)(nil)),
+       reflect.TypeOf((*ast.TypeSwitchStmt)(nil)),
+       reflect.TypeOf((*ast.TypeAssertExpr)(nil)),
+       reflect.TypeOf((*ast.TypeSpec)(nil)),
+       reflect.TypeOf((*ast.InterfaceType)(nil)),
+       reflect.TypeOf((*ast.BranchStmt)(nil)),
+       reflect.TypeOf((*ast.IncDecStmt)(nil)),
+       reflect.TypeOf((*ast.BasicLit)(nil)),
+}
+
+var nodeToASTTypes = map[reflect.Type][]reflect.Type{
+       reflect.TypeOf(String("")):       nil,
+       reflect.TypeOf(Token(0)):         nil,
+       reflect.TypeOf(List{}):           {reflect.TypeOf((*ast.BlockStmt)(nil)), reflect.TypeOf((*ast.FieldList)(nil))},
+       reflect.TypeOf(Builtin{}):        {reflect.TypeOf((*ast.Ident)(nil))},
+       reflect.TypeOf(Object{}):         {reflect.TypeOf((*ast.Ident)(nil))},
+       reflect.TypeOf(Function{}):       {reflect.TypeOf((*ast.Ident)(nil)), reflect.TypeOf((*ast.SelectorExpr)(nil))},
+       reflect.TypeOf(Any{}):            allTypes,
+       reflect.TypeOf(RangeStmt{}):      {reflect.TypeOf((*ast.RangeStmt)(nil))},
+       reflect.TypeOf(AssignStmt{}):     {reflect.TypeOf((*ast.AssignStmt)(nil))},
+       reflect.TypeOf(IndexExpr{}):      {reflect.TypeOf((*ast.IndexExpr)(nil))},
+       reflect.TypeOf(Ident{}):          {reflect.TypeOf((*ast.Ident)(nil))},
+       reflect.TypeOf(ValueSpec{}):      {reflect.TypeOf((*ast.ValueSpec)(nil))},
+       reflect.TypeOf(GenDecl{}):        {reflect.TypeOf((*ast.GenDecl)(nil))},
+       reflect.TypeOf(BinaryExpr{}):     {reflect.TypeOf((*ast.BinaryExpr)(nil))},
+       reflect.TypeOf(ForStmt{}):        {reflect.TypeOf((*ast.ForStmt)(nil))},
+       reflect.TypeOf(ArrayType{}):      {reflect.TypeOf((*ast.ArrayType)(nil))},
+       reflect.TypeOf(DeferStmt{}):      {reflect.TypeOf((*ast.DeferStmt)(nil))},
+       reflect.TypeOf(MapType{}):        {reflect.TypeOf((*ast.MapType)(nil))},
+       reflect.TypeOf(ReturnStmt{}):     {reflect.TypeOf((*ast.ReturnStmt)(nil))},
+       reflect.TypeOf(SliceExpr{}):      {reflect.TypeOf((*ast.SliceExpr)(nil))},
+       reflect.TypeOf(StarExpr{}):       {reflect.TypeOf((*ast.StarExpr)(nil))},
+       reflect.TypeOf(UnaryExpr{}):      {reflect.TypeOf((*ast.UnaryExpr)(nil))},
+       reflect.TypeOf(SendStmt{}):       {reflect.TypeOf((*ast.SendStmt)(nil))},
+       reflect.TypeOf(SelectStmt{}):     {reflect.TypeOf((*ast.SelectStmt)(nil))},
+       reflect.TypeOf(ImportSpec{}):     {reflect.TypeOf((*ast.ImportSpec)(nil))},
+       reflect.TypeOf(IfStmt{}):         {reflect.TypeOf((*ast.IfStmt)(nil))},
+       reflect.TypeOf(GoStmt{}):         {reflect.TypeOf((*ast.GoStmt)(nil))},
+       reflect.TypeOf(Field{}):          {reflect.TypeOf((*ast.Field)(nil))},
+       reflect.TypeOf(SelectorExpr{}):   {reflect.TypeOf((*ast.SelectorExpr)(nil))},
+       reflect.TypeOf(StructType{}):     {reflect.TypeOf((*ast.StructType)(nil))},
+       reflect.TypeOf(KeyValueExpr{}):   {reflect.TypeOf((*ast.KeyValueExpr)(nil))},
+       reflect.TypeOf(FuncType{}):       {reflect.TypeOf((*ast.FuncType)(nil))},
+       reflect.TypeOf(FuncLit{}):        {reflect.TypeOf((*ast.FuncLit)(nil))},
+       reflect.TypeOf(FuncDecl{}):       {reflect.TypeOf((*ast.FuncDecl)(nil))},
+       reflect.TypeOf(ChanType{}):       {reflect.TypeOf((*ast.ChanType)(nil))},
+       reflect.TypeOf(CallExpr{}):       {reflect.TypeOf((*ast.CallExpr)(nil))},
+       reflect.TypeOf(CaseClause{}):     {reflect.TypeOf((*ast.CaseClause)(nil))},
+       reflect.TypeOf(CommClause{}):     {reflect.TypeOf((*ast.CommClause)(nil))},
+       reflect.TypeOf(CompositeLit{}):   {reflect.TypeOf((*ast.CompositeLit)(nil))},
+       reflect.TypeOf(EmptyStmt{}):      {reflect.TypeOf((*ast.EmptyStmt)(nil))},
+       reflect.TypeOf(SwitchStmt{}):     {reflect.TypeOf((*ast.SwitchStmt)(nil))},
+       reflect.TypeOf(TypeSwitchStmt{}): {reflect.TypeOf((*ast.TypeSwitchStmt)(nil))},
+       reflect.TypeOf(TypeAssertExpr{}): {reflect.TypeOf((*ast.TypeAssertExpr)(nil))},
+       reflect.TypeOf(TypeSpec{}):       {reflect.TypeOf((*ast.TypeSpec)(nil))},
+       reflect.TypeOf(InterfaceType{}):  {reflect.TypeOf((*ast.InterfaceType)(nil))},
+       reflect.TypeOf(BranchStmt{}):     {reflect.TypeOf((*ast.BranchStmt)(nil))},
+       reflect.TypeOf(IncDecStmt{}):     {reflect.TypeOf((*ast.IncDecStmt)(nil))},
+       reflect.TypeOf(BasicLit{}):       {reflect.TypeOf((*ast.BasicLit)(nil))},
+}
+
+var requiresTypeInfo = map[string]bool{
+       "Function": true,
+       "Builtin":  true,
+       "Object":   true,
+}
+
+type Parser struct {
+       // Allow nodes that rely on type information
+       AllowTypeInfo bool
+
+       lex   *lexer
+       cur   item
+       last  *item
+       items chan item
+}
+
+func (p *Parser) Parse(s string) (Pattern, error) {
+       p.cur = item{}
+       p.last = nil
+       p.items = nil
+
+       fset := token.NewFileSet()
+       p.lex = &lexer{
+               f:     fset.AddFile("<input>", -1, len(s)),
+               input: s,
+               items: make(chan item),
+       }
+       go p.lex.run()
+       p.items = p.lex.items
+       root, err := p.node()
+       if err != nil {
+               // drain lexer if parsing failed
+               for range p.lex.items {
+               }
+               return Pattern{}, err
+       }
+       if item := <-p.lex.items; item.typ != itemEOF {
+               return Pattern{}, fmt.Errorf("unexpected token %s after end of pattern", item.typ)
+       }
+       return Pattern{
+               Root:     root,
+               Relevant: roots(root),
+       }, nil
+}
+
+func (p *Parser) next() item {
+       if p.last != nil {
+               n := *p.last
+               p.last = nil
+               return n
+       }
+       var ok bool
+       p.cur, ok = <-p.items
+       if !ok {
+               p.cur = item{typ: eof}
+       }
+       return p.cur
+}
+
+func (p *Parser) rewind() {
+       p.last = &p.cur
+}
+
+func (p *Parser) peek() item {
+       n := p.next()
+       p.rewind()
+       return n
+}
+
+func (p *Parser) accept(typ itemType) (item, bool) {
+       n := p.next()
+       if n.typ == typ {
+               return n, true
+       }
+       p.rewind()
+       return item{}, false
+}
+
+func (p *Parser) unexpectedToken(valid string) error {
+       if p.cur.typ == itemError {
+               return fmt.Errorf("error lexing input: %s", p.cur.val)
+       }
+       var got string
+       switch p.cur.typ {
+       case itemTypeName, itemVariable, itemString:
+               got = p.cur.val
+       default:
+               got = "'" + p.cur.typ.String() + "'"
+       }
+
+       pos := p.lex.f.Position(token.Pos(p.cur.pos))
+       return fmt.Errorf("%s: expected %s, found %s", pos, valid, got)
+}
+
+func (p *Parser) node() (Node, error) {
+       if _, ok := p.accept(itemLeftParen); !ok {
+               return nil, p.unexpectedToken("'('")
+       }
+       typ, ok := p.accept(itemTypeName)
+       if !ok {
+               return nil, p.unexpectedToken("Node type")
+       }
+
+       var objs []Node
+       for {
+               if _, ok := p.accept(itemRightParen); ok {
+                       break
+               } else {
+                       p.rewind()
+                       obj, err := p.object()
+                       if err != nil {
+                               return nil, err
+                       }
+                       objs = append(objs, obj)
+               }
+       }
+
+       return p.populateNode(typ.val, objs)
+}
+
+func populateNode(typ string, objs []Node, allowTypeInfo bool) (Node, error) {
+       T, ok := structNodes[typ]
+       if !ok {
+               return nil, fmt.Errorf("unknown node %s", typ)
+       }
+
+       if !allowTypeInfo && requiresTypeInfo[typ] {
+               return nil, fmt.Errorf("Node %s requires type information", typ)
+       }
+
+       pv := reflect.New(T)
+       v := pv.Elem()
+
+       if v.NumField() == 1 {
+               f := v.Field(0)
+               if f.Type().Kind() == reflect.Slice {
+                       // Variadic node
+                       f.Set(reflect.AppendSlice(f, reflect.ValueOf(objs)))
+                       return v.Interface().(Node), nil
+               }
+       }
+       if len(objs) != v.NumField() {
+               return nil, fmt.Errorf("tried to initialize node %s with %d values, expected %d", typ, len(objs), v.NumField())
+       }
+       for i := 0; i < v.NumField(); i++ {
+               f := v.Field(i)
+               if f.Kind() == reflect.String {
+                       if obj, ok := objs[i].(String); ok {
+                               f.Set(reflect.ValueOf(string(obj)))
+                       } else {
+                               return nil, fmt.Errorf("first argument of (Binding name node) must be string, but got %s", objs[i])
+                       }
+               } else {
+                       f.Set(reflect.ValueOf(objs[i]))
+               }
+       }
+       return v.Interface().(Node), nil
+}
+
+func (p *Parser) populateNode(typ string, objs []Node) (Node, error) {
+       return populateNode(typ, objs, p.AllowTypeInfo)
+}
+
+var structNodes = map[string]reflect.Type{
+       "Any":            reflect.TypeOf(Any{}),
+       "Ellipsis":       reflect.TypeOf(Ellipsis{}),
+       "List":           reflect.TypeOf(List{}),
+       "Binding":        reflect.TypeOf(Binding{}),
+       "RangeStmt":      reflect.TypeOf(RangeStmt{}),
+       "AssignStmt":     reflect.TypeOf(AssignStmt{}),
+       "IndexExpr":      reflect.TypeOf(IndexExpr{}),
+       "Ident":          reflect.TypeOf(Ident{}),
+       "Builtin":        reflect.TypeOf(Builtin{}),
+       "ValueSpec":      reflect.TypeOf(ValueSpec{}),
+       "GenDecl":        reflect.TypeOf(GenDecl{}),
+       "BinaryExpr":     reflect.TypeOf(BinaryExpr{}),
+       "ForStmt":        reflect.TypeOf(ForStmt{}),
+       "ArrayType":      reflect.TypeOf(ArrayType{}),
+       "DeferStmt":      reflect.TypeOf(DeferStmt{}),
+       "MapType":        reflect.TypeOf(MapType{}),
+       "ReturnStmt":     reflect.TypeOf(ReturnStmt{}),
+       "SliceExpr":      reflect.TypeOf(SliceExpr{}),
+       "StarExpr":       reflect.TypeOf(StarExpr{}),
+       "UnaryExpr":      reflect.TypeOf(UnaryExpr{}),
+       "SendStmt":       reflect.TypeOf(SendStmt{}),
+       "SelectStmt":     reflect.TypeOf(SelectStmt{}),
+       "ImportSpec":     reflect.TypeOf(ImportSpec{}),
+       "IfStmt":         reflect.TypeOf(IfStmt{}),
+       "GoStmt":         reflect.TypeOf(GoStmt{}),
+       "Field":          reflect.TypeOf(Field{}),
+       "SelectorExpr":   reflect.TypeOf(SelectorExpr{}),
+       "StructType":     reflect.TypeOf(StructType{}),
+       "KeyValueExpr":   reflect.TypeOf(KeyValueExpr{}),
+       "FuncType":       reflect.TypeOf(FuncType{}),
+       "FuncLit":        reflect.TypeOf(FuncLit{}),
+       "FuncDecl":       reflect.TypeOf(FuncDecl{}),
+       "ChanType":       reflect.TypeOf(ChanType{}),
+       "CallExpr":       reflect.TypeOf(CallExpr{}),
+       "CaseClause":     reflect.TypeOf(CaseClause{}),
+       "CommClause":     reflect.TypeOf(CommClause{}),
+       "CompositeLit":   reflect.TypeOf(CompositeLit{}),
+       "EmptyStmt":      reflect.TypeOf(EmptyStmt{}),
+       "SwitchStmt":     reflect.TypeOf(SwitchStmt{}),
+       "TypeSwitchStmt": reflect.TypeOf(TypeSwitchStmt{}),
+       "TypeAssertExpr": reflect.TypeOf(TypeAssertExpr{}),
+       "TypeSpec":       reflect.TypeOf(TypeSpec{}),
+       "InterfaceType":  reflect.TypeOf(InterfaceType{}),
+       "BranchStmt":     reflect.TypeOf(BranchStmt{}),
+       "IncDecStmt":     reflect.TypeOf(IncDecStmt{}),
+       "BasicLit":       reflect.TypeOf(BasicLit{}),
+       "Object":         reflect.TypeOf(Object{}),
+       "Function":       reflect.TypeOf(Function{}),
+       "Or":             reflect.TypeOf(Or{}),
+       "Not":            reflect.TypeOf(Not{}),
+}
+
+func (p *Parser) object() (Node, error) {
+       n := p.next()
+       switch n.typ {
+       case itemLeftParen:
+               p.rewind()
+               node, err := p.node()
+               if err != nil {
+                       return node, err
+               }
+               if p.peek().typ == itemColon {
+                       p.next()
+                       tail, err := p.object()
+                       if err != nil {
+                               return node, err
+                       }
+                       return List{Head: node, Tail: tail}, nil
+               }
+               return node, nil
+       case itemLeftBracket:
+               p.rewind()
+               return p.array()
+       case itemVariable:
+               v := n
+               if v.val == "nil" {
+                       return Nil{}, nil
+               }
+               var b Binding
+               if _, ok := p.accept(itemAt); ok {
+                       o, err := p.node()
+                       if err != nil {
+                               return nil, err
+                       }
+                       b = Binding{
+                               Name: v.val,
+                               Node: o,
+                       }
+               } else {
+                       p.rewind()
+                       b = Binding{Name: v.val}
+               }
+               if p.peek().typ == itemColon {
+                       p.next()
+                       tail, err := p.object()
+                       if err != nil {
+                               return b, err
+                       }
+                       return List{Head: b, Tail: tail}, nil
+               }
+               return b, nil
+       case itemBlank:
+               return Any{}, nil
+       case itemString:
+               return String(n.val), nil
+       default:
+               return nil, p.unexpectedToken("object")
+       }
+}
+
+func (p *Parser) array() (Node, error) {
+       if _, ok := p.accept(itemLeftBracket); !ok {
+               return nil, p.unexpectedToken("'['")
+       }
+
+       var objs []Node
+       for {
+               if _, ok := p.accept(itemRightBracket); ok {
+                       break
+               } else {
+                       p.rewind()
+                       obj, err := p.object()
+                       if err != nil {
+                               return nil, err
+                       }
+                       objs = append(objs, obj)
+               }
+       }
+
+       tail := List{}
+       for i := len(objs) - 1; i >= 0; i-- {
+               l := List{
+                       Head: objs[i],
+                       Tail: tail,
+               }
+               tail = l
+       }
+       return tail, nil
+}
+
+/*
+Node ::= itemLeftParen itemTypeName Object* itemRightParen
+Object ::= Node | Array | Binding | itemVariable | itemBlank | itemString
+Array := itemLeftBracket Object* itemRightBracket
+Array := Object itemColon Object
+Binding ::= itemVariable itemAt Node
+*/