1
0
Fork 0

Parser context

This commit is contained in:
Gregory Eremin 2015-02-17 22:47:02 +07:00
parent 76ee42a0a6
commit 937c8b31d7
1 changed files with 120 additions and 0 deletions

120
parser/context.go Normal file
View File

@ -0,0 +1,120 @@
package parser
import (
"strconv"
"strings"
)
type (
context struct {
exps []expectation
}
// Context building block
expectation struct {
typ expectationType
key string // Object key
index int64 // Array index
}
// Type of expectation: object or array
expectationType int
)
const (
unknown expectationType = iota
object
array
)
func (c *context) compare(c2 *context) bool {
if len(c.exps) != len(c2.exps) {
return false
}
for i, exp := range c.exps {
exp2 := c2.exps[i]
if exp.typ != exp2.typ {
return false
}
switch exp.typ {
case array:
if exp.index != -1 && exp2.index != -1 && exp.index != exp2.index {
return false
}
case object:
if exp.key != exp2.key {
return false
}
}
}
return true
}
func (c *context) push(typ expectationType) {
c.exps = append(c.exps, expectation{
typ: typ,
})
}
func (c *context) pop() {
if len(c.exps) == 0 {
return
}
c.exps = c.exps[:len(c.exps)-1]
}
func (c *context) setKey(key string) {
c.exps[len(c.exps)-1].key = key
}
func (c *context) setIndex(i int64) {
c.exps[len(c.exps)-1].index = i
}
func parseSelectors(sels []string) map[string]*context {
ctxs := map[string]*context{}
for _, sel := range sels {
ctxs[sel] = &context{
exps: parseSelector(sel),
}
}
return ctxs
}
func parseSelector(sel string) []expectation {
exps := []expectation{}
parts := strings.Split(sel[1:], "/")
for _, part := range parts {
c := expectation{}
if len(part) > 2 && part[:1] == "[" && part[len(part)-1:] == "]" {
c.typ = array
part = part[1 : len(part)-1]
if part == "*" {
c.index = -1
} else if i, err := strconv.ParseInt(part, 10, 64); err == nil {
c.index = i
} else {
panic("Array index should be numeric: " + part)
}
} else {
c.typ = object
c.key = part
}
exps = append(exps, c)
}
return exps
}
func (e expectationType) String() string {
switch e {
case array:
return "Index"
case object:
return "Key"
default:
return "Unknown"
}
}