func (s *Scope) SObjects() string {
    so := ""
    set := make(map[string]bool, 10)
    for _,tp := range s.Tps {
        if _,ok := set[tp.S]; !ok && strings.HasPrefix(tp.S, "?v") {
            so += tp.S + " "
            set[tp.S] = true
        }
        if _,ok := set[tp.O]; !ok && strings.HasPrefix(tp.O, "?v") {
            so += tp.O + " "
            set[tp.O] = true
        }
    }
    return so
}
SObjects returns the set of variables at the subject and object position
package autocompletion
import (
    "strings"
    "text/template"
    "bytes"
    "strconv"
)
type Type uint
const (
    NONE Type = iota
    CLASS
    PREDICATE
    PATH
    SUBJECT
    OBJECT
)
type triplePattern struct {
    S, P, O string
    Leaf bool
}
type Scope struct {
    Tps []triplePattern
    scope map[string]bool
    template *template.Template
    Keyword string
    pathLength int
    Pof string
    Prefix string
    Prefixes map[string]string
}
func NewScope() *Scope {
    tmpl := `
        {{range $prefix, $uri := .Prefixes}}
        PREFIX {{$prefix}}: <{{$uri}}>
        {{end}}
        SELECT DISTINCT {{.Pof}}
        WHERE {
        {{range .Tps}}
            {{.S}} {{.P}} {{.O}} .
        {{end}}
        {{if .Keyword}}
            FILTER regex(?POF, "{{.Keyword}}", "i")
        {{else if .Prefix}}
            FILTER regex(?POF, "^{{.Prefix}}")
        {{end}}
        }
        LIMIT 10
    `
    return NewScopeWithTemplate(tmpl)
}
func NewScopeWithTemplate(tmpl string) *Scope {
    scope := &Scope{ Pof : "?POF" }
    tp, _ := template.New("rec").Parse(tmpl)
    scope.template = tp
    scope.Prefixes = make(map[string]string)
    return scope
}
func Reset(s *Sparql) {
    s.Reset()
    s.skipBegin = 0
    s.Keyword = ""
    s.Prefix = ""
    s.pathLength = 0
    s.Pof = "?POF"
    s.Tps = s.Tps[:0]
}