diff --git a/vendor/github.com/hashicorp/hil/ast/arithmetic_op.go b/vendor/github.com/hashicorp/hil/ast/arithmetic_op.go index e36dd42dc..18880c604 100644 --- a/vendor/github.com/hashicorp/hil/ast/arithmetic_op.go +++ b/vendor/github.com/hashicorp/hil/ast/arithmetic_op.go @@ -5,9 +5,20 @@ type ArithmeticOp int const ( ArithmeticOpInvalid ArithmeticOp = 0 - ArithmeticOpAdd ArithmeticOp = iota + + ArithmeticOpAdd ArithmeticOp = iota ArithmeticOpSub ArithmeticOpMul ArithmeticOpDiv ArithmeticOpMod + + ArithmeticOpLogicalAnd + ArithmeticOpLogicalOr + + ArithmeticOpEqual + ArithmeticOpNotEqual + ArithmeticOpLessThan + ArithmeticOpLessThanOrEqual + ArithmeticOpGreaterThan + ArithmeticOpGreaterThanOrEqual ) diff --git a/vendor/github.com/hashicorp/hil/ast/conditional.go b/vendor/github.com/hashicorp/hil/ast/conditional.go new file mode 100644 index 000000000..be48f89d4 --- /dev/null +++ b/vendor/github.com/hashicorp/hil/ast/conditional.go @@ -0,0 +1,36 @@ +package ast + +import ( + "fmt" +) + +type Conditional struct { + CondExpr Node + TrueExpr Node + FalseExpr Node + Posx Pos +} + +// Accept passes the given visitor to the child nodes in this order: +// CondExpr, TrueExpr, FalseExpr. It then finally passes itself to the visitor. +func (n *Conditional) Accept(v Visitor) Node { + n.CondExpr = n.CondExpr.Accept(v) + n.TrueExpr = n.TrueExpr.Accept(v) + n.FalseExpr = n.FalseExpr.Accept(v) + + return v(n) +} + +func (n *Conditional) Pos() Pos { + return n.Posx +} + +func (n *Conditional) Type(Scope) (Type, error) { + // This is not actually a useful value; the type checker ignores + // this function when analyzing conditionals, just as with Arithmetic. + return TypeInt, nil +} + +func (n *Conditional) GoString() string { + return fmt.Sprintf("*%#v", *n) +} diff --git a/vendor/github.com/hashicorp/hil/ast/literal.go b/vendor/github.com/hashicorp/hil/ast/literal.go index 1714ff026..8149d495d 100644 --- a/vendor/github.com/hashicorp/hil/ast/literal.go +++ b/vendor/github.com/hashicorp/hil/ast/literal.go @@ -2,6 +2,7 @@ package ast import ( "fmt" + "reflect" ) // LiteralNode represents a single literal value, such as "foo" or @@ -12,6 +13,51 @@ type LiteralNode struct { Posx Pos } +// NewLiteralNode returns a new literal node representing the given +// literal Go value, which must correspond to one of the primitive types +// supported by HIL. Lists and maps cannot currently be constructed via +// this function. +// +// If an inappropriately-typed value is provided, this function will +// return an error. The main intended use of this function is to produce +// "synthetic" literals from constants in code, where the value type is +// well known at compile time. To easily store these in global variables, +// see also MustNewLiteralNode. +func NewLiteralNode(value interface{}, pos Pos) (*LiteralNode, error) { + goType := reflect.TypeOf(value) + var hilType Type + + switch goType.Kind() { + case reflect.Bool: + hilType = TypeBool + case reflect.Int: + hilType = TypeInt + case reflect.Float64: + hilType = TypeFloat + case reflect.String: + hilType = TypeString + default: + return nil, fmt.Errorf("unsupported literal node type: %T", value) + } + + return &LiteralNode{ + Value: value, + Typex: hilType, + Posx: pos, + }, nil +} + +// MustNewLiteralNode wraps NewLiteralNode and panics if an error is +// returned, thus allowing valid literal nodes to be easily assigned to +// global variables. +func MustNewLiteralNode(value interface{}, pos Pos) *LiteralNode { + node, err := NewLiteralNode(value, pos) + if err != nil { + panic(err) + } + return node +} + func (n *LiteralNode) Accept(v Visitor) Node { return v(n) } diff --git a/vendor/github.com/hashicorp/hil/builtins.go b/vendor/github.com/hashicorp/hil/builtins.go index 9b6a8c2f4..909c788a2 100644 --- a/vendor/github.com/hashicorp/hil/builtins.go +++ b/vendor/github.com/hashicorp/hil/builtins.go @@ -30,6 +30,11 @@ func registerBuiltins(scope *ast.BasicScope) *ast.BasicScope { // Math operations scope.FuncMap["__builtin_IntMath"] = builtinIntMath() scope.FuncMap["__builtin_FloatMath"] = builtinFloatMath() + scope.FuncMap["__builtin_BoolCompare"] = builtinBoolCompare() + scope.FuncMap["__builtin_FloatCompare"] = builtinFloatCompare() + scope.FuncMap["__builtin_IntCompare"] = builtinIntCompare() + scope.FuncMap["__builtin_StringCompare"] = builtinStringCompare() + scope.FuncMap["__builtin_Logical"] = builtinLogical() return scope } @@ -99,6 +104,136 @@ func builtinIntMath() ast.Function { } } +func builtinBoolCompare() ast.Function { + return ast.Function{ + ArgTypes: []ast.Type{ast.TypeInt, ast.TypeBool, ast.TypeBool}, + Variadic: false, + ReturnType: ast.TypeBool, + Callback: func(args []interface{}) (interface{}, error) { + op := args[0].(ast.ArithmeticOp) + lhs := args[1].(bool) + rhs := args[2].(bool) + + switch op { + case ast.ArithmeticOpEqual: + return lhs == rhs, nil + case ast.ArithmeticOpNotEqual: + return lhs != rhs, nil + default: + return nil, errors.New("invalid comparison operation") + } + }, + } +} + +func builtinFloatCompare() ast.Function { + return ast.Function{ + ArgTypes: []ast.Type{ast.TypeInt, ast.TypeFloat, ast.TypeFloat}, + Variadic: false, + ReturnType: ast.TypeBool, + Callback: func(args []interface{}) (interface{}, error) { + op := args[0].(ast.ArithmeticOp) + lhs := args[1].(float64) + rhs := args[2].(float64) + + switch op { + case ast.ArithmeticOpEqual: + return lhs == rhs, nil + case ast.ArithmeticOpNotEqual: + return lhs != rhs, nil + case ast.ArithmeticOpLessThan: + return lhs < rhs, nil + case ast.ArithmeticOpLessThanOrEqual: + return lhs <= rhs, nil + case ast.ArithmeticOpGreaterThan: + return lhs > rhs, nil + case ast.ArithmeticOpGreaterThanOrEqual: + return lhs >= rhs, nil + default: + return nil, errors.New("invalid comparison operation") + } + }, + } +} + +func builtinIntCompare() ast.Function { + return ast.Function{ + ArgTypes: []ast.Type{ast.TypeInt, ast.TypeInt, ast.TypeInt}, + Variadic: false, + ReturnType: ast.TypeBool, + Callback: func(args []interface{}) (interface{}, error) { + op := args[0].(ast.ArithmeticOp) + lhs := args[1].(int) + rhs := args[2].(int) + + switch op { + case ast.ArithmeticOpEqual: + return lhs == rhs, nil + case ast.ArithmeticOpNotEqual: + return lhs != rhs, nil + case ast.ArithmeticOpLessThan: + return lhs < rhs, nil + case ast.ArithmeticOpLessThanOrEqual: + return lhs <= rhs, nil + case ast.ArithmeticOpGreaterThan: + return lhs > rhs, nil + case ast.ArithmeticOpGreaterThanOrEqual: + return lhs >= rhs, nil + default: + return nil, errors.New("invalid comparison operation") + } + }, + } +} + +func builtinStringCompare() ast.Function { + return ast.Function{ + ArgTypes: []ast.Type{ast.TypeInt, ast.TypeString, ast.TypeString}, + Variadic: false, + ReturnType: ast.TypeBool, + Callback: func(args []interface{}) (interface{}, error) { + op := args[0].(ast.ArithmeticOp) + lhs := args[1].(string) + rhs := args[2].(string) + + switch op { + case ast.ArithmeticOpEqual: + return lhs == rhs, nil + case ast.ArithmeticOpNotEqual: + return lhs != rhs, nil + default: + return nil, errors.New("invalid comparison operation") + } + }, + } +} + +func builtinLogical() ast.Function { + return ast.Function{ + ArgTypes: []ast.Type{ast.TypeInt}, + Variadic: true, + VariadicType: ast.TypeBool, + ReturnType: ast.TypeBool, + Callback: func(args []interface{}) (interface{}, error) { + op := args[0].(ast.ArithmeticOp) + result := args[1].(bool) + for _, raw := range args[2:] { + arg := raw.(bool) + switch op { + case ast.ArithmeticOpLogicalOr: + result = result || arg + case ast.ArithmeticOpLogicalAnd: + result = result && arg + default: + return nil, errors.New("invalid logical operator") + } + } + + return result, nil + }, + } +} + func builtinFloatToInt() ast.Function { return ast.Function{ ArgTypes: []ast.Type{ast.TypeFloat}, diff --git a/vendor/github.com/hashicorp/hil/check_types.go b/vendor/github.com/hashicorp/hil/check_types.go index ec9ae7bbc..9346c4cf1 100644 --- a/vendor/github.com/hashicorp/hil/check_types.go +++ b/vendor/github.com/hashicorp/hil/check_types.go @@ -67,6 +67,9 @@ func (v *TypeCheck) visit(raw ast.Node) ast.Node { case *ast.Call: tc := &typeCheckCall{n} result, err = tc.TypeCheck(v) + case *ast.Conditional: + tc := &typeCheckConditional{n} + result, err = tc.TypeCheck(v) case *ast.Index: tc := &typeCheckIndex{n} result, err = tc.TypeCheck(v) @@ -113,6 +116,18 @@ func (tc *typeCheckArithmetic) TypeCheck(v *TypeCheck) (ast.Node, error) { exprs[len(tc.n.Exprs)-1-i] = v.StackPop() } + switch tc.n.Op { + case ast.ArithmeticOpLogicalAnd, ast.ArithmeticOpLogicalOr: + return tc.checkLogical(v, exprs) + case ast.ArithmeticOpEqual, ast.ArithmeticOpNotEqual, ast.ArithmeticOpLessThan, ast.ArithmeticOpGreaterThan, ast.ArithmeticOpGreaterThanOrEqual, ast.ArithmeticOpLessThanOrEqual: + return tc.checkComparison(v, exprs) + default: + return tc.checkNumeric(v, exprs) + } + +} + +func (tc *typeCheckArithmetic) checkNumeric(v *TypeCheck, exprs []ast.Type) (ast.Node, error) { // Determine the resulting type we want. We do this by going over // every expression until we find one with a type we recognize. // We do this because the first expr might be a string ("var.foo") @@ -177,6 +192,116 @@ func (tc *typeCheckArithmetic) TypeCheck(v *TypeCheck) (ast.Node, error) { }, nil } +func (tc *typeCheckArithmetic) checkComparison(v *TypeCheck, exprs []ast.Type) (ast.Node, error) { + + if len(exprs) != 2 { + // This should never happen, because the parser never produces + // nodes that violate this. + return nil, fmt.Errorf( + "comparison operators must have exactly two operands", + ) + } + + // The first operand always dictates the type for a comparison. + compareFunc := "" + compareType := exprs[0] + switch compareType { + case ast.TypeBool: + compareFunc = "__builtin_BoolCompare" + case ast.TypeFloat: + compareFunc = "__builtin_FloatCompare" + case ast.TypeInt: + compareFunc = "__builtin_IntCompare" + case ast.TypeString: + compareFunc = "__builtin_StringCompare" + default: + return nil, fmt.Errorf( + "comparison operators apply only to bool, float, int, and string", + ) + } + + // Verify (and possibly, convert) the args + for i, arg := range exprs { + if arg != compareType { + cn := v.ImplicitConversion(exprs[i], compareType, tc.n.Exprs[i]) + if cn != nil { + tc.n.Exprs[i] = cn + continue + } + + return nil, fmt.Errorf( + "operand %d should be %s, got %s", + i+1, compareType, arg, + ) + } + } + + // Only ints and floats can have the <, >, <= and >= operators applied + switch tc.n.Op { + case ast.ArithmeticOpEqual, ast.ArithmeticOpNotEqual: + // anything goes + default: + switch compareType { + case ast.TypeFloat, ast.TypeInt: + // fine + default: + return nil, fmt.Errorf( + "<, >, <= and >= may apply only to int and float values", + ) + } + } + + // Comparison operators always return bool + v.StackPush(ast.TypeBool) + + // Replace our node with a call to the proper function. This isn't + // type checked but we already verified types. + args := make([]ast.Node, len(tc.n.Exprs)+1) + args[0] = &ast.LiteralNode{ + Value: tc.n.Op, + Typex: ast.TypeInt, + Posx: tc.n.Pos(), + } + copy(args[1:], tc.n.Exprs) + return &ast.Call{ + Func: compareFunc, + Args: args, + Posx: tc.n.Pos(), + }, nil +} + +func (tc *typeCheckArithmetic) checkLogical(v *TypeCheck, exprs []ast.Type) (ast.Node, error) { + for i, t := range exprs { + if t != ast.TypeBool { + cn := v.ImplicitConversion(t, ast.TypeBool, tc.n.Exprs[i]) + if cn == nil { + return nil, fmt.Errorf( + "logical operators require boolean operands, not %s", + t, + ) + } + tc.n.Exprs[i] = cn + } + } + + // Return type is always boolean + v.StackPush(ast.TypeBool) + + // Arithmetic nodes are replaced with a call to a built-in function + args := make([]ast.Node, len(tc.n.Exprs)+1) + args[0] = &ast.LiteralNode{ + Value: tc.n.Op, + Typex: ast.TypeInt, + Posx: tc.n.Pos(), + } + copy(args[1:], tc.n.Exprs) + return &ast.Call{ + Func: "__builtin_Logical", + Args: args, + Posx: tc.n.Pos(), + }, nil +} + type typeCheckCall struct { n *ast.Call } @@ -240,6 +365,79 @@ func (tc *typeCheckCall) TypeCheck(v *TypeCheck) (ast.Node, error) { return tc.n, nil } +type typeCheckConditional struct { + n *ast.Conditional +} + +func (tc *typeCheckConditional) TypeCheck(v *TypeCheck) (ast.Node, error) { + // On the stack we have the types of the condition, true and false + // expressions, but they are in reverse order. + falseType := v.StackPop() + trueType := v.StackPop() + condType := v.StackPop() + + if condType != ast.TypeBool { + cn := v.ImplicitConversion(condType, ast.TypeBool, tc.n.CondExpr) + if cn == nil { + return nil, fmt.Errorf( + "condition must be type bool, not %s", condType.Printable(), + ) + } + tc.n.CondExpr = cn + } + + // The types of the true and false expression must match + if trueType != falseType { + + // Since passing around stringified versions of other types is + // common, we pragmatically allow the false expression to dictate + // the result type when the true expression is a string. + if trueType == ast.TypeString { + cn := v.ImplicitConversion(trueType, falseType, tc.n.TrueExpr) + if cn == nil { + return nil, fmt.Errorf( + "true and false expression types must match; have %s and %s", + trueType.Printable(), falseType.Printable(), + ) + } + tc.n.TrueExpr = cn + trueType = falseType + } else { + cn := v.ImplicitConversion(falseType, trueType, tc.n.FalseExpr) + if cn == nil { + return nil, fmt.Errorf( + "true and false expression types must match; have %s and %s", + trueType.Printable(), falseType.Printable(), + ) + } + tc.n.FalseExpr = cn + falseType = trueType + } + } + + // Currently list and map types cannot be used, because we cannot + // generally assert that their element types are consistent. + // Such support might be added later, either by improving the type + // system or restricting usage to only variable and literal expressions, + // but for now this is simply prohibited because it doesn't seem to + // be a common enough case to be worth the complexity. + switch trueType { + case ast.TypeList: + return nil, fmt.Errorf( + "conditional operator cannot be used with list values", + ) + case ast.TypeMap: + return nil, fmt.Errorf( + "conditional operator cannot be used with map values", + ) + } + + // Result type (guaranteed to also match falseType due to the above) + v.StackPush(trueType) + + return tc.n, nil +} + type typeCheckOutput struct { n *ast.Output } diff --git a/vendor/github.com/hashicorp/hil/eval.go b/vendor/github.com/hashicorp/hil/eval.go index 04b4f8530..5c7afb024 100644 --- a/vendor/github.com/hashicorp/hil/eval.go +++ b/vendor/github.com/hashicorp/hil/eval.go @@ -232,6 +232,8 @@ func evalNode(raw ast.Node) (EvalNode, error) { return &evalIndex{n}, nil case *ast.Call: return &evalCall{n}, nil + case *ast.Conditional: + return &evalConditional{n}, nil case *ast.Output: return &evalOutput{n}, nil case *ast.LiteralNode: @@ -274,6 +276,23 @@ func (v *evalCall) Eval(s ast.Scope, stack *ast.Stack) (interface{}, ast.Type, e return result, function.ReturnType, nil } +type evalConditional struct{ *ast.Conditional } + +func (v *evalConditional) Eval(s ast.Scope, stack *ast.Stack) (interface{}, ast.Type, error) { + // On the stack we have literal nodes representing the resulting values + // of the condition, true and false expressions, but they are in reverse + // order. + falseLit := stack.Pop().(*ast.LiteralNode) + trueLit := stack.Pop().(*ast.LiteralNode) + condLit := stack.Pop().(*ast.LiteralNode) + + if condLit.Value.(bool) { + return trueLit.Value, trueLit.Typex, nil + } else { + return falseLit.Value, trueLit.Typex, nil + } +} + type evalIndex struct{ *ast.Index } func (v *evalIndex) Eval(scope ast.Scope, stack *ast.Stack) (interface{}, ast.Type, error) { diff --git a/vendor/github.com/hashicorp/hil/parser/binary_op.go b/vendor/github.com/hashicorp/hil/parser/binary_op.go index c43c5eb02..2e013e01d 100644 --- a/vendor/github.com/hashicorp/hil/parser/binary_op.go +++ b/vendor/github.com/hashicorp/hil/parser/binary_op.go @@ -16,6 +16,22 @@ func init() { // the *lowest* precedence first. Operators within the same group // have left-to-right associativity. binaryOps = []map[scanner.TokenType]ast.ArithmeticOp{ + { + scanner.OR: ast.ArithmeticOpLogicalOr, + }, + { + scanner.AND: ast.ArithmeticOpLogicalAnd, + }, + { + scanner.EQUAL: ast.ArithmeticOpEqual, + scanner.NOTEQUAL: ast.ArithmeticOpNotEqual, + }, + { + scanner.GT: ast.ArithmeticOpGreaterThan, + scanner.GTE: ast.ArithmeticOpGreaterThanOrEqual, + scanner.LT: ast.ArithmeticOpLessThan, + scanner.LTE: ast.ArithmeticOpLessThanOrEqual, + }, { scanner.PLUS: ast.ArithmeticOpAdd, scanner.MINUS: ast.ArithmeticOpSub, diff --git a/vendor/github.com/hashicorp/hil/parser/parser.go b/vendor/github.com/hashicorp/hil/parser/parser.go index 26cc7aaa6..d7a461323 100644 --- a/vendor/github.com/hashicorp/hil/parser/parser.go +++ b/vendor/github.com/hashicorp/hil/parser/parser.go @@ -191,7 +191,56 @@ func (p *parser) ParseInterpolation() (ast.Node, error) { } func (p *parser) ParseExpression() (ast.Node, error) { - return p.parseBinaryOps(binaryOps) + return p.parseTernaryCond() +} + +func (p *parser) parseTernaryCond() (ast.Node, error) { + // The ternary condition operator (.. ? .. : ..) behaves somewhat + // like a binary operator except that the "operator" is itself + // an expression enclosed in two punctuation characters. + // The middle expression is parsed as if the ? and : symbols + // were parentheses. The "rhs" (the "false expression") is then + // treated right-associatively so it behaves similarly to the + // middle in terms of precedence. + + startPos := p.peeker.Peek().Pos + + var cond, trueExpr, falseExpr ast.Node + var err error + + cond, err = p.parseBinaryOps(binaryOps) + if err != nil { + return nil, err + } + + next := p.peeker.Peek() + if next.Type != scanner.QUESTION { + return cond, nil + } + + p.peeker.Read() // eat question mark + + trueExpr, err = p.ParseExpression() + if err != nil { + return nil, err + } + + colon := p.peeker.Read() + if colon.Type != scanner.COLON { + return nil, ExpectationError(":", colon) + } + + falseExpr, err = p.ParseExpression() + if err != nil { + return nil, err + } + + return &ast.Conditional{ + CondExpr: cond, + TrueExpr: trueExpr, + FalseExpr: falseExpr, + Posx: startPos, + }, nil } // parseBinaryOps calls itself recursively to work through all of the @@ -348,6 +397,30 @@ func (p *parser) ParseExpressionTerm() (ast.Node, error) { Posx: opTok.Pos, }, nil + case scanner.BANG: + opTok := p.peeker.Read() + // important to use ParseExpressionTerm rather than ParseExpression + // here, otherwise we can capture a following binary expression into + // our negation. + operand, err := p.ParseExpressionTerm() + if err != nil { + return nil, err + } + // The AST currently represents binary negation as an equality + // test with "false". + return &ast.Arithmetic{ + Op: ast.ArithmeticOpEqual, + Exprs: []ast.Node{ + &ast.LiteralNode{ + Value: false, + Typex: ast.TypeBool, + Posx: opTok.Pos, + }, + operand, + }, + Posx: opTok.Pos, + }, nil + case scanner.IDENTIFIER: return p.ParseScopeInteraction() diff --git a/vendor/github.com/hashicorp/hil/scanner/scanner.go b/vendor/github.com/hashicorp/hil/scanner/scanner.go index 8089eaa21..e448f13bf 100644 --- a/vendor/github.com/hashicorp/hil/scanner/scanner.go +++ b/vendor/github.com/hashicorp/hil/scanner/scanner.go @@ -168,7 +168,7 @@ func scanInterpolationToken(s string, startPos ast.Pos) (*Token, int, ast.Pos) { var token *Token switch next { - case '(', ')', '[', ']', ',', '.', '+', '-', '*', '/', '%': + case '(', ')', '[', ']', ',', '.', '+', '-', '*', '/', '%', '?', ':': // Easy punctuation symbols that don't have any special meaning // during scanning, and that stand for themselves in the // TokenType enumeration. @@ -189,6 +189,91 @@ func scanInterpolationToken(s string, startPos ast.Pos) (*Token, int, ast.Pos) { Content: s[:1], Pos: pos, } + case '!': + if len(s) >= 2 && s[:2] == "!=" { + token = &Token{ + Type: NOTEQUAL, + Content: s[:2], + Pos: pos, + } + } else { + token = &Token{ + Type: BANG, + Content: s[:1], + Pos: pos, + } + } + case '<': + if len(s) >= 2 && s[:2] == "<=" { + token = &Token{ + Type: LTE, + Content: s[:2], + Pos: pos, + } + } else { + token = &Token{ + Type: LT, + Content: s[:1], + Pos: pos, + } + } + case '>': + if len(s) >= 2 && s[:2] == ">=" { + token = &Token{ + Type: GTE, + Content: s[:2], + Pos: pos, + } + } else { + token = &Token{ + Type: GT, + Content: s[:1], + Pos: pos, + } + } + case '=': + if len(s) >= 2 && s[:2] == "==" { + token = &Token{ + Type: EQUAL, + Content: s[:2], + Pos: pos, + } + } else { + // A single equals is not a valid operator + token = &Token{ + Type: INVALID, + Content: s[:1], + Pos: pos, + } + } + case '&': + if len(s) >= 2 && s[:2] == "&&" { + token = &Token{ + Type: AND, + Content: s[:2], + Pos: pos, + } + } else { + token = &Token{ + Type: INVALID, + Content: s[:1], + Pos: pos, + } + } + case '|': + if len(s) >= 2 && s[:2] == "||" { + token = &Token{ + Type: OR, + Content: s[:2], + Pos: pos, + } + } else { + token = &Token{ + Type: INVALID, + Content: s[:1], + Pos: pos, + } + } default: if next >= '0' && next <= '9' { num, numType := scanNumber(s) diff --git a/vendor/github.com/hashicorp/hil/scanner/token.go b/vendor/github.com/hashicorp/hil/scanner/token.go index b63d59acd..b6c82ae9b 100644 --- a/vendor/github.com/hashicorp/hil/scanner/token.go +++ b/vendor/github.com/hashicorp/hil/scanner/token.go @@ -48,6 +48,20 @@ const ( SLASH TokenType = '/' PERCENT TokenType = '%' + AND TokenType = '∧' + OR TokenType = '∨' + BANG TokenType = '!' + + EQUAL TokenType = '=' + NOTEQUAL TokenType = '≠' + GT TokenType = '>' + LT TokenType = '<' + GTE TokenType = '≥' + LTE TokenType = '≤' + + QUESTION TokenType = '?' + COLON TokenType = ':' + EOF TokenType = '␄' // Produced for sequences that cannot be understood as valid tokens @@ -73,6 +87,16 @@ func (t *Token) String() string { return fmt.Sprintf("opening quote") case CQUOTE: return fmt.Sprintf("closing quote") + case AND: + return "&&" + case OR: + return "||" + case NOTEQUAL: + return "!=" + case GTE: + return ">=" + case LTE: + return "<=" default: // The remaining token types have content that // speaks for itself. diff --git a/vendor/github.com/hashicorp/hil/scanner/tokentype_string.go b/vendor/github.com/hashicorp/hil/scanner/tokentype_string.go index 7185db000..a602f5fdd 100644 --- a/vendor/github.com/hashicorp/hil/scanner/tokentype_string.go +++ b/vendor/github.com/hashicorp/hil/scanner/tokentype_string.go @@ -4,32 +4,43 @@ package scanner import "fmt" -const _TokenType_name = "BEGINPERCENTOPARENCPARENSTARPLUSCOMMAMINUSPERIODSLASHBOOLFLOATINTEGERSTRINGOBRACKETCBRACKETIDENTIFIERLITERALENDOQUOTECQUOTEEOFINVALID" +const _TokenType_name = "BANGBEGINPERCENTOPARENCPARENSTARPLUSCOMMAMINUSPERIODSLASHCOLONLTEQUALGTQUESTIONBOOLFLOATINTEGERSTRINGOBRACKETCBRACKETIDENTIFIERLITERALENDOQUOTECQUOTEANDORNOTEQUALLTEGTEEOFINVALID" var _TokenType_map = map[TokenType]string{ - 36: _TokenType_name[0:5], - 37: _TokenType_name[5:12], - 40: _TokenType_name[12:18], - 41: _TokenType_name[18:24], - 42: _TokenType_name[24:28], - 43: _TokenType_name[28:32], - 44: _TokenType_name[32:37], - 45: _TokenType_name[37:42], - 46: _TokenType_name[42:48], - 47: _TokenType_name[48:53], - 66: _TokenType_name[53:57], - 70: _TokenType_name[57:62], - 73: _TokenType_name[62:69], - 83: _TokenType_name[69:75], - 91: _TokenType_name[75:83], - 93: _TokenType_name[83:91], - 105: _TokenType_name[91:101], - 111: _TokenType_name[101:108], - 125: _TokenType_name[108:111], - 8220: _TokenType_name[111:117], - 8221: _TokenType_name[117:123], - 9220: _TokenType_name[123:126], - 65533: _TokenType_name[126:133], + 33: _TokenType_name[0:4], + 36: _TokenType_name[4:9], + 37: _TokenType_name[9:16], + 40: _TokenType_name[16:22], + 41: _TokenType_name[22:28], + 42: _TokenType_name[28:32], + 43: _TokenType_name[32:36], + 44: _TokenType_name[36:41], + 45: _TokenType_name[41:46], + 46: _TokenType_name[46:52], + 47: _TokenType_name[52:57], + 58: _TokenType_name[57:62], + 60: _TokenType_name[62:64], + 61: _TokenType_name[64:69], + 62: _TokenType_name[69:71], + 63: _TokenType_name[71:79], + 66: _TokenType_name[79:83], + 70: _TokenType_name[83:88], + 73: _TokenType_name[88:95], + 83: _TokenType_name[95:101], + 91: _TokenType_name[101:109], + 93: _TokenType_name[109:117], + 105: _TokenType_name[117:127], + 111: _TokenType_name[127:134], + 125: _TokenType_name[134:137], + 8220: _TokenType_name[137:143], + 8221: _TokenType_name[143:149], + 8743: _TokenType_name[149:152], + 8744: _TokenType_name[152:154], + 8800: _TokenType_name[154:162], + 8804: _TokenType_name[162:165], + 8805: _TokenType_name[165:168], + 9220: _TokenType_name[168:171], + 65533: _TokenType_name[171:178], } func (i TokenType) String() string { diff --git a/vendor/vendor.json b/vendor/vendor.json index 66a4e98db..127e4a8ec 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -1586,28 +1586,28 @@ "revisionTime": "2016-11-30T20:58:18Z" }, { - "checksumSHA1": "/TJCBetWCMVsOpehJzVk3S/xtWM=", + "checksumSHA1": "xONRNgLDc5OqCUmyDN3iBRKmKB0=", "path": "github.com/hashicorp/hil", - "revision": "76d6c606283f17780baaad00df4b6ce8e9fca941", - "revisionTime": "2016-11-20T06:09:40Z" + "revision": "bf046eec69cc383b7f32c47990336409601c8116", + "revisionTime": "2016-12-04T02:32:26Z" }, { - "checksumSHA1": "YPJwewz3dAqEWOGP2qIIWeCufF0=", + "checksumSHA1": "oZ2a2x9qyHqvqJdv/Du3LGeaFdA=", "path": "github.com/hashicorp/hil/ast", - "revision": "76d6c606283f17780baaad00df4b6ce8e9fca941", - "revisionTime": "2016-11-20T06:09:40Z" + "revision": "bf046eec69cc383b7f32c47990336409601c8116", + "revisionTime": "2016-12-04T02:32:26Z" }, { - "checksumSHA1": "+mEEIN7pTcda+Vu837rQBkHYzao=", + "checksumSHA1": "p/zZysJW/AaPXXPCI20nM2arPnw=", "path": "github.com/hashicorp/hil/parser", - "revision": "76d6c606283f17780baaad00df4b6ce8e9fca941", - "revisionTime": "2016-11-20T06:09:40Z" + "revision": "bf046eec69cc383b7f32c47990336409601c8116", + "revisionTime": "2016-12-04T02:32:26Z" }, { - "checksumSHA1": "2aIAMbqPrE0qyYoJSL6qjVm+Tt0=", + "checksumSHA1": "FlzgVCYqnODad4pKujXhSaGcrIo=", "path": "github.com/hashicorp/hil/scanner", - "revision": "76d6c606283f17780baaad00df4b6ce8e9fca941", - "revisionTime": "2016-11-20T06:09:40Z" + "revision": "bf046eec69cc383b7f32c47990336409601c8116", + "revisionTime": "2016-12-04T02:32:26Z" }, { "path": "github.com/hashicorp/logutils",