155
vendor/github.com/hashicorp/go-bexpr/grammar/ast.go
generated
vendored
Normal file
155
vendor/github.com/hashicorp/go-bexpr/grammar/ast.go
generated
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
package grammar
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// TODO - Probably should make most of what is in here un-exported
|
||||
|
||||
type Expression interface {
|
||||
ExpressionDump(w io.Writer, indent string, level int)
|
||||
}
|
||||
|
||||
type UnaryOperator int
|
||||
|
||||
const (
|
||||
UnaryOpNot UnaryOperator = iota
|
||||
)
|
||||
|
||||
func (op UnaryOperator) String() string {
|
||||
switch op {
|
||||
case UnaryOpNot:
|
||||
return "Not"
|
||||
default:
|
||||
return "UNKNOWN"
|
||||
}
|
||||
}
|
||||
|
||||
type BinaryOperator int
|
||||
|
||||
const (
|
||||
BinaryOpAnd BinaryOperator = iota
|
||||
BinaryOpOr
|
||||
)
|
||||
|
||||
func (op BinaryOperator) String() string {
|
||||
switch op {
|
||||
case BinaryOpAnd:
|
||||
return "And"
|
||||
case BinaryOpOr:
|
||||
return "Or"
|
||||
default:
|
||||
return "UNKNOWN"
|
||||
}
|
||||
}
|
||||
|
||||
type MatchOperator int
|
||||
|
||||
const (
|
||||
MatchEqual MatchOperator = iota
|
||||
MatchNotEqual
|
||||
MatchIn
|
||||
MatchNotIn
|
||||
MatchIsEmpty
|
||||
MatchIsNotEmpty
|
||||
MatchMatches
|
||||
MatchNotMatches
|
||||
)
|
||||
|
||||
func (op MatchOperator) String() string {
|
||||
switch op {
|
||||
case MatchEqual:
|
||||
return "Equal"
|
||||
case MatchNotEqual:
|
||||
return "Not Equal"
|
||||
case MatchIn:
|
||||
return "In"
|
||||
case MatchNotIn:
|
||||
return "Not In"
|
||||
case MatchIsEmpty:
|
||||
return "Is Empty"
|
||||
case MatchIsNotEmpty:
|
||||
return "Is Not Empty"
|
||||
case MatchMatches:
|
||||
return "Matches"
|
||||
case MatchNotMatches:
|
||||
return "Not Matches"
|
||||
default:
|
||||
return "UNKNOWN"
|
||||
}
|
||||
}
|
||||
|
||||
type MatchValue struct {
|
||||
Raw string
|
||||
Converted interface{}
|
||||
}
|
||||
|
||||
type UnaryExpression struct {
|
||||
Operator UnaryOperator
|
||||
Operand Expression
|
||||
}
|
||||
|
||||
type BinaryExpression struct {
|
||||
Left Expression
|
||||
Operator BinaryOperator
|
||||
Right Expression
|
||||
}
|
||||
|
||||
type SelectorType uint32
|
||||
|
||||
const (
|
||||
SelectorTypeUnknown = iota
|
||||
SelectorTypeBexpr
|
||||
SelectorTypeJsonPointer
|
||||
)
|
||||
|
||||
type Selector struct {
|
||||
Type SelectorType
|
||||
Path []string
|
||||
}
|
||||
|
||||
func (sel Selector) String() string {
|
||||
if len(sel.Path) == 0 {
|
||||
return ""
|
||||
}
|
||||
switch sel.Type {
|
||||
case SelectorTypeBexpr:
|
||||
return strings.Join(sel.Path, ".")
|
||||
case SelectorTypeJsonPointer:
|
||||
return strings.Join(sel.Path, "/")
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
type MatchExpression struct {
|
||||
Selector Selector
|
||||
Operator MatchOperator
|
||||
Value *MatchValue
|
||||
}
|
||||
|
||||
func (expr *UnaryExpression) ExpressionDump(w io.Writer, indent string, level int) {
|
||||
localIndent := strings.Repeat(indent, level)
|
||||
fmt.Fprintf(w, "%s%s {\n", localIndent, expr.Operator.String())
|
||||
expr.Operand.ExpressionDump(w, indent, level+1)
|
||||
fmt.Fprintf(w, "%s}\n", localIndent)
|
||||
}
|
||||
|
||||
func (expr *BinaryExpression) ExpressionDump(w io.Writer, indent string, level int) {
|
||||
localIndent := strings.Repeat(indent, level)
|
||||
fmt.Fprintf(w, "%s%s {\n", localIndent, expr.Operator.String())
|
||||
expr.Left.ExpressionDump(w, indent, level+1)
|
||||
expr.Right.ExpressionDump(w, indent, level+1)
|
||||
fmt.Fprintf(w, "%s}\n", localIndent)
|
||||
}
|
||||
|
||||
func (expr *MatchExpression) ExpressionDump(w io.Writer, indent string, level int) {
|
||||
switch expr.Operator {
|
||||
case MatchEqual, MatchNotEqual, MatchIn, MatchNotIn:
|
||||
fmt.Fprintf(w, "%[1]s%[3]s {\n%[2]sSelector: %[4]v\n%[2]sValue: %[5]q\n%[1]s}\n", strings.Repeat(indent, level), strings.Repeat(indent, level+1), expr.Operator.String(), expr.Selector, expr.Value.Raw)
|
||||
default:
|
||||
fmt.Fprintf(w, "%[1]s%[3]s {\n%[2]sSelector: %[4]v\n%[1]s}\n", strings.Repeat(indent, level), strings.Repeat(indent, level+1), expr.Operator.String(), expr.Selector)
|
||||
}
|
||||
}
|
||||
3107
vendor/github.com/hashicorp/go-bexpr/grammar/grammar.go
generated
vendored
Normal file
3107
vendor/github.com/hashicorp/go-bexpr/grammar/grammar.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
193
vendor/github.com/hashicorp/go-bexpr/grammar/grammar.peg
generated
vendored
Normal file
193
vendor/github.com/hashicorp/go-bexpr/grammar/grammar.peg
generated
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
{
|
||||
package grammar
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/mitchellh/pointerstructure"
|
||||
)
|
||||
}
|
||||
|
||||
Input <- _? "(" _? expr:OrExpression _? ")" _? EOF {
|
||||
return expr, nil
|
||||
} / _? expr:OrExpression _? EOF {
|
||||
return expr, nil
|
||||
}
|
||||
|
||||
OrExpression <- left:AndExpression _ "or" _ right:OrExpression {
|
||||
return &BinaryExpression{
|
||||
Operator: BinaryOpOr,
|
||||
Left: left.(Expression),
|
||||
Right: right.(Expression),
|
||||
}, nil
|
||||
} / expr:AndExpression {
|
||||
return expr, nil
|
||||
}
|
||||
|
||||
AndExpression <- left:NotExpression _ "and" _ right:AndExpression {
|
||||
return &BinaryExpression{
|
||||
Operator: BinaryOpAnd,
|
||||
Left: left.(Expression),
|
||||
Right: right.(Expression),
|
||||
}, nil
|
||||
} / expr:NotExpression {
|
||||
return expr, nil
|
||||
}
|
||||
|
||||
NotExpression <- "not" _ expr:NotExpression {
|
||||
if unary, ok := expr.(*UnaryExpression); ok && unary.Operator == UnaryOpNot {
|
||||
// small optimization to get rid unnecessary levels of AST nodes
|
||||
// for things like: not not foo == 3 which is equivalent to foo == 3
|
||||
return unary.Operand, nil
|
||||
}
|
||||
|
||||
return &UnaryExpression{
|
||||
Operator: UnaryOpNot,
|
||||
Operand: expr.(Expression),
|
||||
}, nil
|
||||
} / expr:ParenthesizedExpression {
|
||||
return expr, nil
|
||||
}
|
||||
|
||||
ParenthesizedExpression "grouping" <- "(" _? expr:OrExpression _? ")" {
|
||||
return expr, nil
|
||||
} / expr:MatchExpression {
|
||||
return expr, nil
|
||||
} / "(" _? OrExpression _? !")" &{
|
||||
return false, errors.New("Unmatched parentheses")
|
||||
}
|
||||
|
||||
MatchExpression "match" <- MatchSelectorOpValue / MatchSelectorOp / MatchValueOpSelector
|
||||
|
||||
MatchSelectorOpValue "match" <- selector:Selector operator:(MatchEqual / MatchNotEqual / MatchContains / MatchNotContains / MatchMatches / MatchNotMatches) value:Value {
|
||||
return &MatchExpression{Selector: selector.(Selector), Operator: operator.(MatchOperator), Value: value.(*MatchValue)}, nil
|
||||
}
|
||||
|
||||
MatchSelectorOp "match" <- selector:Selector operator:(MatchIsEmpty / MatchIsNotEmpty) {
|
||||
return &MatchExpression{Selector: selector.(Selector), Operator: operator.(MatchOperator), Value: nil}, nil
|
||||
}
|
||||
|
||||
MatchValueOpSelector "match" <- value:Value operator:(MatchIn / MatchNotIn) selector:Selector {
|
||||
return &MatchExpression{Selector: selector.(Selector), Operator: operator.(MatchOperator), Value: value.(*MatchValue)}, nil
|
||||
} / Value operator:(MatchIn / MatchNotIn) !Selector &{
|
||||
return false, errors.New("Invalid selector")
|
||||
}
|
||||
|
||||
MatchEqual <- _? "==" _? {
|
||||
return MatchEqual, nil
|
||||
}
|
||||
MatchNotEqual <- _? "!=" _? {
|
||||
return MatchNotEqual, nil
|
||||
}
|
||||
MatchIsEmpty <- _ "is" _ "empty" {
|
||||
return MatchIsEmpty, nil
|
||||
}
|
||||
MatchIsNotEmpty <- _"is" _ "not" _ "empty" {
|
||||
return MatchIsNotEmpty, nil
|
||||
}
|
||||
MatchIn <- _ "in" _ {
|
||||
return MatchIn, nil
|
||||
}
|
||||
MatchNotIn <- _ "not" _ "in" _ {
|
||||
return MatchNotIn, nil
|
||||
}
|
||||
MatchContains <- _ "contains" _ {
|
||||
return MatchIn, nil
|
||||
}
|
||||
MatchNotContains <- _ "not" _ "contains" _ {
|
||||
return MatchNotIn, nil
|
||||
}
|
||||
MatchMatches <- _ "matches" _ {
|
||||
return MatchMatches, nil
|
||||
}
|
||||
MatchNotMatches <- _ "not" _ "matches" _ {
|
||||
return MatchNotMatches, nil
|
||||
}
|
||||
|
||||
Selector "selector" <- first:Identifier rest:SelectorOrIndex* {
|
||||
sel := Selector{
|
||||
Type: SelectorTypeBexpr,
|
||||
Path: []string{first.(string)},
|
||||
}
|
||||
if rest != nil {
|
||||
for _, v := range rest.([]interface{}) {
|
||||
sel.Path = append(sel.Path, v.(string))
|
||||
}
|
||||
}
|
||||
return sel, nil
|
||||
} / '"' ptrsegs:JsonPointerSegment* '"' {
|
||||
sel := Selector{
|
||||
Type: SelectorTypeJsonPointer,
|
||||
}
|
||||
if ptrsegs != nil {
|
||||
for _, v := range ptrsegs.([]interface{}) {
|
||||
sel.Path = append(sel.Path, v.(string))
|
||||
}
|
||||
}
|
||||
|
||||
// Validate and cache
|
||||
ptrStr := fmt.Sprintf("/%s", strings.Join(sel.Path, "/"))
|
||||
ptr, err := pointerstructure.Parse(ptrStr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error validating json pointer: %w", err)
|
||||
}
|
||||
sel.Path = ptr.Parts
|
||||
|
||||
return sel, nil
|
||||
}
|
||||
|
||||
JsonPointerSegment <- '/' ident:[\pL\pN-_.~:|]+ {
|
||||
return string(c.text)[1:], nil
|
||||
}
|
||||
|
||||
Identifier <- [a-zA-Z] [a-zA-Z0-9_/]* {
|
||||
return string(c.text), nil
|
||||
}
|
||||
|
||||
SelectorOrIndex <- "." ident:Identifier {
|
||||
return ident, nil
|
||||
} / expr:IndexExpression {
|
||||
return expr, nil
|
||||
} / "." idx:[0-9]+ {
|
||||
return string(c.text)[1:], nil
|
||||
}
|
||||
|
||||
IndexExpression "index" <- "[" _? lit:StringLiteral _? "]" {
|
||||
return lit, nil
|
||||
} / "[" _? !StringLiteral &{
|
||||
return false, errors.New("Invalid index")
|
||||
} / "[" _? StringLiteral _? !"]" &{
|
||||
return false, errors.New("Unclosed index expression")
|
||||
}
|
||||
|
||||
Value "value" <- selector:Selector {
|
||||
return &MatchValue{Raw:selector.(Selector).String()}, nil
|
||||
} / n:NumberLiteral {
|
||||
return &MatchValue{Raw: n.(string)}, nil
|
||||
} / s:StringLiteral {
|
||||
return &MatchValue{Raw: s.(string)}, nil
|
||||
}
|
||||
|
||||
NumberLiteral "number" <- "-"? IntegerOrFloat &AfterNumbers {
|
||||
return string(c.text), nil
|
||||
} / "-"? IntegerOrFloat !AfterNumbers &{
|
||||
return false, errors.New("Invalid number literal")
|
||||
}
|
||||
|
||||
AfterNumbers <- &(_ / EOF / ")")
|
||||
|
||||
IntegerOrFloat <- ("0" / [1-9][0-9]*) ("." [0-9]+)?
|
||||
|
||||
StringLiteral "string" <- ('`' RawStringChar* '`' / '"' DoubleStringChar* '"') {
|
||||
return strconv.Unquote(string(c.text))
|
||||
} / ('`' RawStringChar* / '"' DoubleStringChar*) EOF &{
|
||||
return false, errors.New("Unterminated string literal")
|
||||
}
|
||||
|
||||
RawStringChar <- !'`' .
|
||||
DoubleStringChar <- !'"' .
|
||||
|
||||
_ "whitespace" <- [ \t\r\n]+
|
||||
|
||||
EOF <- !.
|
||||
Reference in New Issue
Block a user