summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/hashicorp/hcl/json/parser
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/hcl/json/parser')
-rw-r--r--vendor/github.com/hashicorp/hcl/json/parser/flatten.go117
-rw-r--r--vendor/github.com/hashicorp/hcl/json/parser/parser.go313
-rw-r--r--vendor/github.com/hashicorp/hcl/json/parser/parser_test.go384
-rw-r--r--vendor/github.com/hashicorp/hcl/json/parser/test-fixtures/array.json4
-rw-r--r--vendor/github.com/hashicorp/hcl/json/parser/test-fixtures/bad_input_128.json1
-rw-r--r--vendor/github.com/hashicorp/hcl/json/parser/test-fixtures/bad_input_tf_8110.json7
-rw-r--r--vendor/github.com/hashicorp/hcl/json/parser/test-fixtures/basic.json3
-rw-r--r--vendor/github.com/hashicorp/hcl/json/parser/test-fixtures/good_input_tf_8110.json7
-rw-r--r--vendor/github.com/hashicorp/hcl/json/parser/test-fixtures/object.json5
-rw-r--r--vendor/github.com/hashicorp/hcl/json/parser/test-fixtures/types.json10
10 files changed, 851 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/hcl/json/parser/flatten.go b/vendor/github.com/hashicorp/hcl/json/parser/flatten.go
new file mode 100644
index 000000000..f652d6fe7
--- /dev/null
+++ b/vendor/github.com/hashicorp/hcl/json/parser/flatten.go
@@ -0,0 +1,117 @@
+package parser
+
+import "github.com/hashicorp/hcl/hcl/ast"
+
+// flattenObjects takes an AST node, walks it, and flattens
+func flattenObjects(node ast.Node) {
+ ast.Walk(node, func(n ast.Node) (ast.Node, bool) {
+ // We only care about lists, because this is what we modify
+ list, ok := n.(*ast.ObjectList)
+ if !ok {
+ return n, true
+ }
+
+ // Rebuild the item list
+ items := make([]*ast.ObjectItem, 0, len(list.Items))
+ frontier := make([]*ast.ObjectItem, len(list.Items))
+ copy(frontier, list.Items)
+ for len(frontier) > 0 {
+ // Pop the current item
+ n := len(frontier)
+ item := frontier[n-1]
+ frontier = frontier[:n-1]
+
+ switch v := item.Val.(type) {
+ case *ast.ObjectType:
+ items, frontier = flattenObjectType(v, item, items, frontier)
+ case *ast.ListType:
+ items, frontier = flattenListType(v, item, items, frontier)
+ default:
+ items = append(items, item)
+ }
+ }
+
+ // Reverse the list since the frontier model runs things backwards
+ for i := len(items)/2 - 1; i >= 0; i-- {
+ opp := len(items) - 1 - i
+ items[i], items[opp] = items[opp], items[i]
+ }
+
+ // Done! Set the original items
+ list.Items = items
+ return n, true
+ })
+}
+
+func flattenListType(
+ ot *ast.ListType,
+ item *ast.ObjectItem,
+ items []*ast.ObjectItem,
+ frontier []*ast.ObjectItem) ([]*ast.ObjectItem, []*ast.ObjectItem) {
+ // If the list is empty, keep the original list
+ if len(ot.List) == 0 {
+ items = append(items, item)
+ return items, frontier
+ }
+
+ // All the elements of this object must also be objects!
+ for _, subitem := range ot.List {
+ if _, ok := subitem.(*ast.ObjectType); !ok {
+ items = append(items, item)
+ return items, frontier
+ }
+ }
+
+ // Great! We have a match go through all the items and flatten
+ for _, elem := range ot.List {
+ // Add it to the frontier so that we can recurse
+ frontier = append(frontier, &ast.ObjectItem{
+ Keys: item.Keys,
+ Assign: item.Assign,
+ Val: elem,
+ LeadComment: item.LeadComment,
+ LineComment: item.LineComment,
+ })
+ }
+
+ return items, frontier
+}
+
+func flattenObjectType(
+ ot *ast.ObjectType,
+ item *ast.ObjectItem,
+ items []*ast.ObjectItem,
+ frontier []*ast.ObjectItem) ([]*ast.ObjectItem, []*ast.ObjectItem) {
+ // If the list has no items we do not have to flatten anything
+ if ot.List.Items == nil {
+ items = append(items, item)
+ return items, frontier
+ }
+
+ // All the elements of this object must also be objects!
+ for _, subitem := range ot.List.Items {
+ if _, ok := subitem.Val.(*ast.ObjectType); !ok {
+ items = append(items, item)
+ return items, frontier
+ }
+ }
+
+ // Great! We have a match go through all the items and flatten
+ for _, subitem := range ot.List.Items {
+ // Copy the new key
+ keys := make([]*ast.ObjectKey, len(item.Keys)+len(subitem.Keys))
+ copy(keys, item.Keys)
+ copy(keys[len(item.Keys):], subitem.Keys)
+
+ // Add it to the frontier so that we can recurse
+ frontier = append(frontier, &ast.ObjectItem{
+ Keys: keys,
+ Assign: item.Assign,
+ Val: subitem.Val,
+ LeadComment: item.LeadComment,
+ LineComment: item.LineComment,
+ })
+ }
+
+ return items, frontier
+}
diff --git a/vendor/github.com/hashicorp/hcl/json/parser/parser.go b/vendor/github.com/hashicorp/hcl/json/parser/parser.go
new file mode 100644
index 000000000..6f4608530
--- /dev/null
+++ b/vendor/github.com/hashicorp/hcl/json/parser/parser.go
@@ -0,0 +1,313 @@
+package parser
+
+import (
+ "errors"
+ "fmt"
+
+ "github.com/hashicorp/hcl/hcl/ast"
+ hcltoken "github.com/hashicorp/hcl/hcl/token"
+ "github.com/hashicorp/hcl/json/scanner"
+ "github.com/hashicorp/hcl/json/token"
+)
+
+type Parser struct {
+ sc *scanner.Scanner
+
+ // Last read token
+ tok token.Token
+ commaPrev token.Token
+
+ enableTrace bool
+ indent int
+ n int // buffer size (max = 1)
+}
+
+func newParser(src []byte) *Parser {
+ return &Parser{
+ sc: scanner.New(src),
+ }
+}
+
+// Parse returns the fully parsed source and returns the abstract syntax tree.
+func Parse(src []byte) (*ast.File, error) {
+ p := newParser(src)
+ return p.Parse()
+}
+
+var errEofToken = errors.New("EOF token found")
+
+// Parse returns the fully parsed source and returns the abstract syntax tree.
+func (p *Parser) Parse() (*ast.File, error) {
+ f := &ast.File{}
+ var err, scerr error
+ p.sc.Error = func(pos token.Pos, msg string) {
+ scerr = fmt.Errorf("%s: %s", pos, msg)
+ }
+
+ // The root must be an object in JSON
+ object, err := p.object()
+ if scerr != nil {
+ return nil, scerr
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ // We make our final node an object list so it is more HCL compatible
+ f.Node = object.List
+
+ // Flatten it, which finds patterns and turns them into more HCL-like
+ // AST trees.
+ flattenObjects(f.Node)
+
+ return f, nil
+}
+
+func (p *Parser) objectList() (*ast.ObjectList, error) {
+ defer un(trace(p, "ParseObjectList"))
+ node := &ast.ObjectList{}
+
+ for {
+ n, err := p.objectItem()
+ if err == errEofToken {
+ break // we are finished
+ }
+
+ // we don't return a nil node, because might want to use already
+ // collected items.
+ if err != nil {
+ return node, err
+ }
+
+ node.Add(n)
+
+ // Check for a followup comma. If it isn't a comma, then we're done
+ if tok := p.scan(); tok.Type != token.COMMA {
+ break
+ }
+ }
+
+ return node, nil
+}
+
+// objectItem parses a single object item
+func (p *Parser) objectItem() (*ast.ObjectItem, error) {
+ defer un(trace(p, "ParseObjectItem"))
+
+ keys, err := p.objectKey()
+ if err != nil {
+ return nil, err
+ }
+
+ o := &ast.ObjectItem{
+ Keys: keys,
+ }
+
+ switch p.tok.Type {
+ case token.COLON:
+ pos := p.tok.Pos
+ o.Assign = hcltoken.Pos{
+ Filename: pos.Filename,
+ Offset: pos.Offset,
+ Line: pos.Line,
+ Column: pos.Column,
+ }
+
+ o.Val, err = p.objectValue()
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return o, nil
+}
+
+// objectKey parses an object key and returns a ObjectKey AST
+func (p *Parser) objectKey() ([]*ast.ObjectKey, error) {
+ keyCount := 0
+ keys := make([]*ast.ObjectKey, 0)
+
+ for {
+ tok := p.scan()
+ switch tok.Type {
+ case token.EOF:
+ return nil, errEofToken
+ case token.STRING:
+ keyCount++
+ keys = append(keys, &ast.ObjectKey{
+ Token: p.tok.HCLToken(),
+ })
+ case token.COLON:
+ // If we have a zero keycount it means that we never got
+ // an object key, i.e. `{ :`. This is a syntax error.
+ if keyCount == 0 {
+ return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type)
+ }
+
+ // Done
+ return keys, nil
+ case token.ILLEGAL:
+ fmt.Println("illegal")
+ default:
+ return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type)
+ }
+ }
+}
+
+// object parses any type of object, such as number, bool, string, object or
+// list.
+func (p *Parser) objectValue() (ast.Node, error) {
+ defer un(trace(p, "ParseObjectValue"))
+ tok := p.scan()
+
+ switch tok.Type {
+ case token.NUMBER, token.FLOAT, token.BOOL, token.NULL, token.STRING:
+ return p.literalType()
+ case token.LBRACE:
+ return p.objectType()
+ case token.LBRACK:
+ return p.listType()
+ case token.EOF:
+ return nil, errEofToken
+ }
+
+ return nil, fmt.Errorf("Expected object value, got unknown token: %+v", tok)
+}
+
+// object parses any type of object, such as number, bool, string, object or
+// list.
+func (p *Parser) object() (*ast.ObjectType, error) {
+ defer un(trace(p, "ParseType"))
+ tok := p.scan()
+
+ switch tok.Type {
+ case token.LBRACE:
+ return p.objectType()
+ case token.EOF:
+ return nil, errEofToken
+ }
+
+ return nil, fmt.Errorf("Expected object, got unknown token: %+v", tok)
+}
+
+// objectType parses an object type and returns a ObjectType AST
+func (p *Parser) objectType() (*ast.ObjectType, error) {
+ defer un(trace(p, "ParseObjectType"))
+
+ // we assume that the currently scanned token is a LBRACE
+ o := &ast.ObjectType{}
+
+ l, err := p.objectList()
+
+ // if we hit RBRACE, we are good to go (means we parsed all Items), if it's
+ // not a RBRACE, it's an syntax error and we just return it.
+ if err != nil && p.tok.Type != token.RBRACE {
+ return nil, err
+ }
+
+ o.List = l
+ return o, nil
+}
+
+// listType parses a list type and returns a ListType AST
+func (p *Parser) listType() (*ast.ListType, error) {
+ defer un(trace(p, "ParseListType"))
+
+ // we assume that the currently scanned token is a LBRACK
+ l := &ast.ListType{}
+
+ for {
+ tok := p.scan()
+ switch tok.Type {
+ case token.NUMBER, token.FLOAT, token.STRING:
+ node, err := p.literalType()
+ if err != nil {
+ return nil, err
+ }
+
+ l.Add(node)
+ case token.COMMA:
+ continue
+ case token.LBRACE:
+ node, err := p.objectType()
+ if err != nil {
+ return nil, err
+ }
+
+ l.Add(node)
+ case token.BOOL:
+ // TODO(arslan) should we support? not supported by HCL yet
+ case token.LBRACK:
+ // TODO(arslan) should we support nested lists? Even though it's
+ // written in README of HCL, it's not a part of the grammar
+ // (not defined in parse.y)
+ case token.RBRACK:
+ // finished
+ return l, nil
+ default:
+ return nil, fmt.Errorf("unexpected token while parsing list: %s", tok.Type)
+ }
+
+ }
+}
+
+// literalType parses a literal type and returns a LiteralType AST
+func (p *Parser) literalType() (*ast.LiteralType, error) {
+ defer un(trace(p, "ParseLiteral"))
+
+ return &ast.LiteralType{
+ Token: p.tok.HCLToken(),
+ }, nil
+}
+
+// scan returns the next token from the underlying scanner. If a token has
+// been unscanned then read that instead.
+func (p *Parser) scan() token.Token {
+ // If we have a token on the buffer, then return it.
+ if p.n != 0 {
+ p.n = 0
+ return p.tok
+ }
+
+ p.tok = p.sc.Scan()
+ return p.tok
+}
+
+// unscan pushes the previously read token back onto the buffer.
+func (p *Parser) unscan() {
+ p.n = 1
+}
+
+// ----------------------------------------------------------------------------
+// Parsing support
+
+func (p *Parser) printTrace(a ...interface{}) {
+ if !p.enableTrace {
+ return
+ }
+
+ const dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
+ const n = len(dots)
+ fmt.Printf("%5d:%3d: ", p.tok.Pos.Line, p.tok.Pos.Column)
+
+ i := 2 * p.indent
+ for i > n {
+ fmt.Print(dots)
+ i -= n
+ }
+ // i <= n
+ fmt.Print(dots[0:i])
+ fmt.Println(a...)
+}
+
+func trace(p *Parser, msg string) *Parser {
+ p.printTrace(msg, "(")
+ p.indent++
+ return p
+}
+
+// Usage pattern: defer un(trace(p, "..."))
+func un(p *Parser) {
+ p.indent--
+ p.printTrace(")")
+}
diff --git a/vendor/github.com/hashicorp/hcl/json/parser/parser_test.go b/vendor/github.com/hashicorp/hcl/json/parser/parser_test.go
new file mode 100644
index 000000000..e0cebf50a
--- /dev/null
+++ b/vendor/github.com/hashicorp/hcl/json/parser/parser_test.go
@@ -0,0 +1,384 @@
+package parser
+
+import (
+ "fmt"
+ "io/ioutil"
+ "path/filepath"
+ "reflect"
+ "runtime"
+ "testing"
+
+ "github.com/hashicorp/hcl/hcl/ast"
+ "github.com/hashicorp/hcl/hcl/token"
+)
+
+func TestType(t *testing.T) {
+ var literals = []struct {
+ typ token.Type
+ src string
+ }{
+ {token.STRING, `"foo": "bar"`},
+ {token.NUMBER, `"foo": 123`},
+ {token.FLOAT, `"foo": 123.12`},
+ {token.FLOAT, `"foo": -123.12`},
+ {token.BOOL, `"foo": true`},
+ {token.STRING, `"foo": null`},
+ }
+
+ for _, l := range literals {
+ t.Logf("Testing: %s", l.src)
+
+ p := newParser([]byte(l.src))
+ item, err := p.objectItem()
+ if err != nil {
+ t.Error(err)
+ }
+
+ lit, ok := item.Val.(*ast.LiteralType)
+ if !ok {
+ t.Errorf("node should be of type LiteralType, got: %T", item.Val)
+ }
+
+ if lit.Token.Type != l.typ {
+ t.Errorf("want: %s, got: %s", l.typ, lit.Token.Type)
+ }
+ }
+}
+
+func TestListType(t *testing.T) {
+ var literals = []struct {
+ src string
+ tokens []token.Type
+ }{
+ {
+ `"foo": ["123", 123]`,
+ []token.Type{token.STRING, token.NUMBER},
+ },
+ {
+ `"foo": [123, "123",]`,
+ []token.Type{token.NUMBER, token.STRING},
+ },
+ {
+ `"foo": []`,
+ []token.Type{},
+ },
+ {
+ `"foo": ["123", 123]`,
+ []token.Type{token.STRING, token.NUMBER},
+ },
+ {
+ `"foo": ["123", {}]`,
+ []token.Type{token.STRING, token.LBRACE},
+ },
+ }
+
+ for _, l := range literals {
+ t.Logf("Testing: %s", l.src)
+
+ p := newParser([]byte(l.src))
+ item, err := p.objectItem()
+ if err != nil {
+ t.Error(err)
+ }
+
+ list, ok := item.Val.(*ast.ListType)
+ if !ok {
+ t.Errorf("node should be of type LiteralType, got: %T", item.Val)
+ }
+
+ tokens := []token.Type{}
+ for _, li := range list.List {
+ switch v := li.(type) {
+ case *ast.LiteralType:
+ tokens = append(tokens, v.Token.Type)
+ case *ast.ObjectType:
+ tokens = append(tokens, token.LBRACE)
+ }
+ }
+
+ equals(t, l.tokens, tokens)
+ }
+}
+
+func TestObjectType(t *testing.T) {
+ var literals = []struct {
+ src string
+ nodeType []ast.Node
+ itemLen int
+ }{
+ {
+ `"foo": {}`,
+ nil,
+ 0,
+ },
+ {
+ `"foo": {
+ "bar": "fatih"
+ }`,
+ []ast.Node{&ast.LiteralType{}},
+ 1,
+ },
+ {
+ `"foo": {
+ "bar": "fatih",
+ "baz": ["arslan"]
+ }`,
+ []ast.Node{
+ &ast.LiteralType{},
+ &ast.ListType{},
+ },
+ 2,
+ },
+ {
+ `"foo": {
+ "bar": {}
+ }`,
+ []ast.Node{
+ &ast.ObjectType{},
+ },
+ 1,
+ },
+ {
+ `"foo": {
+ "bar": {},
+ "foo": true
+ }`,
+ []ast.Node{
+ &ast.ObjectType{},
+ &ast.LiteralType{},
+ },
+ 2,
+ },
+ }
+
+ for _, l := range literals {
+ t.Logf("Testing:\n%s\n", l.src)
+
+ p := newParser([]byte(l.src))
+ // p.enableTrace = true
+ item, err := p.objectItem()
+ if err != nil {
+ t.Error(err)
+ }
+
+ // we know that the ObjectKey name is foo for all cases, what matters
+ // is the object
+ obj, ok := item.Val.(*ast.ObjectType)
+ if !ok {
+ t.Errorf("node should be of type LiteralType, got: %T", item.Val)
+ }
+
+ // check if the total length of items are correct
+ equals(t, l.itemLen, len(obj.List.Items))
+
+ // check if the types are correct
+ for i, item := range obj.List.Items {
+ equals(t, reflect.TypeOf(l.nodeType[i]), reflect.TypeOf(item.Val))
+ }
+ }
+}
+
+func TestFlattenObjects(t *testing.T) {
+ var literals = []struct {
+ src string
+ nodeType []ast.Node
+ itemLen int
+ }{
+ {
+ `{
+ "foo": [
+ {
+ "foo": "svh",
+ "bar": "fatih"
+ }
+ ]
+ }`,
+ []ast.Node{
+ &ast.ObjectType{},
+ &ast.LiteralType{},
+ &ast.LiteralType{},
+ },
+ 3,
+ },
+ {
+ `{
+ "variable": {
+ "foo": {}
+ }
+ }`,
+ []ast.Node{
+ &ast.ObjectType{},
+ },
+ 1,
+ },
+ {
+ `{
+ "empty": []
+ }`,
+ []ast.Node{
+ &ast.ListType{},
+ },
+ 1,
+ },
+ {
+ `{
+ "basic": [1, 2, 3]
+ }`,
+ []ast.Node{
+ &ast.ListType{},
+ },
+ 1,
+ },
+ }
+
+ for _, l := range literals {
+ t.Logf("Testing:\n%s\n", l.src)
+
+ f, err := Parse([]byte(l.src))
+ if err != nil {
+ t.Error(err)
+ }
+
+ // the first object is always an ObjectList so just assert that one
+ // so we can use it as such
+ obj, ok := f.Node.(*ast.ObjectList)
+ if !ok {
+ t.Errorf("node should be *ast.ObjectList, got: %T", f.Node)
+ }
+
+ // check if the types are correct
+ var i int
+ for _, item := range obj.Items {
+ equals(t, reflect.TypeOf(l.nodeType[i]), reflect.TypeOf(item.Val))
+ i++
+
+ if obj, ok := item.Val.(*ast.ObjectType); ok {
+ for _, item := range obj.List.Items {
+ equals(t, reflect.TypeOf(l.nodeType[i]), reflect.TypeOf(item.Val))
+ i++
+ }
+ }
+ }
+
+ // check if the number of items is correct
+ equals(t, l.itemLen, i)
+
+ }
+}
+
+func TestObjectKey(t *testing.T) {
+ keys := []struct {
+ exp []token.Type
+ src string
+ }{
+ {[]token.Type{token.STRING}, `"foo": {}`},
+ }
+
+ for _, k := range keys {
+ p := newParser([]byte(k.src))
+ keys, err := p.objectKey()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ tokens := []token.Type{}
+ for _, o := range keys {
+ tokens = append(tokens, o.Token.Type)
+ }
+
+ equals(t, k.exp, tokens)
+ }
+
+ errKeys := []struct {
+ src string
+ }{
+ {`foo 12 {}`},
+ {`foo bar = {}`},
+ {`foo []`},
+ {`12 {}`},
+ }
+
+ for _, k := range errKeys {
+ p := newParser([]byte(k.src))
+ _, err := p.objectKey()
+ if err == nil {
+ t.Errorf("case '%s' should give an error", k.src)
+ }
+ }
+}
+
+// Official HCL tests
+func TestParse(t *testing.T) {
+ cases := []struct {
+ Name string
+ Err bool
+ }{
+ {
+ "array.json",
+ false,
+ },
+ {
+ "basic.json",
+ false,
+ },
+ {
+ "object.json",
+ false,
+ },
+ {
+ "types.json",
+ false,
+ },
+ {
+ "bad_input_128.json",
+ true,
+ },
+ {
+ "bad_input_tf_8110.json",
+ true,
+ },
+ {
+ "good_input_tf_8110.json",
+ false,
+ },
+ }
+
+ const fixtureDir = "./test-fixtures"
+
+ for _, tc := range cases {
+ d, err := ioutil.ReadFile(filepath.Join(fixtureDir, tc.Name))
+ if err != nil {
+ t.Fatalf("err: %s", err)
+ }
+
+ _, err = Parse(d)
+ if (err != nil) != tc.Err {
+ t.Fatalf("Input: %s\n\nError: %s", tc.Name, err)
+ }
+ }
+}
+
+func TestParse_inline(t *testing.T) {
+ cases := []struct {
+ Value string
+ Err bool
+ }{
+ {"{:{", true},
+ }
+
+ for _, tc := range cases {
+ _, err := Parse([]byte(tc.Value))
+ if (err != nil) != tc.Err {
+ t.Fatalf("Input: %q\n\nError: %s", tc.Value, err)
+ }
+ }
+}
+
+// equals fails the test if exp is not equal to act.
+func equals(tb testing.TB, exp, act interface{}) {
+ if !reflect.DeepEqual(exp, act) {
+ _, file, line, _ := runtime.Caller(1)
+ fmt.Printf("\033[31m%s:%d:\n\n\texp: %s\n\n\tgot: %s\033[39m\n\n", filepath.Base(file), line, exp, act)
+ tb.FailNow()
+ }
+}
diff --git a/vendor/github.com/hashicorp/hcl/json/parser/test-fixtures/array.json b/vendor/github.com/hashicorp/hcl/json/parser/test-fixtures/array.json
new file mode 100644
index 000000000..e320f17ab
--- /dev/null
+++ b/vendor/github.com/hashicorp/hcl/json/parser/test-fixtures/array.json
@@ -0,0 +1,4 @@
+{
+ "foo": [1, 2, "bar"],
+ "bar": "baz"
+}
diff --git a/vendor/github.com/hashicorp/hcl/json/parser/test-fixtures/bad_input_128.json b/vendor/github.com/hashicorp/hcl/json/parser/test-fixtures/bad_input_128.json
new file mode 100644
index 000000000..b5f850c96
--- /dev/null
+++ b/vendor/github.com/hashicorp/hcl/json/parser/test-fixtures/bad_input_128.json
@@ -0,0 +1 @@
+{:{
diff --git a/vendor/github.com/hashicorp/hcl/json/parser/test-fixtures/bad_input_tf_8110.json b/vendor/github.com/hashicorp/hcl/json/parser/test-fixtures/bad_input_tf_8110.json
new file mode 100644
index 000000000..a04385833
--- /dev/null
+++ b/vendor/github.com/hashicorp/hcl/json/parser/test-fixtures/bad_input_tf_8110.json
@@ -0,0 +1,7 @@
+{
+ "variable": {
+ "poc": {
+ "default": "${replace("europe-west", "-", " ")}"
+ }
+ }
+}
diff --git a/vendor/github.com/hashicorp/hcl/json/parser/test-fixtures/basic.json b/vendor/github.com/hashicorp/hcl/json/parser/test-fixtures/basic.json
new file mode 100644
index 000000000..b54bde96c
--- /dev/null
+++ b/vendor/github.com/hashicorp/hcl/json/parser/test-fixtures/basic.json
@@ -0,0 +1,3 @@
+{
+ "foo": "bar"
+}
diff --git a/vendor/github.com/hashicorp/hcl/json/parser/test-fixtures/good_input_tf_8110.json b/vendor/github.com/hashicorp/hcl/json/parser/test-fixtures/good_input_tf_8110.json
new file mode 100644
index 000000000..f21aa090d
--- /dev/null
+++ b/vendor/github.com/hashicorp/hcl/json/parser/test-fixtures/good_input_tf_8110.json
@@ -0,0 +1,7 @@
+{
+ "variable": {
+ "poc": {
+ "default": "${replace(\"europe-west\", \"-\", \" \")}"
+ }
+ }
+}
diff --git a/vendor/github.com/hashicorp/hcl/json/parser/test-fixtures/object.json b/vendor/github.com/hashicorp/hcl/json/parser/test-fixtures/object.json
new file mode 100644
index 000000000..72168a3cc
--- /dev/null
+++ b/vendor/github.com/hashicorp/hcl/json/parser/test-fixtures/object.json
@@ -0,0 +1,5 @@
+{
+ "foo": {
+ "bar": [1,2]
+ }
+}
diff --git a/vendor/github.com/hashicorp/hcl/json/parser/test-fixtures/types.json b/vendor/github.com/hashicorp/hcl/json/parser/test-fixtures/types.json
new file mode 100644
index 000000000..9a142a6ca
--- /dev/null
+++ b/vendor/github.com/hashicorp/hcl/json/parser/test-fixtures/types.json
@@ -0,0 +1,10 @@
+{
+ "foo": "bar",
+ "bar": 7,
+ "baz": [1,2,3],
+ "foo": -12,
+ "bar": 3.14159,
+ "foo": true,
+ "bar": false,
+ "foo": null
+}