func (this *token_iterator) extract_go_expr() string {
	orig := this.token_index
	prev := this.token().tok
loop:
	for {
		if !this.go_back() {
			return token_items_to_string(this.tokens[:orig])
		}
		switch this.token().tok {
		case token.PERIOD:
			if prev != token.IDENT {
				break loop
			}
		case token.IDENT:
			switch prev {
			case token.PERIOD, token.LBRACK, token.LBRACE, token.LPAREN:
			default:
				break loop
			}
		case token.RBRACE:
			if prev != token.PERIOD {
				break loop
			}
			this.skip_to_balanced_pair()
		case token.RPAREN, token.RBRACK:
			switch prev {
			case token.PERIOD, token.LBRACK, token.LPAREN:
			default:
				break loop
			}
			this.skip_to_balanced_pair()
		default:
			break loop
		}
		prev = this.token().tok
	}
	expr := token_items_to_string(this.tokens[this.token_index+1 : orig])
	if *g_debug {
		log.Printf("extracted expression tokens: %s", expr)
	}
	return expr
}
Starting from the token under the cursor move back and extract something
that resembles a valid Go primary expression. Examples of primary expressions
from Go spec:
x
2
(s + ".txt")
f(3.1415, true)
Point{1, 2}
m["foo"]
s[i : j + 1]
obj.color
f.p[i].x()

As you can see we can move through all of them using balanced bracket
matching and applying simple rules
E.g.
Point{1, 2}.m["foo"].s[i : j + 1].MethodCall(a, func(a, b int) int { return a + b }).
Can be seen as:
Point{    }.m[     ].s[         ].MethodCall(                                      ).
Which boils the rules down to these connected via dots:
ident
ident[]
ident{}
ident()
Of course there are also slightly more complicated rules for brackets:
ident{}.ident()[5][4](), etc.
package gocode
import (
	"bytes"
	"go/ast"
	"go/parser"
	"go/scanner"
	"go/token"
	"log"
)
type cursor_context struct {
	decl         *decl
	partial      string
	struct_field bool
}
type token_iterator struct {
	tokens      []token_item
	token_index int
}
type token_item struct {
	off int
	tok token.Token
	lit string
}
func (i token_item) literal() string {
	if i.tok.IsLiteral() {
		return i.lit
	} else {
		return i.tok.String()
	}
	return ""
}
func new_token_iterator(src []byte, cursor int) token_iterator {
	tokens := make([]token_item, 0, 1000)
	var s scanner.Scanner
	fset := token.NewFileSet()
	file := fset.AddFile("", fset.Base(), len(src))
	s.Init(file, src, nil, 0)
	for {
		pos, tok, lit := s.Scan()
		off := fset.Position(pos).Offset
		if tok == token.EOF || cursor <= off {
			break
		}
		tokens = append(tokens, token_item{
			off: off,
			tok: tok,
			lit: lit,
		})
	}
	return token_iterator{
		tokens:      tokens,
		token_index: len(tokens) - 1,
	}
}
func (this *token_iterator) token() token_item {
	return this.tokens[this.token_index]
}
func (this *token_iterator) go_back() bool {
	if this.token_index <= 0 {
		return false
	}
	this.token_index--
	return true
}
var bracket_pairs_map = map[token.Token]token.Token{
	token.RPAREN: token.LPAREN,
	token.RBRACK: token.LBRACK,
	token.RBRACE: token.LBRACE,
}
func (ti *token_iterator) skip_to_left(left, right token.Token) bool {
	if ti.token().tok == left {
		return true
	}
	balance := 1
	for balance != 0 {
		if !ti.go_back() {
			return false
		}
		switch ti.token().tok {
		case right:
			balance++
		case left:
			balance--
		}
	}
	return true
}
func (this *token_iterator) skip_to_balanced_pair() bool {
	right := this.token().tok
	left := bracket_pairs_map[right]
	return this.skip_to_left(left, right)
}
func (this *token_iterator) skip_to_left_curly() bool {
	return this.skip_to_left(token.LBRACE, token.RBRACE)
}
func (ti *token_iterator) extract_struct_type() string {
	if !ti.skip_to_left_curly() {
		return ""
	}
	if !ti.go_back() {
		return ""
	}
	if ti.token().tok != token.IDENT {
		return ""
	}
	b := ti.token().literal()
	if !ti.go_back() {
		return b
	}
	if ti.token().tok != token.PERIOD {
		return b
	}
	if !ti.go_back() {
		return b
	}
	if ti.token().tok != token.IDENT {
		return b
	}
	return ti.token().literal() + "." + b
}