cloudflare/pint

Public

mirrored from https://github.com/cloudflare/pintAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.74.6

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

internal/parser/decode.go

101lines · modecode

1package parser
2
3import (
4 "encoding/json"
5
6 promParser "github.com/prometheus/prometheus/promql/parser"
7)
8
9type PromQLExpr struct {
10 Value *YamlNode
11 SyntaxError error
12 Query *PromQLNode
13}
14
15// PromQLNode is used to turn the parsed PromQL query expression into a tree.
16// This allows us to walk the tree up & down and look for either parents
17// or children of specific type. Which is useful if you, for example,
18// want to check if all vector selectors are wrapped inside function
19// calls etc.
20type PromQLNode struct {
21 Parent *PromQLNode
22 Expr promParser.Node
23 Children []*PromQLNode
24}
25
26func (pn PromQLNode) MarshalJSON() ([]byte, error) {
27 return json.Marshal(pn.Expr.String())
28}
29
30// Tree takes a parsed PromQL node and turns it into a Node
31// instance with parent and children populated.
32func tree(expr promParser.Node, parent *PromQLNode) *PromQLNode {
33 n := PromQLNode{
34 Parent: parent,
35 Expr: expr,
36 Children: nil,
37 }
38 for _, child := range promParser.Children(expr) {
39 n.Children = append(n.Children, tree(child, &n))
40 }
41
42 return &n
43}
44
45// WalkUpExpr allows to iterate a promQLNode node looking for
46// parents of specific type.
47// Prometheus parser returns interfaces which makes it more difficult
48// to figure out what kind of node we're dealing with, hence this
49// helper takes a type parameter it tries to cast.
50// It starts by checking the node passed to it and then walks
51// up by visiting all parent nodes.
52func WalkUpExpr[T promParser.Node](node *PromQLNode) (nodes []*PromQLNode) {
53 if node == nil {
54 return nodes
55 }
56 if _, ok := node.Expr.(T); ok {
57 nodes = append(nodes, node)
58 }
59 if node.Parent != nil {
60 nodes = append(nodes, WalkUpExpr[T](node.Parent)...)
61 }
62 return nodes
63}
64
65// WalkDownExpr works just like WalkUpExpr but it walks the tree
66// down, visiting all children.
67// It also starts by checking the node passed to it before walking
68// down the tree.
69func WalkDownExpr[T promParser.Node](node *PromQLNode) (nodes []*PromQLNode) {
70 if _, ok := node.Expr.(T); ok {
71 nodes = append(nodes, node)
72 }
73 for _, child := range node.Children {
74 nodes = append(nodes, WalkDownExpr[T](child)...)
75 }
76 return nodes
77}
78
79// WalkUpParent works like WalkUpExpr but checks the parent
80// (if present) instead of the node itself.
81// It returns the nodes where the parent is of given type.
82func WalkUpParent[T promParser.Node](node *PromQLNode) (nodes []*PromQLNode) {
83 if node == nil || node.Parent == nil {
84 return nodes
85 }
86 if _, ok := node.Parent.Expr.(T); ok {
87 nodes = append(nodes, node)
88 }
89 if node.Parent != nil {
90 nodes = append(nodes, WalkUpParent[T](node.Parent)...)
91 }
92 return nodes
93}
94
95func DecodeExpr(expr string) (*PromQLNode, error) {
96 node, err := promParser.ParseExpr(expr)
97 if err != nil {
98 return nil, err
99 }
100 return tree(node, nil), nil
101}
102