-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparser.go
More file actions
134 lines (116 loc) · 3.72 KB
/
parser.go
File metadata and controls
134 lines (116 loc) · 3.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package risorxpath
import (
"context"
"github.com/risor-io/risor/object"
"github.com/risor-io/risor/op"
"github.com/speedata/goxpath"
"github.com/speedata/risorxml"
)
type xpathParser struct {
// The XPath parser.
value *goxpath.Parser
ctx *xpathContext
}
func (xp *xpathParser) evaluate(ctx context.Context, args ...object.Object) object.Object {
if len(args) != 1 {
return object.ArgsErrorf("args error: xpath.evaluate() takes exactly 1 argument (%d given)", len(args))
}
firstArg := args[0]
if firstArg.Type() != "string" {
return object.TypeErrorf("xpath.evaluate() takes a string as argument, got %s", firstArg.Type())
}
seq, err := xp.value.Evaluate(firstArg.Interface().(string))
if err != nil {
return object.NewError(err)
}
seqList := newSequence(nil)
for _, itm := range seq {
seqList.seq = append(seqList.seq, itm)
}
return seqList
}
func (xp *xpathParser) setVariable(ctx context.Context, args ...object.Object) object.Object {
if len(args) != 2 {
return object.ArgsErrorf("args error: xpath.set_variable() takes exactly 2 arguments (%d given)", len(args))
}
firstArg := args[0]
secondArg := args[1]
if firstArg.Type() != "string" {
return object.TypeErrorf("xpath.set_variable() takes a string as first argument, got %s", firstArg.Type())
}
if secondArg.Type() != "list" {
return object.TypeErrorf("xpath.set_variable() takes a list as second argument, got %s", secondArg.Type())
}
varname := firstArg.Interface().(string)
seq := goxpath.Sequence{}
for _, itm := range secondArg.Interface().([]any) {
switch t := itm.(type) {
case string:
seq = append(seq, itm)
case goxpath.Sequence:
seq = append(seq, t...)
default:
seq = append(seq, itm)
}
}
xp.value.SetVariable(varname, seq)
return nil
}
// Type of the object.
func (xp *xpathParser) Type() object.Type {
return "xpath.parser"
}
// Inspect returns a string representation of the given object.
func (xp *xpathParser) Inspect() string {
return "xpath.parser"
}
// Interface converts the given object to a native Go value.
func (xp *xpathParser) Interface() interface{} {
return xp.value
}
// Returns True if the given object is equal to this object.
func (xp *xpathParser) Equals(other object.Object) object.Object {
return object.NewBool(xp.value == other.(*xpathParser).value)
}
// GetAttr returns the attribute with the given name from this object.
func (xp *xpathParser) GetAttr(name string) (object.Object, bool) {
switch name {
case "evaluate":
if xp.ctx != nil && xp.ctx.namespaces != nil {
for k, v := range xp.ctx.namespaces.Interface().(map[string]any) {
xp.ctx.value.Namespaces[k] = v.(string)
}
}
return object.NewBuiltin("xpath.evaluate", xp.evaluate), true
case "ctx":
if xp.ctx != nil {
return xp.ctx, true
}
xp.ctx = &xpathContext{
value: xp.value.Ctx,
}
return xp.ctx, true
case "set_variable":
return object.NewBuiltin("xpath.set_variable", xp.setVariable), true
case "xml_document":
return &risorxml.XMLDocument{Value: xp.value.XMLDocument()}, true
}
return nil, false
}
// SetAttr sets the attribute with the given name on this object.
func (xp *xpathParser) SetAttr(name string, value object.Object) error {
return object.Errorf("xpath.parser: cannot set attribute %s", name)
}
// IsTruthy returns true if the object is considered "truthy".
func (xp *xpathParser) IsTruthy() bool {
return true
}
// RunOperation runs an operation on this object with the given
// right-hand side object.
func (xp *xpathParser) RunOperation(opType op.BinaryOpType, right object.Object) object.Object {
return object.TypeErrorf("xpath.parser: cannot run operation %s on %s", opType, xp.Type())
}
// Cost returns the incremental processing cost of this object.
func (xp *xpathParser) Cost() int {
return 0
}