Parser context
This commit is contained in:
parent
76ee42a0a6
commit
937c8b31d7
|
@ -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"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue