consul/vendor/github.com/hashicorp/go-bexpr/grammar.peg

157 lines
4.2 KiB
Plaintext

{
package bexpr
import (
"strconv"
"strings"
)
}
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) 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
}
Selector "selector" <- first:Identifier rest:SelectorOrIndex* {
sel := Selector{
first.(string),
}
if rest != nil {
for _, v := range rest.([]interface{}) {
sel = append(sel, v.(string))
}
}
return sel, 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
}
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:strings.Join(selector.(Selector), ".")}, 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 <- !.