Compare commits

...

4 Commits

Author SHA1 Message Date
eson
89cfda8545 todo 2020-09-23 20:21:41 +08:00
eson
24c816c640 2% 2020-09-22 18:57:30 +08:00
eson
a9054b9704 %1.2 2020-09-21 18:55:32 +08:00
eson
414d979931 1% 2020-09-21 16:15:14 +08:00

View File

@ -1,97 +1,205 @@
package main package main
import ( import (
"strings"
"testing" "testing"
) )
type Type int // type Type int
const ( // const (
TypeChild Type = iota // TypeUnknown Type = iota
TypeChildren
TypeAllChildren
)
type Node struct { // TypeNode
Prev *Node // TypeText
Next *Node // TypeAttribute
Name []rune // )
Type Type
}
// func extractPath(cur *Node) string { // // type Attribute struct {
// var path []byte // // Name []rune
// // Value []rune
// // }
// if cur.Next.Next == nil { // type Node struct {
// return "/" // Parent *Node
// } // Children []*Node
// for ; cur != nil; cur = cur.Next { // Attributes []*Node
// path = append(path, cur.Name...)
// if cur.Next.Next == nil { // Name []rune
// break // Value []rune
// }
// path = append(path, '/') // Type Type
// }
// return string(path)
// } // }
func toString(root *Node) string { type Selection int
var content string
for root != nil { const (
SelUnknown Selection = iota
SelRoot // 根节点
SelSelf // 自身
SelParent // 父节点
SelChildren // 孩子
SelAllChildRen // 所有子孙
SelMethod // 函数类型
SelAttribute // 属性
)
content += string(root.Name) type Predicates struct {
if root.Type == TypeAllChildren { Name []rune
content += "//"
} else {
content += "/"
}
root = root.Next
}
return content
} }
func xPath(spath string) string { type Node struct {
Name []rune // Axis
Value []rune // Name(Axis)::Value
Next *Node
Sel Selection
Pred []*Predicates
}
var path []rune = []rune(spath) // compile 编译
func compile(spath string) (head *Node, tail *Node) {
var path []rune = []rune(strings.TrimSpace(spath))
path = append(path, ' ') path = append(path, ' ')
root := &Node{} var cur *Node
cur := root if path[0] == '/' {
head = &Node{}
head.Sel = SelRoot
head.Next = cur
} else {
head = cur
}
for i := 0; i < len(spath); i++ { // for i := 0; i < len(spath); i++ {
var i = 0
c := path[i]
switch c {
case '/':
if path[i+1] == '/' {
i++
head.Sel = SelAllChildRen
} else {
head.Sel = SelChildren
}
case '.':
head.Sel = SelSelf
case '(':
// 进入递归
i++
start, end := getBrackets(path, len(spath), &i)
h, t := compile(string(path[start:end]))
cur.Next = h
cur = t
case '|':
// 递归
default:
head.Sel = SelUnknown
}
return head, cur
}
func getPredicates(path []rune, limit int, ii *int, cur *Node) []*Predicates {
return nil
}
func getAxes(path []rune, limit int, ii *int, cur *Node) {
i := *ii
for ; i < limit; i++ {
c := path[i] c := path[i]
switch c { switch c {
case '[':
cur.Pred = getPredicates(path, limit, ii, cur)
return
case '/': case '/':
if path[i+1] == '/' { return
cur.Type = TypeAllChildren case ':':
if path[i+1] == ':' {
i++ i++
return
}
panic("':' error")
case '@': //
cur.Sel = SelAttribute
cur.Name = getAttributeName(path, limit, ii)
case '.': // 获取节点
if path[i+1] == '.' {
i++
cur.Sel = SelParent
} else { } else {
cur.Type = TypeChild cur.Sel = SelSelf
} }
return
if len(cur.Name) == 0 { case '(': // function
continue s, e := getBrackets(path, limit, ii)
} cur.Value = path[s:e]
cur.Sel = SelMethod
cur.Next = &Node{Prev: cur} return
cur = cur.Next case '\\': // 转义
// case '(': 先拿括号 i++
fallthrough
default: default:
cur.Name = append(cur.Name, c) cur.Name = append(cur.Name, c)
} }
} }
}
return toString(root) func getAttributeName(path []rune, limit int, ii *int) []rune {
i := *ii
for start := i; i < limit; i++ {
if c, ok := Escape(path, &i); !ok {
switch {
case c >= ' ' && c <= '/':
fallthrough
case c >= ':' && c <= '@':
fallthrough
case c >= '[' && c <= '`':
fallthrough
case c >= '{' && c <= '~':
return path[start:i]
default:
panic("get attribute error")
}
}
}
panic("get attribute error")
}
func getBrackets(path []rune, limit int, ii *int) (start int, end int) {
i := *ii
open := 1
for start := i; i < limit; i++ {
if c, ok := Escape(path, &i); !ok {
switch c {
case '(':
open++
case ')':
open--
}
if open == 0 {
return start, i
}
}
}
panic("can't find ')' close?")
}
// Escape
func Escape(data []rune, i *int) (rune, bool) {
if data[*i] == '\\' {
*i++
return data[*i], true
}
return data[*i], false
} }
func TestMain(t *testing.T) { func TestMain(t *testing.T) {
// t.Error(xPath("/a/../../b/../c//.//")) t.Error(compile("/a/../../b/../c//.//"))
// t.Error(xPath("/a/./b/../../c/")) // t.Error(xPath("/a/./b/../../c/"))
// t.Error(xPath("/")) // t.Error(xPath("/"))
t.Error(xPath("/a/./b/../../c/")) // t.Error(xPath("/a/./b/../../c/"))
// t.Error(xPath("/a//b////c/d//././/..")) // t.Error(xPath("/a//b////c/d//././/.."))
} }