internal/third_party/yaml: parse into CUE ast

Also:
- remove support for parsing into Go-structs
- remove support for encoding
- add comment parsing
- port non-standard test harness to standard go
- add testdata
- fix some bugs related to merging

Change-Id: I7fbd2bed6f76bb5da8a309f8d3fb3fb6228048ab
diff --git a/internal/third_party/yaml/README.md b/internal/third_party/yaml/README.md
index b50c6e8..ea39618 100644
--- a/internal/third_party/yaml/README.md
+++ b/internal/third_party/yaml/README.md
@@ -1,42 +1,7 @@
-# YAML support for the Go language
+# YAML reader for CUE
 
-Introduction
-------------
-
-The yaml package enables Go programs to comfortably encode and decode YAML
-values. It was developed within [Canonical](https://www.canonical.com) as
-part of the [juju](https://juju.ubuntu.com) project, and is based on a
-pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML)
-C library to parse and generate YAML data quickly and reliably.
-
-Compatibility
--------------
-
-The yaml package supports most of YAML 1.1 and 1.2, including support for
-anchors, tags, map merging, etc. Multi-document unmarshalling is not yet
-implemented, and base-60 floats from YAML 1.1 are purposefully not
-supported since they're a poor design and are gone in YAML 1.2.
-
-Installation and usage
-----------------------
-
-The import path for the package is *gopkg.in/yaml.v2*.
-
-To install it, run:
-
-    go get gopkg.in/yaml.v2
-
-API documentation
------------------
-
-If opened in a browser, the import path itself leads to the API documentation:
-
-  * [https://gopkg.in/yaml.v2](https://gopkg.in/yaml.v2)
-
-API stability
--------------
-
-The package API for yaml v2 will remain stable as described in [gopkg.in](https://gopkg.in).
+This yaml parser is a heavily modified version of Canonical's go-yaml parser,
+which in turn is a port of the [libyaml](http://pyyaml.org/wiki/LibYAML) parser.
 
 
 License
@@ -44,90 +9,3 @@
 
 The yaml package is licensed under the Apache License 2.0. Please see the LICENSE file for details.
 
-
-Example
--------
-
-```Go
-package main
-
-import (
-        "fmt"
-        "log"
-
-        "gopkg.in/yaml.v2"
-)
-
-var data = `
-a: Easy!
-b:
-  c: 2
-  d: [3, 4]
-`
-
-// Note: struct fields must be public in order for unmarshal to
-// correctly populate the data.
-type T struct {
-        A string
-        B struct {
-                RenamedC int   `yaml:"c"`
-                D        []int `yaml:",flow"`
-        }
-}
-
-func main() {
-        t := T{}
-    
-        err := yaml.Unmarshal([]byte(data), &t)
-        if err != nil {
-                log.Fatalf("error: %v", err)
-        }
-        fmt.Printf("--- t:\n%v\n\n", t)
-    
-        d, err := yaml.Marshal(&t)
-        if err != nil {
-                log.Fatalf("error: %v", err)
-        }
-        fmt.Printf("--- t dump:\n%s\n\n", string(d))
-    
-        m := make(map[interface{}]interface{})
-    
-        err = yaml.Unmarshal([]byte(data), &m)
-        if err != nil {
-                log.Fatalf("error: %v", err)
-        }
-        fmt.Printf("--- m:\n%v\n\n", m)
-    
-        d, err = yaml.Marshal(&m)
-        if err != nil {
-                log.Fatalf("error: %v", err)
-        }
-        fmt.Printf("--- m dump:\n%s\n\n", string(d))
-}
-```
-
-This example will generate the following output:
-
-```
---- t:
-{Easy! {2 [3 4]}}
-
---- t dump:
-a: Easy!
-b:
-  c: 2
-  d: [3, 4]
-
-
---- m:
-map[a:Easy! b:map[c:2 d:[3 4]]]
-
---- m dump:
-a: Easy!
-b:
-  c: 2
-  d:
-  - 3
-  - 4
-```
-
diff --git a/internal/third_party/yaml/apic.go b/internal/third_party/yaml/apic.go
index 1f7e87e..9cf9005 100644
--- a/internal/third_party/yaml/apic.go
+++ b/internal/third_party/yaml/apic.go
@@ -24,8 +24,9 @@
 }
 
 // Create a new parser object.
-func yaml_parser_initialize(parser *yaml_parser_t) bool {
+func yaml_parser_initialize(parser *yaml_parser_t, filename string) bool {
 	*parser = yaml_parser_t{
+		filename:   filename,
 		raw_buffer: make([]byte, 0, input_raw_buffer_size),
 		buffer:     make([]byte, 0, input_buffer_size),
 	}
diff --git a/internal/third_party/yaml/decode.go b/internal/third_party/yaml/decode.go
index e4e56e2..5a970d2 100644
--- a/internal/third_party/yaml/decode.go
+++ b/internal/third_party/yaml/decode.go
@@ -1,14 +1,21 @@
 package yaml
 
 import (
-	"encoding"
+	"bytes"
 	"encoding/base64"
+	"errors"
 	"fmt"
 	"io"
+	"io/ioutil"
 	"math"
 	"reflect"
 	"strconv"
+	"strings"
 	"time"
+	"unicode"
+
+	"cuelang.org/go/cue/ast"
+	"cuelang.org/go/cue/token"
 )
 
 const (
@@ -20,9 +27,10 @@
 )
 
 type node struct {
-	kind         int
-	line, column int
-	tag          string
+	kind     int
+	startPos yaml_mark_t
+	endPos   yaml_mark_t
+	tag      string
 	// For an alias node, alias holds the resolved alias.
 	alias    *node
 	value    string
@@ -38,28 +46,51 @@
 	parser   yaml_parser_t
 	event    yaml_event_t
 	doc      *node
+	info     *token.File
+	last     *node
 	doneInit bool
 }
 
-func newParser(b []byte) *parser {
-	p := parser{}
-	if !yaml_parser_initialize(&p.parser) {
+func readSource(filename string, src interface{}) ([]byte, error) {
+	if src != nil {
+		switch s := src.(type) {
+		case string:
+			return []byte(s), nil
+		case []byte:
+			return s, nil
+		case *bytes.Buffer:
+			// is io.Reader, but src is already available in []byte form
+			if s != nil {
+				return s.Bytes(), nil
+			}
+		case io.Reader:
+			var buf bytes.Buffer
+			if _, err := io.Copy(&buf, s); err != nil {
+				return nil, err
+			}
+			return buf.Bytes(), nil
+		}
+		return nil, errors.New("invalid source")
+	}
+	return ioutil.ReadFile(filename)
+}
+
+func newParser(fset *token.FileSet, filename string, src interface{}) (*parser, error) {
+	b, err := readSource(filename, src)
+	if err != nil {
+		return nil, err
+	}
+	info := fset.AddFile(filename, -1, len(b))
+	info.SetLinesForContent(b)
+	p := parser{info: info}
+	if !yaml_parser_initialize(&p.parser, filename) {
 		panic("failed to initialize YAML emitter")
 	}
 	if len(b) == 0 {
 		b = []byte{'\n'}
 	}
 	yaml_parser_set_input_string(&p.parser, b)
-	return &p
-}
-
-func newParserFromReader(r io.Reader) *parser {
-	p := parser{}
-	if !yaml_parser_initialize(&p.parser) {
-		panic("failed to initialize YAML emitter")
-	}
-	yaml_parser_set_input_reader(&p.parser, r)
-	return &p
+	return &p, nil
 }
 
 func (p *parser) init() {
@@ -86,7 +117,7 @@
 		}
 	}
 	if p.event.typ == yaml_STREAM_END_EVENT {
-		failf("attempted to go past the end of stream; corrupted value?")
+		p.failf(p.event.end_mark.line, "attempted to go past the end of stream; corrupted value?")
 	}
 	if p.event.typ != e {
 		p.parser.problem = fmt.Sprintf("expected %s event but got %s", e, p.event.typ)
@@ -109,19 +140,15 @@
 }
 
 func (p *parser) fail() {
-	var where string
 	var line int
 	if p.parser.problem_mark.line != 0 {
 		line = p.parser.problem_mark.line
 		// Scanner errors don't iterate line before returning error
-		if p.parser.error == yaml_SCANNER_ERROR {
-			line++
+		if p.parser.error != yaml_SCANNER_ERROR {
+			line--
 		}
 	} else if p.parser.context_mark.line != 0 {
-		line = p.parser.context_mark.line
-	}
-	if line != 0 {
-		where = "line " + strconv.Itoa(line) + ": "
+		line = p.parser.context_mark.line - 1
 	}
 	var msg string
 	if len(p.parser.problem) > 0 {
@@ -129,7 +156,7 @@
 	} else {
 		msg = "unknown problem parsing YAML content"
 	}
-	failf("%s%s", where, msg)
+	p.failf(line, msg)
 }
 
 func (p *parser) anchor(n *node, anchor []byte) {
@@ -160,11 +187,12 @@
 }
 
 func (p *parser) node(kind int) *node {
-	return &node{
-		kind:   kind,
-		line:   p.event.start_mark.line,
-		column: p.event.start_mark.column,
+	n := &node{
+		kind:     kind,
+		startPos: p.event.start_mark,
+		endPos:   p.event.end_mark,
 	}
+	return n
 }
 
 func (p *parser) document() *node {
@@ -182,7 +210,7 @@
 	n.value = string(p.event.anchor)
 	n.alias = p.doc.anchors[n.value]
 	if n.alias == nil {
-		failf("unknown anchor '%s' referenced", n.value)
+		p.failf(n.startPos.line, "unknown anchor '%s' referenced", n.value)
 	}
 	p.expect(yaml_ALIAS_EVENT)
 	return n
@@ -224,29 +252,30 @@
 // Decoder, unmarshals a node into a provided value.
 
 type decoder struct {
-	doc     *node
-	aliases map[*node]bool
-	mapType reflect.Type
-	terrors []string
-	strict  bool
+	p        *parser
+	doc      *node
+	aliases  map[*node]bool
+	mapType  reflect.Type
+	terrors  []string
+	prev     token.Pos
+	lastNode ast.Node
 }
 
 var (
 	mapItemType    = reflect.TypeOf(MapItem{})
 	durationType   = reflect.TypeOf(time.Duration(0))
 	defaultMapType = reflect.TypeOf(map[interface{}]interface{}{})
-	ifaceType      = defaultMapType.Elem()
 	timeType       = reflect.TypeOf(time.Time{})
 	ptrTimeType    = reflect.TypeOf(&time.Time{})
 )
 
-func newDecoder(strict bool) *decoder {
-	d := &decoder{mapType: defaultMapType, strict: strict}
+func newDecoder(p *parser) *decoder {
+	d := &decoder{p: p, mapType: defaultMapType}
 	d.aliases = make(map[*node]bool)
 	return d
 }
 
-func (d *decoder) terror(n *node, tag string, out reflect.Value) {
+func (d *decoder) terror(n *node, tag string) string {
 	if n.tag != "" {
 		tag = n.tag
 	}
@@ -258,499 +287,392 @@
 			value = " `" + value + "`"
 		}
 	}
-	d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.line+1, shortTag(tag), value, out.Type()))
+	msg := fmt.Sprintf("line %d: cannot unmarshal %s%s", n.startPos.line+1, shortTag(tag), value)
+	d.terrors = append(d.terrors, msg)
+	return msg
 }
 
-func (d *decoder) callUnmarshaler(n *node, u Unmarshaler) (good bool) {
-	terrlen := len(d.terrors)
-	err := u.UnmarshalYAML(func(v interface{}) (err error) {
-		defer handleErr(&err)
-		d.unmarshal(n, reflect.ValueOf(v))
-		if len(d.terrors) > terrlen {
-			issues := d.terrors[terrlen:]
-			d.terrors = d.terrors[:terrlen]
-			return &TypeError{issues}
-		}
-		return nil
-	})
-	if e, ok := err.(*TypeError); ok {
-		d.terrors = append(d.terrors, e.Errors...)
-		return false
-	}
-	if err != nil {
-		fail(err)
-	}
-	return true
-}
-
-// d.prepare initializes and dereferences pointers and calls UnmarshalYAML
-// if a value is found to implement it.
-// It returns the initialized and dereferenced out value, whether
-// unmarshalling was already done by UnmarshalYAML, and if so whether
-// its types unmarshalled appropriately.
-//
-// If n holds a null value, prepare returns before doing anything.
-func (d *decoder) prepare(n *node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) {
-	if n.tag == yaml_NULL_TAG || n.kind == scalarNode && n.tag == "" && (n.value == "null" || n.value == "~" || n.value == "" && n.implicit) {
-		return out, false, false
-	}
-	again := true
-	for again {
-		again = false
-		if out.Kind() == reflect.Ptr {
-			if out.IsNil() {
-				out.Set(reflect.New(out.Type().Elem()))
-			}
-			out = out.Elem()
-			again = true
-		}
-		if out.CanAddr() {
-			if u, ok := out.Addr().Interface().(Unmarshaler); ok {
-				good = d.callUnmarshaler(n, u)
-				return out, true, good
-			}
-		}
-	}
-	return out, false, false
-}
-
-func (d *decoder) unmarshal(n *node, out reflect.Value) (good bool) {
+func (d *decoder) unmarshal(n *node) (node ast.Expr) {
 	switch n.kind {
 	case documentNode:
-		return d.document(n, out)
+		node = d.document(n)
 	case aliasNode:
-		return d.alias(n, out)
-	}
-	out, unmarshaled, good := d.prepare(n, out)
-	if unmarshaled {
-		return good
-	}
-	switch n.kind {
-	case scalarNode:
-		good = d.scalar(n, out)
-	case mappingNode:
-		good = d.mapping(n, out)
-	case sequenceNode:
-		good = d.sequence(n, out)
+		node = d.alias(n)
 	default:
-		panic("internal error: unknown node kind: " + strconv.Itoa(n.kind))
+		switch n.kind {
+		case scalarNode:
+			node = d.scalar(n)
+		case mappingNode:
+			node = d.mapping(n)
+		case sequenceNode:
+			node = d.sequence(n)
+		default:
+			panic("internal error: unknown node kind: " + strconv.Itoa(n.kind))
+		}
 	}
-	return good
+	return node
 }
 
-func (d *decoder) document(n *node, out reflect.Value) (good bool) {
+func (d *decoder) attachDocComments(m yaml_mark_t, pos int8, expr ast.Node) {
+	comments := []*ast.Comment{}
+	for len(d.p.parser.comments) > 0 {
+		c := d.p.parser.comments[0]
+		if c.mark.index >= m.index {
+			break
+		}
+		// fp := d.p.info.Pos(c.mark.index, 0)
+		comments = append(comments, &ast.Comment{
+			token.Pos(c.pos),
+			"//" + c.text[1:],
+		})
+		d.p.parser.comments = d.p.parser.comments[1:]
+	}
+	if len(comments) > 0 {
+		expr.AddComment(&ast.CommentGroup{
+			Doc:      pos == 0,
+			Position: pos,
+			List:     comments,
+		})
+	}
+}
+
+func (d *decoder) attachLineComment(m yaml_mark_t, pos int8, expr ast.Node) {
+	if len(d.p.parser.comments) == 0 {
+		return
+	}
+	c := d.p.parser.comments[0]
+	if c.mark.index == m.index {
+		comment := &ast.Comment{
+			token.Pos(c.pos),
+			// d.p.info.Pos(m.index+1, 0),
+			"//" + c.text[1:],
+		}
+		// expr.AddComment(pos, false)
+		expr.AddComment(&ast.CommentGroup{
+			Line:     true,
+			Position: pos,
+			List:     []*ast.Comment{comment},
+		})
+	}
+}
+
+func (d *decoder) pos(m yaml_mark_t) token.Pos {
+	return token.NoPos
+	// TODO: reenable once we have better spacing.
+	// pos := d.p.info.Pos(m.index)
+	// if pos <= d.prev+1 {
+	// 	return token.NoPos
+	// }
+	// d.prev = pos
+	// return pos
+}
+
+func (d *decoder) start(n *node) token.Pos {
+	return d.pos(n.startPos)
+}
+
+func (d *decoder) ident(n *node, name string) *ast.Ident {
+	return &ast.Ident{
+		// NamePos: d.pos(n.startPos),
+		NamePos: token.Pos(d.p.parser.relPos()),
+		Name:    name,
+	}
+}
+
+func (d *decoder) document(n *node) ast.Expr {
 	if len(n.children) == 1 {
 		d.doc = n
-		d.unmarshal(n.children[0], out)
-		return true
+		return d.unmarshal(n.children[0])
 	}
-	return false
+	return &ast.BottomLit{} // TODO: more informatives
 }
 
-func (d *decoder) alias(n *node, out reflect.Value) (good bool) {
+func (d *decoder) alias(n *node) ast.Expr {
 	if d.aliases[n] {
 		// TODO this could actually be allowed in some circumstances.
-		failf("anchor '%s' value contains itself", n.value)
+		d.p.failf(n.startPos.line, "anchor '%s' value contains itself", n.value)
 	}
 	d.aliases[n] = true
-	good = d.unmarshal(n.alias, out)
+	node := d.unmarshal(n.alias)
 	delete(d.aliases, n)
-	return good
+	return node
 }
 
 var zeroValue reflect.Value
 
-func resetMap(out reflect.Value) {
-	for _, k := range out.MapKeys() {
-		out.SetMapIndex(k, zeroValue)
-	}
-}
-
-func (d *decoder) scalar(n *node, out reflect.Value) bool {
+func (d *decoder) scalar(n *node) ast.Expr {
 	var tag string
 	var resolved interface{}
 	if n.tag == "" && !n.implicit {
 		tag = yaml_STR_TAG
 		resolved = n.value
 	} else {
-		tag, resolved = resolve(n.tag, n.value)
+		tag, resolved = d.resolve(n)
 		if tag == yaml_BINARY_TAG {
 			data, err := base64.StdEncoding.DecodeString(resolved.(string))
 			if err != nil {
-				failf("!!binary value contains invalid base64 data")
+				d.p.failf(n.startPos.line, "!!binary value contains invalid base64 data")
 			}
 			resolved = string(data)
 		}
 	}
 	if resolved == nil {
-		if out.Kind() == reflect.Map && !out.CanAddr() {
-			resetMap(out)
-		} else {
-			out.Set(reflect.Zero(out.Type()))
-		}
-		return true
+		return d.ident(n, "null")
 	}
-	if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
-		// We've resolved to exactly the type we want, so use that.
-		out.Set(resolvedv)
-		return true
+	switch tag {
+	// TODO: use parse literal or parse expression instead.
+	case yaml_TIMESTAMP_TAG:
+		return &ast.BasicLit{
+			// ValuePos: d.start(n),
+			ValuePos: token.Pos(d.p.parser.relPos()),
+			Kind:     token.STRING,
+			Value:    strconv.Quote(n.value),
+		}
+
+	case yaml_STR_TAG:
+		return &ast.BasicLit{
+			// ValuePos: d.start(n),
+			ValuePos: token.Pos(d.p.parser.relPos()),
+			Kind:     token.STRING,
+			Value:    d.quoteString(n.value),
+		}
+
+	case yaml_BINARY_TAG:
+		buf := strconv.AppendQuote(nil, resolved.(string))
+		buf[0] = '\''
+		buf[len(buf)-1] = '\''
+		return &ast.BasicLit{
+			// ValuePos: d.start(n),
+			ValuePos: token.Pos(d.p.parser.relPos()),
+			Kind:     token.STRING,
+			Value:    string(buf),
+		}
+
+	case yaml_BOOL_TAG:
+		str := "false"
+		if b, _ := resolved.(bool); b {
+			str = "true"
+		}
+		return d.ident(n, str)
+
+	case yaml_INT_TAG:
+		return d.makeNum(n, n.value, token.INT)
+
+	case yaml_FLOAT_TAG:
+		value := n.value
+		if f, ok := resolved.(float64); ok {
+			switch {
+			case math.IsInf(f, -1),
+				math.IsInf(f, 1),
+				math.IsNaN(f):
+				value = fmt.Sprint(f)
+			}
+		}
+		if n.tag != "" {
+			if p := strings.IndexAny(value, ".eEiInN"); p == -1 {
+				// TODO: float(v) when we have conversions
+				value = fmt.Sprintf("float & %s", value)
+			}
+		}
+		return d.makeNum(n, value, token.FLOAT)
+
+	case yaml_NULL_TAG:
+		return d.ident(n, "null")
 	}
-	// Perhaps we can use the value as a TextUnmarshaler to
-	// set its value.
-	if out.CanAddr() {
-		u, ok := out.Addr().Interface().(encoding.TextUnmarshaler)
-		if ok {
-			var text []byte
-			if tag == yaml_BINARY_TAG {
-				text = []byte(resolved.(string))
-			} else {
-				// We let any value be unmarshaled into TextUnmarshaler.
-				// That might be more lax than we'd like, but the
-				// TextUnmarshaler itself should bowl out any dubious values.
-				text = []byte(n.value)
-			}
-			err := u.UnmarshalText(text)
-			if err != nil {
-				fail(err)
-			}
-			return true
-		}
+	err := &ast.BottomLit{
+		// Bottom: d.pos(n.startPos)
+		Bottom: token.Pos(d.p.parser.relPos()),
 	}
-	switch out.Kind() {
-	case reflect.String:
-		if tag == yaml_BINARY_TAG {
-			out.SetString(resolved.(string))
-			return true
-		}
-		if resolved != nil {
-			out.SetString(n.value)
-			return true
-		}
-	case reflect.Interface:
-		if resolved == nil {
-			out.Set(reflect.Zero(out.Type()))
-		} else if tag == yaml_TIMESTAMP_TAG {
-			// It looks like a timestamp but for backward compatibility
-			// reasons we set it as a string, so that code that unmarshals
-			// timestamp-like values into interface{} will continue to
-			// see a string and not a time.Time.
-			// TODO(v3) Drop this.
-			out.Set(reflect.ValueOf(n.value))
-		} else {
-			out.Set(reflect.ValueOf(resolved))
-		}
-		return true
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		switch resolved := resolved.(type) {
-		case int:
-			if !out.OverflowInt(int64(resolved)) {
-				out.SetInt(int64(resolved))
-				return true
-			}
-		case int64:
-			if !out.OverflowInt(resolved) {
-				out.SetInt(resolved)
-				return true
-			}
-		case uint64:
-			if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
-				out.SetInt(int64(resolved))
-				return true
-			}
-		case float64:
-			if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
-				out.SetInt(int64(resolved))
-				return true
-			}
-		case string:
-			if out.Type() == durationType {
-				d, err := time.ParseDuration(resolved)
-				if err == nil {
-					out.SetInt(int64(d))
-					return true
+	comment := &ast.Comment{
+		// Slash: d.start(n),
+		Slash: token.Pos(token.Blank),
+		Text:  "// " + d.terror(n, tag),
+	}
+	err.AddComment(&ast.CommentGroup{
+		Line:     true,
+		Position: 1,
+		List:     []*ast.Comment{comment},
+	})
+	return err
+}
+
+func (d *decoder) label(n *node) ast.Label {
+	var tag string
+	if n.tag == "" && !n.implicit {
+		tag = yaml_STR_TAG
+	} else {
+		tag, _ = d.resolve(n)
+	}
+	if tag == yaml_STR_TAG {
+		// TODO: improve
+		for i, r := range n.value {
+			if !unicode.In(r, unicode.L) && r != '_' {
+				if i == 0 || !unicode.In(r, unicode.N) {
+					goto stringLabel
 				}
 			}
 		}
-	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-		switch resolved := resolved.(type) {
-		case int:
-			if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
-				out.SetUint(uint64(resolved))
-				return true
-			}
-		case int64:
-			if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
-				out.SetUint(uint64(resolved))
-				return true
-			}
-		case uint64:
-			if !out.OverflowUint(uint64(resolved)) {
-				out.SetUint(uint64(resolved))
-				return true
-			}
-		case float64:
-			if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) {
-				out.SetUint(uint64(resolved))
-				return true
-			}
-		}
-	case reflect.Bool:
-		switch resolved := resolved.(type) {
-		case bool:
-			out.SetBool(resolved)
-			return true
-		}
-	case reflect.Float32, reflect.Float64:
-		switch resolved := resolved.(type) {
-		case int:
-			out.SetFloat(float64(resolved))
-			return true
-		case int64:
-			out.SetFloat(float64(resolved))
-			return true
-		case uint64:
-			out.SetFloat(float64(resolved))
-			return true
-		case float64:
-			out.SetFloat(resolved)
-			return true
-		}
-	case reflect.Struct:
-		if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
-			out.Set(resolvedv)
-			return true
-		}
-	case reflect.Ptr:
-		if out.Type().Elem() == reflect.TypeOf(resolved) {
-			// TODO DOes this make sense? When is out a Ptr except when decoding a nil value?
-			elem := reflect.New(out.Type().Elem())
-			elem.Elem().Set(reflect.ValueOf(resolved))
-			out.Set(elem)
-			return true
+		return d.ident(n, n.value)
+	}
+stringLabel:
+	return &ast.BasicLit{
+		ValuePos: token.Pos(d.p.parser.relPos()),
+		// ValuePos: d.start(n),
+		Kind:  token.STRING,
+		Value: strconv.Quote(n.value),
+	}
+}
+
+func (d *decoder) makeNum(n *node, val string, kind token.Token) (expr ast.Expr) {
+	minuses := 0
+	for ; val[0] == '-'; val = val[1:] {
+		minuses++
+	}
+	expr = &ast.BasicLit{
+		// ValuePos: d.start(n) + token.Pos(minuses),
+		ValuePos: token.Pos(d.p.parser.relPos()),
+		Kind:     kind,
+		Value:    val,
+	}
+	if minuses > 0 {
+		expr = &ast.UnaryExpr{
+			// OpPos: d.start(n),
+			OpPos: token.Pos(d.p.parser.relPos()),
+			Op:    token.SUB,
+			X:     expr,
 		}
 	}
-	d.terror(n, tag, out)
-	return false
+	return expr
 }
 
-func settableValueOf(i interface{}) reflect.Value {
-	v := reflect.ValueOf(i)
-	sv := reflect.New(v.Type()).Elem()
-	sv.Set(v)
-	return sv
+// quoteString converts a string to a CUE multiline string if needed.
+func (d *decoder) quoteString(s string) string {
+	lines := []string{}
+	last := 0
+	for i, c := range s {
+		if c == '\n' {
+			lines = append(lines, s[last:i])
+			last = i + 1
+		}
+		if c == '\r' {
+			goto quoted
+		}
+	}
+	lines = append(lines, s[last:])
+	if len(lines) >= 2 {
+		buf := []byte{}
+		buf = append(buf, `"""`+"\n"...)
+		for _, l := range lines {
+			if l == "" {
+				// no indentation for empty lines
+				buf = append(buf, '\n')
+				continue
+			}
+			buf = append(buf, '\t')
+			p := len(buf)
+			buf = strconv.AppendQuote(buf, l)
+			// remove quotes
+			buf[p] = '\t'
+			buf[len(buf)-1] = '\n'
+		}
+		buf = append(buf, "\t\t"+`"""`...)
+		return string(buf)
+	}
+quoted:
+	return strconv.Quote(s)
 }
 
-func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
+func (d *decoder) sequence(n *node) ast.Expr {
+	list := &ast.ListLit{}
+	if n.startPos.line != n.endPos.line || len(n.children) != 1 {
+		list.Lbrack = d.pos(n.startPos)
+		list.Rbrack = d.pos(n.endPos)
+	}
+	for _, c := range n.children {
+		list.Elts = append(list.Elts, d.unmarshal(c))
+	}
+	return list
+}
+
+func (d *decoder) mapping(n *node) ast.Expr {
+	structure := &ast.StructLit{}
+	d.insertMap(n, structure, false)
+	if len(structure.Elts) != 1 {
+		structure.Lbrace = d.pos(n.startPos)
+		structure.Rbrace = d.pos(n.endPos)
+	}
+	return structure
+}
+
+func (d *decoder) insertMap(n *node, m *ast.StructLit, merge bool) {
 	l := len(n.children)
-
-	var iface reflect.Value
-	switch out.Kind() {
-	case reflect.Slice:
-		out.Set(reflect.MakeSlice(out.Type(), l, l))
-	case reflect.Array:
-		if l != out.Len() {
-			failf("invalid array: want %d elements but got %d", out.Len(), l)
-		}
-	case reflect.Interface:
-		// No type hints. Will have to use a generic sequence.
-		iface = out
-		out = settableValueOf(make([]interface{}, l))
-	default:
-		d.terror(n, yaml_SEQ_TAG, out)
-		return false
-	}
-	et := out.Type().Elem()
-
-	j := 0
-	for i := 0; i < l; i++ {
-		e := reflect.New(et).Elem()
-		if ok := d.unmarshal(n.children[i], e); ok {
-			out.Index(j).Set(e)
-			j++
-		}
-	}
-	if out.Kind() != reflect.Array {
-		out.Set(out.Slice(0, j))
-	}
-	if iface.IsValid() {
-		iface.Set(out)
-	}
-	return true
-}
-
-func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
-	switch out.Kind() {
-	case reflect.Struct:
-		return d.mappingStruct(n, out)
-	case reflect.Slice:
-		return d.mappingSlice(n, out)
-	case reflect.Map:
-		// okay
-	case reflect.Interface:
-		if d.mapType.Kind() == reflect.Map {
-			iface := out
-			out = reflect.MakeMap(d.mapType)
-			iface.Set(out)
-		} else {
-			slicev := reflect.New(d.mapType).Elem()
-			if !d.mappingSlice(n, slicev) {
-				return false
-			}
-			out.Set(slicev)
-			return true
-		}
-	default:
-		d.terror(n, yaml_MAP_TAG, out)
-		return false
-	}
-	outt := out.Type()
-	kt := outt.Key()
-	et := outt.Elem()
-
-	mapType := d.mapType
-	if outt.Key() == ifaceType && outt.Elem() == ifaceType {
-		d.mapType = outt
-	}
-
-	if out.IsNil() {
-		out.Set(reflect.MakeMap(outt))
-	}
-	l := len(n.children)
+outer:
 	for i := 0; i < l; i += 2 {
 		if isMerge(n.children[i]) {
-			d.merge(n.children[i+1], out)
+			merge = true
+			d.merge(n.children[i+1], m)
 			continue
 		}
-		k := reflect.New(kt).Elem()
-		if d.unmarshal(n.children[i], k) {
-			kkind := k.Kind()
-			if kkind == reflect.Interface {
-				kkind = k.Elem().Kind()
-			}
-			if kkind == reflect.Map || kkind == reflect.Slice {
-				failf("invalid map key: %#v", k.Interface())
-			}
-			e := reflect.New(et).Elem()
-			if d.unmarshal(n.children[i+1], e) {
-				d.setMapIndex(n.children[i+1], out, k, e)
-			}
+		switch n.children[i].kind {
+		case mappingNode:
+			d.p.failf(n.startPos.line, "invalid map key: map")
+		case sequenceNode:
+			d.p.failf(n.startPos.line, "invalid map key: sequence")
 		}
-	}
-	d.mapType = mapType
-	return true
-}
 
-func (d *decoder) setMapIndex(n *node, out, k, v reflect.Value) {
-	if d.strict && out.MapIndex(k) != zeroValue {
-		d.terrors = append(d.terrors, fmt.Sprintf("line %d: key %#v already set in map", n.line+1, k.Interface()))
-		return
-	}
-	out.SetMapIndex(k, v)
-}
+		field := &ast.Field{}
+		d.attachDocComments(n.children[i].startPos, 0, field)
 
-func (d *decoder) mappingSlice(n *node, out reflect.Value) (good bool) {
-	outt := out.Type()
-	if outt.Elem() != mapItemType {
-		d.terror(n, yaml_MAP_TAG, out)
-		return false
-	}
+		label := d.label(n.children[i])
+		field.Label = label
+		d.attachLineComment(n.children[i].endPos, 1, label)
 
-	mapType := d.mapType
-	d.mapType = outt
-
-	var slice []MapItem
-	var l = len(n.children)
-	for i := 0; i < l; i += 2 {
-		if isMerge(n.children[i]) {
-			d.merge(n.children[i+1], out)
-			continue
-		}
-		item := MapItem{}
-		k := reflect.ValueOf(&item.Key).Elem()
-		if d.unmarshal(n.children[i], k) {
-			v := reflect.ValueOf(&item.Value).Elem()
-			if d.unmarshal(n.children[i+1], v) {
-				slice = append(slice, item)
-			}
-		}
-	}
-	out.Set(reflect.ValueOf(slice))
-	d.mapType = mapType
-	return true
-}
-
-func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
-	sinfo, err := getStructInfo(out.Type())
-	if err != nil {
-		panic(err)
-	}
-	name := settableValueOf("")
-	l := len(n.children)
-
-	var inlineMap reflect.Value
-	var elemType reflect.Type
-	if sinfo.InlineMap != -1 {
-		inlineMap = out.Field(sinfo.InlineMap)
-		inlineMap.Set(reflect.New(inlineMap.Type()).Elem())
-		elemType = inlineMap.Type().Elem()
-	}
-
-	var doneFields []bool
-	if d.strict {
-		doneFields = make([]bool, len(sinfo.FieldsList))
-	}
-	for i := 0; i < l; i += 2 {
-		ni := n.children[i]
-		if isMerge(ni) {
-			d.merge(n.children[i+1], out)
-			continue
-		}
-		if !d.unmarshal(ni, name) {
-			continue
-		}
-		if info, ok := sinfo.FieldsMap[name.String()]; ok {
-			if d.strict {
-				if doneFields[info.Id] {
-					d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.line+1, name.String(), out.Type()))
-					continue
+		if merge {
+			key := labelStr(label)
+			for _, decl := range m.Elts {
+				f := decl.(*ast.Field)
+				name, _ := ast.LabelName(f.Label)
+				if name == key {
+					f.Value = d.unmarshal(n.children[i+1])
+					continue outer
 				}
-				doneFields[info.Id] = true
 			}
-			var field reflect.Value
-			if info.Inline == nil {
-				field = out.Field(info.Num)
-			} else {
-				field = out.FieldByIndex(info.Inline)
-			}
-			d.unmarshal(n.children[i+1], field)
-		} else if sinfo.InlineMap != -1 {
-			if inlineMap.IsNil() {
-				inlineMap.Set(reflect.MakeMap(inlineMap.Type()))
-			}
-			value := reflect.New(elemType).Elem()
-			d.unmarshal(n.children[i+1], value)
-			d.setMapIndex(n.children[i+1], inlineMap, name, value)
-		} else if d.strict {
-			d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.line+1, name.String(), out.Type()))
 		}
+
+		value := d.unmarshal(n.children[i+1])
+		field.Value = value
+		d.attachDocComments(n.children[i+1].startPos, 0, value)
+		d.attachLineComment(n.children[i+1].endPos, 10, value)
+
+		m.Elts = append(m.Elts, field)
 	}
-	return true
 }
 
-func failWantMap() {
-	failf("map merge requires map or sequence of maps as the value")
+func labelStr(l ast.Label) string {
+	switch x := l.(type) {
+	case *ast.Ident:
+		return x.Name
+	case *ast.BasicLit:
+		s, _ := strconv.Unquote(x.Value)
+		return s
+	}
+	return ""
 }
 
-func (d *decoder) merge(n *node, out reflect.Value) {
+func (d *decoder) failWantMap(n *node) {
+	d.p.failf(n.startPos.line, "map merge requires map or sequence of maps as the value")
+}
+
+func (d *decoder) merge(n *node, m *ast.StructLit) {
 	switch n.kind {
 	case mappingNode:
-		d.unmarshal(n, out)
+		d.insertMap(n, m, true)
 	case aliasNode:
 		an, ok := d.doc.anchors[n.value]
 		if ok && an.kind != mappingNode {
-			failWantMap()
+			d.failWantMap(n)
 		}
-		d.unmarshal(n, out)
+		d.insertMap(an, m, true)
 	case sequenceNode:
 		// Step backwards as earlier nodes take precedence.
 		for i := len(n.children) - 1; i >= 0; i-- {
@@ -758,15 +680,17 @@
 			if ni.kind == aliasNode {
 				an, ok := d.doc.anchors[ni.value]
 				if ok && an.kind != mappingNode {
-					failWantMap()
+					d.failWantMap(n)
 				}
+				d.insertMap(an, m, true)
+				continue
 			} else if ni.kind != mappingNode {
-				failWantMap()
+				d.failWantMap(n)
 			}
-			d.unmarshal(ni, out)
+			d.insertMap(ni, m, true)
 		}
 	default:
-		failWantMap()
+		d.failWantMap(n)
 	}
 }
 
diff --git a/internal/third_party/yaml/decode_test.go b/internal/third_party/yaml/decode_test.go
index 9269f12..be4d034 100644
--- a/internal/third_party/yaml/decode_test.go
+++ b/internal/third_party/yaml/decode_test.go
@@ -1,94 +1,100 @@
 package yaml_test
 
 import (
+	"bytes"
 	"errors"
+	"flag"
+	"fmt"
 	"io"
-	"math"
-	"reflect"
+	"io/ioutil"
+	"strconv"
 	"strings"
-	"time"
+	"testing"
 
-	. "gopkg.in/check.v1"
-	"gopkg.in/yaml.v2"
+	"cuelang.org/go/cue/ast"
+	"cuelang.org/go/cue/format"
+	"cuelang.org/go/cue/token"
+	"cuelang.org/go/internal/third_party/yaml"
 )
 
+var update = flag.Bool("update", false, "update test data")
+
 var unmarshalIntTest = 123
 
 var unmarshalTests = []struct {
-	data  string
-	value interface{}
+	data string
+	want string
 }{
 	{
 		"",
-		(*struct{})(nil),
+		"",
 	},
 	{
-		"{}", &struct{}{},
+		"{}",
+		"",
 	}, {
 		"v: hi",
-		map[string]string{"v": "hi"},
+		`v: "hi"`,
 	}, {
-		"v: hi", map[string]interface{}{"v": "hi"},
+		"v: hi",
+		`v: "hi"`,
 	}, {
 		"v: true",
-		map[string]string{"v": "true"},
-	}, {
 		"v: true",
-		map[string]interface{}{"v": true},
 	}, {
 		"v: 10",
-		map[string]interface{}{"v": 10},
+		"v: 10",
 	}, {
 		"v: 0b10",
-		map[string]interface{}{"v": 2},
+		"v: 0b10",
 	}, {
 		"v: 0xA",
-		map[string]interface{}{"v": 10},
+		"v: 0xA",
 	}, {
 		"v: 4294967296",
-		map[string]int64{"v": 4294967296},
+		"v: 4294967296",
 	}, {
 		"v: 0.1",
-		map[string]interface{}{"v": 0.1},
+		"v: 0.1",
 	}, {
 		"v: .1",
-		map[string]interface{}{"v": 0.1},
+		"v: .1",
 	}, {
 		"v: .Inf",
-		map[string]interface{}{"v": math.Inf(+1)},
+		"v: +Inf",
 	}, {
 		"v: -.Inf",
-		map[string]interface{}{"v": math.Inf(-1)},
+		"v: -Inf",
 	}, {
 		"v: -10",
-		map[string]interface{}{"v": -10},
+		"v: -10",
 	}, {
 		"v: -.1",
-		map[string]interface{}{"v": -0.1},
+		"v: -.1",
 	},
 
 	// Simple values.
 	{
 		"123",
-		&unmarshalIntTest,
+		"123",
 	},
 
 	// Floats from spec
 	{
 		"canonical: 6.8523e+5",
-		map[string]interface{}{"canonical": 6.8523e+5},
+		"canonical: 6.8523e+5",
 	}, {
 		"expo: 685.230_15e+03",
-		map[string]interface{}{"expo": 685.23015e+03},
+		"expo: 685.230_15e+03",
 	}, {
 		"fixed: 685_230.15",
-		map[string]interface{}{"fixed": 685230.15},
+		"fixed: 685_230.15",
 	}, {
 		"neginf: -.inf",
-		map[string]interface{}{"neginf": math.Inf(-1)},
+		"neginf: -Inf",
 	}, {
 		"fixed: 685_230.15",
-		map[string]float64{"fixed": 685230.15},
+		"fixed: 685_230.15",
 	},
 	//{"sexa: 190:20:30.15", map[string]interface{}{"sexa": 0}}, // Unsupported
 	//{"notanum: .NaN", map[string]interface{}{"notanum": math.NaN()}}, // Equality of NaN fails.
@@ -96,45 +102,42 @@
 	// Bools from spec
 	{
 		"canonical: y",
-		map[string]interface{}{"canonical": true},
+		"canonical: true",
 	}, {
 		"answer: NO",
-		map[string]interface{}{"answer": false},
+		"answer: false",
 	}, {
 		"logical: True",
-		map[string]interface{}{"logical": true},
+		"logical: true",
 	}, {
 		"option: on",
-		map[string]interface{}{"option": true},
-	}, {
-		"option: on",
-		map[string]bool{"option": true},
+		"option: true",
 	},
 	// Ints from spec
 	{
 		"canonical: 685230",
-		map[string]interface{}{"canonical": 685230},
+		"canonical: 685230",
 	}, {
 		"decimal: +685_230",
-		map[string]interface{}{"decimal": 685230},
+		"decimal: +685_230",
 	}, {
 		"octal: 02472256",
-		map[string]interface{}{"octal": 685230},
+		"octal: 02472256",
 	}, {
 		"hexa: 0x_0A_74_AE",
-		map[string]interface{}{"hexa": 685230},
+		"hexa: 0x_0A_74_AE",
 	}, {
 		"bin: 0b1010_0111_0100_1010_1110",
-		map[string]interface{}{"bin": 685230},
+		"bin: 0b1010_0111_0100_1010_1110",
 	}, {
 		"bin: -0b101010",
-		map[string]interface{}{"bin": -42},
+		"bin: -0b101010",
 	}, {
 		"bin: -0b1000000000000000000000000000000000000000000000000000000000000000",
-		map[string]interface{}{"bin": -9223372036854775808},
+		"bin: -0b1000000000000000000000000000000000000000000000000000000000000000",
 	}, {
 		"decimal: +685_230",
-		map[string]int{"decimal": 685230},
+		"decimal: +685_230",
 	},
 
 	//{"sexa: 190:20:30", map[string]interface{}{"sexa": 0}}, // Unsupported
@@ -142,339 +145,276 @@
 	// Nulls from spec
 	{
 		"empty:",
-		map[string]interface{}{"empty": nil},
+		"empty: null",
 	}, {
 		"canonical: ~",
-		map[string]interface{}{"canonical": nil},
+		"canonical: null",
 	}, {
 		"english: null",
-		map[string]interface{}{"english": nil},
+		"english: null",
 	}, {
 		"~: null key",
-		map[interface{}]string{nil: "null key"},
-	}, {
-		"empty:",
-		map[string]*bool{"empty": nil},
+		`"~": "null key"`,
 	},
 
 	// Flow sequence
 	{
 		"seq: [A,B]",
-		map[string]interface{}{"seq": []interface{}{"A", "B"}},
+		`seq: ["A", "B"]`,
 	}, {
 		"seq: [A,B,C,]",
-		map[string][]string{"seq": []string{"A", "B", "C"}},
+		`seq: ["A", "B", "C"]`,
 	}, {
 		"seq: [A,1,C]",
-		map[string][]string{"seq": []string{"A", "1", "C"}},
-	}, {
-		"seq: [A,1,C]",
-		map[string][]int{"seq": []int{1}},
-	}, {
-		"seq: [A,1,C]",
-		map[string]interface{}{"seq": []interface{}{"A", 1, "C"}},
+		`seq: ["A", 1, "C"]`,
 	},
 	// Block sequence
 	{
 		"seq:\n - A\n - B",
-		map[string]interface{}{"seq": []interface{}{"A", "B"}},
+		`seq: ["A", "B"]`,
 	}, {
 		"seq:\n - A\n - B\n - C",
-		map[string][]string{"seq": []string{"A", "B", "C"}},
+		`seq: ["A", "B", "C"]`,
 	}, {
 		"seq:\n - A\n - 1\n - C",
-		map[string][]string{"seq": []string{"A", "1", "C"}},
-	}, {
-		"seq:\n - A\n - 1\n - C",
-		map[string][]int{"seq": []int{1}},
-	}, {
-		"seq:\n - A\n - 1\n - C",
-		map[string]interface{}{"seq": []interface{}{"A", 1, "C"}},
+		`seq: ["A", 1, "C"]`,
 	},
 
 	// Literal block scalar
 	{
 		"scalar: | # Comment\n\n literal\n\n \ttext\n\n",
-		map[string]string{"scalar": "\nliteral\n\n\ttext\n"},
+		`scalar: """
+
+		literal
+
+		\ttext
+
+		"""`,
 	},
 
 	// Folded block scalar
 	{
 		"scalar: > # Comment\n\n folded\n line\n \n next\n line\n  * one\n  * two\n\n last\n line\n\n",
-		map[string]string{"scalar": "\nfolded line\nnext line\n * one\n * two\n\nlast line\n"},
+		`scalar: """
+
+		folded line
+		next line
+		 * one
+		 * two
+
+		last line
+
+		"""`,
 	},
 
-	// Map inside interface with no type hints.
+	// Structs
 	{
 		"a: {b: c}",
-		map[interface{}]interface{}{"a": map[interface{}]interface{}{"b": "c"}},
+		`a b: "c"`,
 	},
-
-	// Structs and type conversions.
 	{
 		"hello: world",
-		&struct{ Hello string }{"world"},
-	}, {
-		"a: {b: c}",
-		&struct{ A struct{ B string } }{struct{ B string }{"c"}},
-	}, {
-		"a: {b: c}",
-		&struct{ A *struct{ B string } }{&struct{ B string }{"c"}},
-	}, {
-		"a: {b: c}",
-		&struct{ A map[string]string }{map[string]string{"b": "c"}},
-	}, {
-		"a: {b: c}",
-		&struct{ A *map[string]string }{&map[string]string{"b": "c"}},
+		`hello: "world"`,
 	}, {
 		"a:",
-		&struct{ A map[string]string }{},
+		"a: null",
 	}, {
 		"a: 1",
-		&struct{ A int }{1},
-	}, {
 		"a: 1",
-		&struct{ A float64 }{1},
 	}, {
 		"a: 1.0",
-		&struct{ A int }{1},
-	}, {
 		"a: 1.0",
-		&struct{ A uint }{1},
 	}, {
 		"a: [1, 2]",
-		&struct{ A []int }{[]int{1, 2}},
-	}, {
 		"a: [1, 2]",
-		&struct{ A [2]int }{[2]int{1, 2}},
-	}, {
-		"a: 1",
-		&struct{ B int }{0},
-	}, {
-		"a: 1",
-		&struct {
-			B int "a"
-		}{1},
 	}, {
 		"a: y",
-		&struct{ A bool }{true},
+		"a: true",
+	}, {
+		"{ a: 1, b: {c: 1} }",
+		"a: 1\nb c: 1",
 	},
 
 	// Some cross type conversions
 	{
 		"v: 42",
-		map[string]uint{"v": 42},
+		"v: 42",
 	}, {
 		"v: -42",
-		map[string]uint{},
+		"v: -42",
 	}, {
 		"v: 4294967296",
-		map[string]uint64{"v": 4294967296},
+		"v: 4294967296",
 	}, {
 		"v: -4294967296",
-		map[string]uint64{},
+		"v: -4294967296",
 	},
 
 	// int
 	{
 		"int_max: 2147483647",
-		map[string]int{"int_max": math.MaxInt32},
+		"int_max: 2147483647",
 	},
 	{
 		"int_min: -2147483648",
-		map[string]int{"int_min": math.MinInt32},
+		"int_min: -2147483648",
 	},
 	{
 		"int_overflow: 9223372036854775808", // math.MaxInt64 + 1
-		map[string]int{},
+		"int_overflow: 9223372036854775808", // math.MaxInt64 + 1
 	},
 
 	// int64
 	{
 		"int64_max: 9223372036854775807",
-		map[string]int64{"int64_max": math.MaxInt64},
+		"int64_max: 9223372036854775807",
 	},
 	{
 		"int64_max_base2: 0b111111111111111111111111111111111111111111111111111111111111111",
-		map[string]int64{"int64_max_base2": math.MaxInt64},
+		"int64_max_base2: 0b111111111111111111111111111111111111111111111111111111111111111",
 	},
 	{
 		"int64_min: -9223372036854775808",
-		map[string]int64{"int64_min": math.MinInt64},
+		"int64_min: -9223372036854775808",
 	},
 	{
 		"int64_neg_base2: -0b111111111111111111111111111111111111111111111111111111111111111",
-		map[string]int64{"int64_neg_base2": -math.MaxInt64},
+		"int64_neg_base2: -0b111111111111111111111111111111111111111111111111111111111111111",
 	},
 	{
 		"int64_overflow: 9223372036854775808", // math.MaxInt64 + 1
-		map[string]int64{},
+		"int64_overflow: 9223372036854775808", // math.MaxInt64 + 1
 	},
 
 	// uint
 	{
-		"uint_min: 0",
-		map[string]uint{"uint_min": 0},
-	},
-	{
 		"uint_max: 4294967295",
-		map[string]uint{"uint_max": math.MaxUint32},
-	},
-	{
-		"uint_underflow: -1",
-		map[string]uint{},
+		"uint_max: 4294967295",
 	},
 
 	// uint64
 	{
-		"uint64_min: 0",
-		map[string]uint{"uint64_min": 0},
-	},
-	{
 		"uint64_max: 18446744073709551615",
-		map[string]uint64{"uint64_max": math.MaxUint64},
+		"uint64_max: 18446744073709551615",
 	},
 	{
 		"uint64_max_base2: 0b1111111111111111111111111111111111111111111111111111111111111111",
-		map[string]uint64{"uint64_max_base2": math.MaxUint64},
+		"uint64_max_base2: 0b1111111111111111111111111111111111111111111111111111111111111111",
 	},
 	{
 		"uint64_maxint64: 9223372036854775807",
-		map[string]uint64{"uint64_maxint64": math.MaxInt64},
-	},
-	{
-		"uint64_underflow: -1",
-		map[string]uint64{},
+		"uint64_maxint64: 9223372036854775807",
 	},
 
 	// float32
 	{
 		"float32_max: 3.40282346638528859811704183484516925440e+38",
-		map[string]float32{"float32_max": math.MaxFloat32},
+		"float32_max: 3.40282346638528859811704183484516925440e+38",
 	},
 	{
 		"float32_nonzero: 1.401298464324817070923729583289916131280e-45",
-		map[string]float32{"float32_nonzero": math.SmallestNonzeroFloat32},
+		"float32_nonzero: 1.401298464324817070923729583289916131280e-45",
 	},
 	{
 		"float32_maxuint64: 18446744073709551615",
-		map[string]float32{"float32_maxuint64": float32(math.MaxUint64)},
+		"float32_maxuint64: 18446744073709551615",
 	},
 	{
 		"float32_maxuint64+1: 18446744073709551616",
-		map[string]float32{"float32_maxuint64+1": float32(math.MaxUint64 + 1)},
+		`"float32_maxuint64+1": 18446744073709551616`,
 	},
 
 	// float64
 	{
 		"float64_max: 1.797693134862315708145274237317043567981e+308",
-		map[string]float64{"float64_max": math.MaxFloat64},
+		"float64_max: 1.797693134862315708145274237317043567981e+308",
 	},
 	{
 		"float64_nonzero: 4.940656458412465441765687928682213723651e-324",
-		map[string]float64{"float64_nonzero": math.SmallestNonzeroFloat64},
+		"float64_nonzero: 4.940656458412465441765687928682213723651e-324",
 	},
 	{
 		"float64_maxuint64: 18446744073709551615",
-		map[string]float64{"float64_maxuint64": float64(math.MaxUint64)},
+		"float64_maxuint64: 18446744073709551615",
 	},
 	{
 		"float64_maxuint64+1: 18446744073709551616",
-		map[string]float64{"float64_maxuint64+1": float64(math.MaxUint64 + 1)},
+		`"float64_maxuint64+1": 18446744073709551616`,
 	},
 
 	// Overflow cases.
 	{
 		"v: 4294967297",
-		map[string]int32{},
+		"v: 4294967297",
 	}, {
 		"v: 128",
-		map[string]int8{},
+		"v: 128",
 	},
 
 	// Quoted values.
 	{
 		"'1': '\"2\"'",
-		map[interface{}]interface{}{"1": "\"2\""},
+		`"1": "\"2\""`,
 	}, {
 		"v:\n- A\n- 'B\n\n  C'\n",
-		map[string][]string{"v": []string{"A", "B\nC"}},
+		`v: ["A", """
+		B
+		C
+		"""]`,
 	},
 
 	// Explicit tags.
 	{
 		"v: !!float '1.1'",
-		map[string]interface{}{"v": 1.1},
+		"v: 1.1",
 	}, {
 		"v: !!float 0",
-		map[string]interface{}{"v": float64(0)},
+		"v: float & 0", // Should this be 0.0?
 	}, {
 		"v: !!float -1",
-		map[string]interface{}{"v": float64(-1)},
+		"v: float & -1", // Should this be -1.0?
 	}, {
 		"v: !!null ''",
-		map[string]interface{}{"v": nil},
+		"v: null",
 	}, {
 		"%TAG !y! tag:yaml.org,2002:\n---\nv: !y!int '1'",
-		map[string]interface{}{"v": 1},
+		"v: 1",
 	},
 
 	// Non-specific tag (Issue #75)
 	{
 		"v: ! test",
-		map[string]interface{}{"v": "test"},
+		// TODO: map[string]interface{}{"v": "test"},
+		"",
 	},
 
 	// Anchors and aliases.
 	{
 		"a: &x 1\nb: &y 2\nc: *x\nd: *y\n",
-		&struct{ A, B, C, D int }{1, 2, 1, 2},
+		`a: 1
+b: 2
+c: 1
+d: 2`,
 	}, {
 		"a: &a {c: 1}\nb: *a",
-		&struct {
-			A, B struct {
-				C int
-			}
-		}{struct{ C int }{1}, struct{ C int }{1}},
+		"a c: 1\nb c: 1",
 	}, {
 		"a: &a [1, 2]\nb: *a",
-		&struct{ B []int }{[]int{1, 2}},
+		"a: [1, 2]\nb: [1, 2]", // TODO: a: [1, 2], b: a
 	},
 
-	// Bug #1133337
 	{
 		"foo: ''",
-		map[string]*string{"foo": new(string)},
+		`foo: ""`,
 	}, {
 		"foo: null",
-		map[string]*string{"foo": nil},
-	}, {
 		"foo: null",
-		map[string]string{"foo": ""},
-	}, {
-		"foo: null",
-		map[string]interface{}{"foo": nil},
 	},
 
 	// Support for ~
 	{
 		"foo: ~",
-		map[string]*string{"foo": nil},
-	}, {
-		"foo: ~",
-		map[string]string{"foo": ""},
-	}, {
-		"foo: ~",
-		map[string]interface{}{"foo": nil},
-	},
-
-	// Ignored field
-	{
-		"a: 1\nb: 2\n",
-		&struct {
-			A int
-			B int "-"
-		}{1, 0},
+		"foo: null",
 	},
 
 	// Bug #1191981
@@ -486,139 +426,108 @@
 			` Generic line break (glyphed)\n\` + "\n" +
 			` Line separator\u2028\` + "\n" +
 			` Paragraph separator\u2029"` + "\n",
-		"" +
-			"Generic line break (no glyph)\n" +
-			"Generic line break (glyphed)\n" +
-			"Line separator\u2028Paragraph separator\u2029",
-	},
-
-	// Struct inlining
-	{
-		"a: 1\nb: 2\nc: 3\n",
-		&struct {
-			A int
-			C inlineB `yaml:",inline"`
-		}{1, inlineB{2, inlineC{3}}},
-	},
-
-	// Map inlining
-	{
-		"a: 1\nb: 2\nc: 3\n",
-		&struct {
-			A int
-			C map[string]int `yaml:",inline"`
-		}{1, map[string]int{"b": 2, "c": 3}},
+		`"""
+		Generic line break (no glyph)
+		Generic line break (glyphed)
+		Line separator\u2028Paragraph separator\u2029
+		"""`,
 	},
 
 	// bug 1243827
 	{
 		"a: -b_c",
-		map[string]interface{}{"a": "-b_c"},
+		`a: "-b_c"`,
 	},
 	{
 		"a: +b_c",
-		map[string]interface{}{"a": "+b_c"},
+		`a: "+b_c"`,
 	},
 	{
 		"a: 50cent_of_dollar",
-		map[string]interface{}{"a": "50cent_of_dollar"},
+		`a: "50cent_of_dollar"`,
 	},
 
 	// issue #295 (allow scalars with colons in flow mappings and sequences)
 	{
 		"a: {b: https://github.com/go-yaml/yaml}",
-		map[string]interface{}{"a": map[interface{}]interface{}{
-			"b": "https://github.com/go-yaml/yaml",
-		}},
+		`a b: "https://github.com/go-yaml/yaml"`,
 	},
 	{
 		"a: [https://github.com/go-yaml/yaml]",
-		map[string]interface{}{"a": []interface{}{"https://github.com/go-yaml/yaml"}},
+		`a: ["https://github.com/go-yaml/yaml"]`,
 	},
 
 	// Duration
 	{
 		"a: 3s",
-		map[string]time.Duration{"a": 3 * time.Second},
+		`a: "3s"`, // for now
 	},
 
 	// Issue #24.
 	{
 		"a: <foo>",
-		map[string]string{"a": "<foo>"},
+		`a: "<foo>"`,
 	},
 
 	// Base 60 floats are obsolete and unsupported.
 	{
 		"a: 1:1\n",
-		map[string]string{"a": "1:1"},
+		`a: "1:1"`,
 	},
 
 	// Binary data.
 	{
 		"a: !!binary gIGC\n",
-		map[string]string{"a": "\x80\x81\x82"},
+		`a: '\x80\x81\x82'`,
 	}, {
 		"a: !!binary |\n  " + strings.Repeat("kJCQ", 17) + "kJ\n  CQ\n",
-		map[string]string{"a": strings.Repeat("\x90", 54)},
+		"a: '" + strings.Repeat(`\x90`, 54) + "'",
 	}, {
 		"a: !!binary |\n  " + strings.Repeat("A", 70) + "\n  ==\n",
-		map[string]string{"a": strings.Repeat("\x00", 52)},
+		"a: '" + strings.Repeat(`\x00`, 52) + "'",
 	},
 
 	// Ordered maps.
 	{
 		"{b: 2, a: 1, d: 4, c: 3, sub: {e: 5}}",
-		&yaml.MapSlice{{"b", 2}, {"a", 1}, {"d", 4}, {"c", 3}, {"sub", yaml.MapSlice{{"e", 5}}}},
+		`b: 2
+a: 1
+d: 4
+c: 3
+sub e: 5`,
 	},
 
 	// Issue #39.
 	{
 		"a:\n b:\n  c: d\n",
-		map[string]struct{ B interface{} }{"a": {map[interface{}]interface{}{"c": "d"}}},
-	},
-
-	// Custom map type.
-	{
-		"a: {b: c}",
-		M{"a": M{"b": "c"}},
-	},
-
-	// Support encoding.TextUnmarshaler.
-	{
-		"a: 1.2.3.4\n",
-		map[string]textUnmarshaler{"a": textUnmarshaler{S: "1.2.3.4"}},
-	},
-	{
-		"a: 2015-02-24T18:19:39Z\n",
-		map[string]textUnmarshaler{"a": textUnmarshaler{"2015-02-24T18:19:39Z"}},
+		`a b c: "d"`,
 	},
 
 	// Timestamps
 	{
 		// Date only.
 		"a: 2015-01-01\n",
-		map[string]time.Time{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)},
+		`a: "2015-01-01"`,
 	},
 	{
 		// RFC3339
 		"a: 2015-02-24T18:19:39.12Z\n",
-		map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, .12e9, time.UTC)},
+		`a: "2015-02-24T18:19:39.12Z"`,
 	},
 	{
 		// RFC3339 with short dates.
 		"a: 2015-2-3T3:4:5Z",
-		map[string]time.Time{"a": time.Date(2015, 2, 3, 3, 4, 5, 0, time.UTC)},
+		`a: "2015-2-3T3:4:5Z"`,
 	},
 	{
 		// ISO8601 lower case t
 		"a: 2015-02-24t18:19:39Z\n",
-		map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, 0, time.UTC)},
+		`a: "2015-02-24t18:19:39Z"`,
 	},
 	{
 		// space separate, no time zone
 		"a: 2015-02-24 18:19:39\n",
-		map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, 0, time.UTC)},
+		`a: "2015-02-24 18:19:39"`,
 	},
 	// Some cases not currently handled. Uncomment these when
 	// the code is fixed.
@@ -635,84 +544,72 @@
 	{
 		// explicit string tag
 		"a: !!str 2015-01-01",
-		map[string]interface{}{"a": "2015-01-01"},
+		`a: "2015-01-01"`,
 	},
 	{
 		// explicit timestamp tag on quoted string
 		"a: !!timestamp \"2015-01-01\"",
-		map[string]time.Time{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)},
+		`a: "2015-01-01"`,
 	},
 	{
 		// explicit timestamp tag on unquoted string
 		"a: !!timestamp 2015-01-01",
-		map[string]time.Time{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)},
+		`a: "2015-01-01"`,
 	},
 	{
 		// quoted string that's a valid timestamp
 		"a: \"2015-01-01\"",
-		map[string]interface{}{"a": "2015-01-01"},
-	},
-	{
-		// explicit timestamp tag into interface.
-		"a: !!timestamp \"2015-01-01\"",
-		map[string]interface{}{"a": "2015-01-01"},
-	},
-	{
-		// implicit timestamp tag into interface.
-		"a: 2015-01-01",
-		map[string]interface{}{"a": "2015-01-01"},
+		"a: \"2015-01-01\"",
 	},
 
-	// Encode empty lists as zero-length slices.
+	// Empty list
 	{
 		"a: []",
-		&struct{ A []int }{[]int{}},
+		"a: []",
 	},
 
 	// UTF-16-LE
 	{
 		"\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n\x00",
-		M{"ñoño": "very yes"},
+		`ñoño: "very yes"`,
 	},
 	// UTF-16-LE with surrogate.
 	{
 		"\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \x00=\xd8\xd4\xdf\n\x00",
-		M{"ñoño": "very yes 🟔"},
+		`ñoño: "very yes 🟔"`,
 	},
 
 	// UTF-16-BE
 	{
 		"\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n",
-		M{"ñoño": "very yes"},
+		`ñoño: "very yes"`,
 	},
 	// UTF-16-BE with surrogate.
 	{
 		"\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \xd8=\xdf\xd4\x00\n",
-		M{"ñoño": "very yes 🟔"},
+		`ñoño: "very yes 🟔"`,
 	},
 
 	// YAML Float regex shouldn't match this
 	{
 		"a: 123456e1\n",
-		M{"a": "123456e1"},
+		`a: "123456e1"`,
 	}, {
 		"a: 123456E1\n",
-		M{"a": "123456E1"},
+		`a: "123456E1"`,
 	},
 	// yaml-test-suite 3GZX: Spec Example 7.1. Alias Nodes
 	{
 		"First occurrence: &anchor Foo\nSecond occurrence: *anchor\nOverride anchor: &anchor Bar\nReuse anchor: *anchor\n",
-		map[interface{}]interface{}{
-			"Reuse anchor":      "Bar",
-			"First occurrence":  "Foo",
-			"Second occurrence": "Foo",
-			"Override anchor":   "Bar",
-		},
+		`"First occurrence":  "Foo"
+"Second occurrence": "Foo"
+"Override anchor":   "Bar"
+"Reuse anchor":      "Bar"`,
 	},
 	// Single document with garbage following it.
 	{
 		"---\nhello\n...\n}not yaml",
-		"hello",
+		`"hello"`,
 	},
 }
 
@@ -727,89 +624,114 @@
 	C int
 }
 
-func (s *S) TestUnmarshal(c *C) {
-	for i, item := range unmarshalTests {
-		c.Logf("test %d: %q", i, item.data)
-		t := reflect.ValueOf(item.value).Type()
-		value := reflect.New(t)
-		err := yaml.Unmarshal([]byte(item.data), value.Interface())
-		if _, ok := err.(*yaml.TypeError); !ok {
-			c.Assert(err, IsNil)
+var fset = token.NewFileSet()
+
+func cueStr(node ast.Node) string {
+	if s, ok := node.(*ast.StructLit); ok {
+		node = &ast.File{
+			Decls: s.Elts,
 		}
-		c.Assert(value.Elem().Interface(), DeepEquals, item.value, Commentf("error: %v", err))
+	}
+	buf := bytes.Buffer{}
+	format.Node(&buf, node)
+	return strings.TrimSpace(buf.String())
+}
+
+func newDecoder(t *testing.T, data string) *yaml.Decoder {
+	dec, err := yaml.NewDecoder(fset, "test.yaml", strings.NewReader(data))
+	if err != nil {
+		t.Fatal(err)
+	}
+	return dec
+}
+
+func callUnmarshal(t *testing.T, data string) (ast.Expr, error) {
+	return yaml.Unmarshal(fset, "test.yaml", []byte(data))
+}
+
+func TestUnmarshal(t *testing.T) {
+	for i, item := range unmarshalTests {
+		t.Run(strconv.Itoa(i), func(t *testing.T) {
+			t.Logf("test %d: %q", i, item.data)
+			expr, err := callUnmarshal(t, item.data)
+			if _, ok := err.(*yaml.TypeError); !ok && err != nil {
+				t.Fatal("expected error to be nil")
+			}
+			if got := cueStr(expr); got != item.want {
+				t.Errorf("\n got: %v;\nwant: %v", got, item.want)
+			}
+		})
 	}
 }
 
-// TODO(v3): This test should also work when unmarshaling onto an interface{}.
-func (s *S) TestUnmarshalFullTimestamp(c *C) {
-	// Full timestamp in same format as encoded. This is confirmed to be
-	// properly decoded by Python as a timestamp as well.
-	var str = "2015-02-24T18:19:39.123456789-03:00"
-	var t time.Time
-	err := yaml.Unmarshal([]byte(str), &t)
-	c.Assert(err, IsNil)
-	c.Assert(t, Equals, time.Date(2015, 2, 24, 18, 19, 39, 123456789, t.Location()))
-	c.Assert(t.In(time.UTC), Equals, time.Date(2015, 2, 24, 21, 19, 39, 123456789, time.UTC))
-}
+// // TODO(v3): This test should also work when unmarshaling onto an interface{}.
+// func (s *S) TestUnmarshalFullTimestamp(c *C) {
+// 	// Full timestamp in same format as encoded. This is confirmed to be
+// 	// properly decoded by Python as a timestamp as well.
+// 	var str = "2015-02-24T18:19:39.123456789-03:00"
+// 	expr, err := yaml.Unmarshal([]byte(str))
+// 	c.Assert(err, IsNil)
+// 	c.Assert(t, Equals, time.Date(2015, 2, 24, 18, 19, 39, 123456789, t.Location()))
+// 	c.Assert(t.In(time.UTC), Equals, time.Date(2015, 2, 24, 21, 19, 39, 123456789, time.UTC))
+// }
 
-func (s *S) TestDecoderSingleDocument(c *C) {
+func TestDecoderSingleDocument(t *testing.T) {
 	// Test that Decoder.Decode works as expected on
 	// all the unmarshal tests.
 	for i, item := range unmarshalTests {
-		c.Logf("test %d: %q", i, item.data)
-		if item.data == "" {
-			// Behaviour differs when there's no YAML.
-			continue
-		}
-		t := reflect.ValueOf(item.value).Type()
-		value := reflect.New(t)
-		err := yaml.NewDecoder(strings.NewReader(item.data)).Decode(value.Interface())
-		if _, ok := err.(*yaml.TypeError); !ok {
-			c.Assert(err, IsNil)
-		}
-		c.Assert(value.Elem().Interface(), DeepEquals, item.value)
+		t.Run(fmt.Sprintf("test %d: %q", i, item.data), func(t *testing.T) {
+			if item.data == "" {
+				// Behaviour differs when there's no YAML.
+				return
+			}
+			expr, err := newDecoder(t, item.data).Decode()
+			if _, ok := err.(*yaml.TypeError); !ok && err != nil {
+				t.Errorf("err should be nil, was %v", err)
+			}
+			if got := cueStr(expr); got != item.want {
+				t.Errorf("\n got: %v;\nwant: %v", got, item.want)
+			}
+		})
 	}
 }
 
 var decoderTests = []struct {
-	data   string
-	values []interface{}
+	data string
+	want string
 }{{
 	"",
-	nil,
+	"",
 }, {
 	"a: b",
-	[]interface{}{
-		map[interface{}]interface{}{"a": "b"},
-	},
+	`a: "b"`,
 }, {
 	"---\na: b\n...\n",
-	[]interface{}{
-		map[interface{}]interface{}{"a": "b"},
-	},
+	`a: "b"`,
 }, {
 	"---\n'hello'\n...\n---\ngoodbye\n...\n",
-	[]interface{}{
-		"hello",
-		"goodbye",
-	},
+	`"hello"` + "\n" + `"goodbye"`,
 }}
 
-func (s *S) TestDecoder(c *C) {
+func TestDecoder(t *testing.T) {
 	for i, item := range decoderTests {
-		c.Logf("test %d: %q", i, item.data)
-		var values []interface{}
-		dec := yaml.NewDecoder(strings.NewReader(item.data))
-		for {
-			var value interface{}
-			err := dec.Decode(&value)
-			if err == io.EOF {
-				break
+		t.Run(fmt.Sprintf("test %d: %q", i, item.data), func(t *testing.T) {
+			var values []string
+			dec := newDecoder(t, item.data)
+			for {
+				expr, err := dec.Decode()
+				if err == io.EOF {
+					break
+				}
+				if err != nil {
+					t.Errorf("err should be nil, was %v", err)
+				}
+				values = append(values, cueStr(expr))
 			}
-			c.Assert(err, IsNil)
-			values = append(values, value)
-		}
-		c.Assert(values, DeepEquals, item.values)
+			got := strings.Join(values, "\n")
+			if got != item.want {
+				t.Errorf("\n got: %v;\nwant: %v", got, item.want)
+			}
+		})
 	}
 }
 
@@ -819,455 +741,92 @@
 	return 0, errors.New("some read error")
 }
 
-func (s *S) TestDecoderReadError(c *C) {
-	err := yaml.NewDecoder(errReader{}).Decode(&struct{}{})
-	c.Assert(err, ErrorMatches, `yaml: input error: some read error`)
-}
-
-func (s *S) TestUnmarshalNaN(c *C) {
-	value := map[string]interface{}{}
-	err := yaml.Unmarshal([]byte("notanum: .NaN"), &value)
-	c.Assert(err, IsNil)
-	c.Assert(math.IsNaN(value["notanum"].(float64)), Equals, true)
+func TestUnmarshalNaN(t *testing.T) {
+	expr, err := callUnmarshal(t, "notanum: .NaN")
+	if err != nil {
+		t.Fatal("unexpected error", err)
+	}
+	got := cueStr(expr)
+	want := "notanum: NaN"
+	if got != want {
+		t.Errorf("got %v; want %v", got, want)
+	}
 }
 
 var unmarshalErrorTests = []struct {
 	data, error string
 }{
-	{"v: !!float 'error'", "yaml: cannot decode !!str `error` as a !!float"},
-	{"v: [A,", "yaml: line 1: did not find expected node content"},
-	{"v:\n- [A,", "yaml: line 2: did not find expected node content"},
-	{"a:\n- b: *,", "yaml: line 2: did not find expected alphabetic or numeric character"},
-	{"a: *b\n", "yaml: unknown anchor 'b' referenced"},
-	{"a: &a\n  b: *a\n", "yaml: anchor 'a' value contains itself"},
-	{"value: -", "yaml: block sequence entries are not allowed in this context"},
-	{"a: !!binary ==", "yaml: !!binary value contains invalid base64 data"},
-	{"{[.]}", `yaml: invalid map key: \[\]interface \{\}\{"\."\}`},
-	{"{{.}}", `yaml: invalid map key: map\[interface\ \{\}\]interface \{\}\{".":interface \{\}\(nil\)\}`},
-	{"b: *a\na: &a {c: 1}", `yaml: unknown anchor 'a' referenced`},
-	{"%TAG !%79! tag:yaml.org,2002:\n---\nv: !%79!int '1'", "yaml: did not find expected whitespace"},
+	{"\nv: !!float 'error'", "test.yaml:2: cannot decode !!str `error` as a !!float"},
+	{"v: [A,", "test.yaml:1: did not find expected node content"},
+	{"v:\n- [A,", "test.yaml:2: did not find expected node content"},
+	{"a:\n- b: *,", "test.yaml:2: did not find expected alphabetic or numeric character"},
+	{"a: *b\n", "test.yaml:1: unknown anchor 'b' referenced"},
+	{"a: &a\n  b: *a\n", "test.yaml:2: anchor 'a' value contains itself"},
+	{"value: -", "test.yaml:1: block sequence entries are not allowed in this context"},
+	{"a: !!binary ==", "test.yaml:1: !!binary value contains invalid base64 data"},
+	{"{[.]}", `test.yaml:1: invalid map key: sequence`},
+	{"{{.}}", `test.yaml:1: invalid map key: map`},
+	{"b: *a\na: &a {c: 1}", `test.yaml:1: unknown anchor 'a' referenced`},
+	{"%TAG !%79! tag:yaml.org,2002:\n---\nv: !%79!int '1'", "test.yaml:1: did not find expected whitespace"},
 }
 
-func (s *S) TestUnmarshalErrors(c *C) {
+func TestUnmarshalErrors(t *testing.T) {
 	for i, item := range unmarshalErrorTests {
-		c.Logf("test %d: %q", i, item.data)
-		var value interface{}
-		err := yaml.Unmarshal([]byte(item.data), &value)
-		c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value))
+		t.Run(fmt.Sprintf("test %d: %q", i, item.data), func(t *testing.T) {
+			expr, err := callUnmarshal(t, item.data)
+			val := ""
+			if expr != nil {
+				val = cueStr(expr)
+			}
+			if err == nil || err.Error() != item.error {
+				t.Errorf("got %v; want %v; (value %v)", err, item.error, val)
+			}
+		})
 	}
 }
 
-func (s *S) TestDecoderErrors(c *C) {
-	for _, item := range unmarshalErrorTests {
-		var value interface{}
-		err := yaml.NewDecoder(strings.NewReader(item.data)).Decode(&value)
-		c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value))
+func TestDecoderErrors(t *testing.T) {
+	for i, item := range unmarshalErrorTests {
+		t.Run(fmt.Sprintf("test %d: %q", i, item.data), func(t *testing.T) {
+			_, err := newDecoder(t, item.data).Decode()
+			if err == nil || err.Error() != item.error {
+				t.Errorf("got %v; want %v", err, item.error)
+			}
+		})
 	}
 }
 
-var unmarshalerTests = []struct {
-	data, tag string
-	value     interface{}
-}{
-	{"_: {hi: there}", "!!map", map[interface{}]interface{}{"hi": "there"}},
-	{"_: [1,A]", "!!seq", []interface{}{1, "A"}},
-	{"_: 10", "!!int", 10},
-	{"_: null", "!!null", nil},
-	{`_: BAR!`, "!!str", "BAR!"},
-	{`_: "BAR!"`, "!!str", "BAR!"},
-	{"_: !!foo 'BAR!'", "!!foo", "BAR!"},
-	{`_: ""`, "!!str", ""},
-}
-
-var unmarshalerResult = map[int]error{}
-
-type unmarshalerType struct {
-	value interface{}
-}
-
-func (o *unmarshalerType) UnmarshalYAML(unmarshal func(v interface{}) error) error {
-	if err := unmarshal(&o.value); err != nil {
-		return err
-	}
-	if i, ok := o.value.(int); ok {
-		if result, ok := unmarshalerResult[i]; ok {
-			return result
-		}
-	}
-	return nil
-}
-
-type unmarshalerPointer struct {
-	Field *unmarshalerType "_"
-}
-
-type unmarshalerValue struct {
-	Field unmarshalerType "_"
-}
-
-func (s *S) TestUnmarshalerPointerField(c *C) {
-	for _, item := range unmarshalerTests {
-		obj := &unmarshalerPointer{}
-		err := yaml.Unmarshal([]byte(item.data), obj)
-		c.Assert(err, IsNil)
-		if item.value == nil {
-			c.Assert(obj.Field, IsNil)
-		} else {
-			c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value))
-			c.Assert(obj.Field.value, DeepEquals, item.value)
-		}
+func TestFiles(t *testing.T) {
+	files := []string{"merge"}
+	for _, test := range files {
+		t.Run(test, func(t *testing.T) {
+			testname := fmt.Sprintf("testdata/%s.test", test)
+			filename := fmt.Sprintf("testdata/%s.out", test)
+			mergeTests, err := ioutil.ReadFile(testname)
+			if err != nil {
+				t.Fatal(err)
+			}
+			expr, err := yaml.Unmarshal(fset, "test.yaml", mergeTests)
+			if err != nil {
+				t.Fatal(err)
+			}
+			got := cueStr(expr)
+			if *update {
+				ioutil.WriteFile(filename, []byte(got), 0644)
+				return
+			}
+			b, err := ioutil.ReadFile(filename)
+			if err != nil {
+				t.Fatal(err)
+			}
+			if want := string(b); got != want {
+				t.Errorf("\n got: %v;\nwant: %v", got, want)
+			}
+		})
 	}
 }
 
-func (s *S) TestUnmarshalerValueField(c *C) {
-	for _, item := range unmarshalerTests {
-		obj := &unmarshalerValue{}
-		err := yaml.Unmarshal([]byte(item.data), obj)
-		c.Assert(err, IsNil)
-		c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value))
-		c.Assert(obj.Field.value, DeepEquals, item.value)
-	}
-}
-
-func (s *S) TestUnmarshalerWholeDocument(c *C) {
-	obj := &unmarshalerType{}
-	err := yaml.Unmarshal([]byte(unmarshalerTests[0].data), obj)
-	c.Assert(err, IsNil)
-	value, ok := obj.value.(map[interface{}]interface{})
-	c.Assert(ok, Equals, true, Commentf("value: %#v", obj.value))
-	c.Assert(value["_"], DeepEquals, unmarshalerTests[0].value)
-}
-
-func (s *S) TestUnmarshalerTypeError(c *C) {
-	unmarshalerResult[2] = &yaml.TypeError{[]string{"foo"}}
-	unmarshalerResult[4] = &yaml.TypeError{[]string{"bar"}}
-	defer func() {
-		delete(unmarshalerResult, 2)
-		delete(unmarshalerResult, 4)
-	}()
-
-	type T struct {
-		Before int
-		After  int
-		M      map[string]*unmarshalerType
-	}
-	var v T
-	data := `{before: A, m: {abc: 1, def: 2, ghi: 3, jkl: 4}, after: B}`
-	err := yaml.Unmarshal([]byte(data), &v)
-	c.Assert(err, ErrorMatches, ""+
-		"yaml: unmarshal errors:\n"+
-		"  line 1: cannot unmarshal !!str `A` into int\n"+
-		"  foo\n"+
-		"  bar\n"+
-		"  line 1: cannot unmarshal !!str `B` into int")
-	c.Assert(v.M["abc"], NotNil)
-	c.Assert(v.M["def"], IsNil)
-	c.Assert(v.M["ghi"], NotNil)
-	c.Assert(v.M["jkl"], IsNil)
-
-	c.Assert(v.M["abc"].value, Equals, 1)
-	c.Assert(v.M["ghi"].value, Equals, 3)
-}
-
-type proxyTypeError struct{}
-
-func (v *proxyTypeError) UnmarshalYAML(unmarshal func(interface{}) error) error {
-	var s string
-	var a int32
-	var b int64
-	if err := unmarshal(&s); err != nil {
-		panic(err)
-	}
-	if s == "a" {
-		if err := unmarshal(&b); err == nil {
-			panic("should have failed")
-		}
-		return unmarshal(&a)
-	}
-	if err := unmarshal(&a); err == nil {
-		panic("should have failed")
-	}
-	return unmarshal(&b)
-}
-
-func (s *S) TestUnmarshalerTypeErrorProxying(c *C) {
-	type T struct {
-		Before int
-		After  int
-		M      map[string]*proxyTypeError
-	}
-	var v T
-	data := `{before: A, m: {abc: a, def: b}, after: B}`
-	err := yaml.Unmarshal([]byte(data), &v)
-	c.Assert(err, ErrorMatches, ""+
-		"yaml: unmarshal errors:\n"+
-		"  line 1: cannot unmarshal !!str `A` into int\n"+
-		"  line 1: cannot unmarshal !!str `a` into int32\n"+
-		"  line 1: cannot unmarshal !!str `b` into int64\n"+
-		"  line 1: cannot unmarshal !!str `B` into int")
-}
-
-type failingUnmarshaler struct{}
-
-var failingErr = errors.New("failingErr")
-
-func (ft *failingUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error {
-	return failingErr
-}
-
-func (s *S) TestUnmarshalerError(c *C) {
-	err := yaml.Unmarshal([]byte("a: b"), &failingUnmarshaler{})
-	c.Assert(err, Equals, failingErr)
-}
-
-type sliceUnmarshaler []int
-
-func (su *sliceUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error {
-	var slice []int
-	err := unmarshal(&slice)
-	if err == nil {
-		*su = slice
-		return nil
-	}
-
-	var intVal int
-	err = unmarshal(&intVal)
-	if err == nil {
-		*su = []int{intVal}
-		return nil
-	}
-
-	return err
-}
-
-func (s *S) TestUnmarshalerRetry(c *C) {
-	var su sliceUnmarshaler
-	err := yaml.Unmarshal([]byte("[1, 2, 3]"), &su)
-	c.Assert(err, IsNil)
-	c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1, 2, 3}))
-
-	err = yaml.Unmarshal([]byte("1"), &su)
-	c.Assert(err, IsNil)
-	c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1}))
-}
-
-// From http://yaml.org/type/merge.html
-var mergeTests = `
-anchors:
-  list:
-    - &CENTER { "x": 1, "y": 2 }
-    - &LEFT   { "x": 0, "y": 2 }
-    - &BIG    { "r": 10 }
-    - &SMALL  { "r": 1 }
-
-# All the following maps are equal:
-
-plain:
-  # Explicit keys
-  "x": 1
-  "y": 2
-  "r": 10
-  label: center/big
-
-mergeOne:
-  # Merge one map
-  << : *CENTER
-  "r": 10
-  label: center/big
-
-mergeMultiple:
-  # Merge multiple maps
-  << : [ *CENTER, *BIG ]
-  label: center/big
-
-override:
-  # Override
-  << : [ *BIG, *LEFT, *SMALL ]
-  "x": 1
-  label: center/big
-
-shortTag:
-  # Explicit short merge tag
-  !!merge "<<" : [ *CENTER, *BIG ]
-  label: center/big
-
-longTag:
-  # Explicit merge long tag
-  !<tag:yaml.org,2002:merge> "<<" : [ *CENTER, *BIG ]
-  label: center/big
-
-inlineMap:
-  # Inlined map 
-  << : {"x": 1, "y": 2, "r": 10}
-  label: center/big
-
-inlineSequenceMap:
-  # Inlined map in sequence
-  << : [ *CENTER, {"r": 10} ]
-  label: center/big
-`
-
-func (s *S) TestMerge(c *C) {
-	var want = map[interface{}]interface{}{
-		"x":     1,
-		"y":     2,
-		"r":     10,
-		"label": "center/big",
-	}
-
-	var m map[interface{}]interface{}
-	err := yaml.Unmarshal([]byte(mergeTests), &m)
-	c.Assert(err, IsNil)
-	for name, test := range m {
-		if name == "anchors" {
-			continue
-		}
-		c.Assert(test, DeepEquals, want, Commentf("test %q failed", name))
-	}
-}
-
-func (s *S) TestMergeStruct(c *C) {
-	type Data struct {
-		X, Y, R int
-		Label   string
-	}
-	want := Data{1, 2, 10, "center/big"}
-
-	var m map[string]Data
-	err := yaml.Unmarshal([]byte(mergeTests), &m)
-	c.Assert(err, IsNil)
-	for name, test := range m {
-		if name == "anchors" {
-			continue
-		}
-		c.Assert(test, Equals, want, Commentf("test %q failed", name))
-	}
-}
-
-var unmarshalNullTests = []func() interface{}{
-	func() interface{} { var v interface{}; v = "v"; return &v },
-	func() interface{} { var s = "s"; return &s },
-	func() interface{} { var s = "s"; sptr := &s; return &sptr },
-	func() interface{} { var i = 1; return &i },
-	func() interface{} { var i = 1; iptr := &i; return &iptr },
-	func() interface{} { m := map[string]int{"s": 1}; return &m },
-	func() interface{} { m := map[string]int{"s": 1}; return m },
-}
-
-func (s *S) TestUnmarshalNull(c *C) {
-	for _, test := range unmarshalNullTests {
-		item := test()
-		zero := reflect.Zero(reflect.TypeOf(item).Elem()).Interface()
-		err := yaml.Unmarshal([]byte("null"), item)
-		c.Assert(err, IsNil)
-		if reflect.TypeOf(item).Kind() == reflect.Map {
-			c.Assert(reflect.ValueOf(item).Interface(), DeepEquals, reflect.MakeMap(reflect.TypeOf(item)).Interface())
-		} else {
-			c.Assert(reflect.ValueOf(item).Elem().Interface(), DeepEquals, zero)
-		}
-	}
-}
-
-func (s *S) TestUnmarshalSliceOnPreset(c *C) {
-	// Issue #48.
-	v := struct{ A []int }{[]int{1}}
-	yaml.Unmarshal([]byte("a: [2]"), &v)
-	c.Assert(v.A, DeepEquals, []int{2})
-}
-
-var unmarshalStrictTests = []struct {
-	data  string
-	value interface{}
-	error string
-}{{
-	data:  "a: 1\nc: 2\n",
-	value: struct{ A, B int }{A: 1},
-	error: `yaml: unmarshal errors:\n  line 2: field c not found in type struct { A int; B int }`,
-}, {
-	data:  "a: 1\nb: 2\na: 3\n",
-	value: struct{ A, B int }{A: 3, B: 2},
-	error: `yaml: unmarshal errors:\n  line 3: field a already set in type struct { A int; B int }`,
-}, {
-	data: "c: 3\na: 1\nb: 2\nc: 4\n",
-	value: struct {
-		A       int
-		inlineB `yaml:",inline"`
-	}{
-		A: 1,
-		inlineB: inlineB{
-			B: 2,
-			inlineC: inlineC{
-				C: 4,
-			},
-		},
-	},
-	error: `yaml: unmarshal errors:\n  line 4: field c already set in type struct { A int; yaml_test.inlineB "yaml:\\",inline\\"" }`,
-}, {
-	data: "c: 0\na: 1\nb: 2\nc: 1\n",
-	value: struct {
-		A       int
-		inlineB `yaml:",inline"`
-	}{
-		A: 1,
-		inlineB: inlineB{
-			B: 2,
-			inlineC: inlineC{
-				C: 1,
-			},
-		},
-	},
-	error: `yaml: unmarshal errors:\n  line 4: field c already set in type struct { A int; yaml_test.inlineB "yaml:\\",inline\\"" }`,
-}, {
-	data: "c: 1\na: 1\nb: 2\nc: 3\n",
-	value: struct {
-		A int
-		M map[string]interface{} `yaml:",inline"`
-	}{
-		A: 1,
-		M: map[string]interface{}{
-			"b": 2,
-			"c": 3,
-		},
-	},
-	error: `yaml: unmarshal errors:\n  line 4: key "c" already set in map`,
-}, {
-	data: "a: 1\n9: 2\nnull: 3\n9: 4",
-	value: map[interface{}]interface{}{
-		"a": 1,
-		nil: 3,
-		9:   4,
-	},
-	error: `yaml: unmarshal errors:\n  line 4: key 9 already set in map`,
-}}
-
-func (s *S) TestUnmarshalStrict(c *C) {
-	for i, item := range unmarshalStrictTests {
-		c.Logf("test %d: %q", i, item.data)
-		// First test that normal Unmarshal unmarshals to the expected value.
-		t := reflect.ValueOf(item.value).Type()
-		value := reflect.New(t)
-		err := yaml.Unmarshal([]byte(item.data), value.Interface())
-		c.Assert(err, Equals, nil)
-		c.Assert(value.Elem().Interface(), DeepEquals, item.value)
-
-		// Then test that UnmarshalStrict fails on the same thing.
-		t = reflect.ValueOf(item.value).Type()
-		value = reflect.New(t)
-		err = yaml.UnmarshalStrict([]byte(item.data), value.Interface())
-		c.Assert(err, ErrorMatches, item.error)
-	}
-}
-
-type textUnmarshaler struct {
-	S string
-}
-
-func (t *textUnmarshaler) UnmarshalText(s []byte) error {
-	t.S = string(s)
-	return nil
-}
-
-func (s *S) TestFuzzCrashers(c *C) {
+func TestFuzzCrashers(t *testing.T) {
 	cases := []string{
 		// runtime error: index out of range
 		"\"\\0\\\r\n",
@@ -1291,8 +850,7 @@
 		"? \ufeff: \ufeff\n",
 	}
 	for _, data := range cases {
-		var v interface{}
-		_ = yaml.Unmarshal([]byte(data), &v)
+		_, _ = callUnmarshal(t, data)
 	}
 }
 
diff --git a/internal/third_party/yaml/emitterc.go b/internal/third_party/yaml/emitterc.go
deleted file mode 100644
index a1c2cc5..0000000
--- a/internal/third_party/yaml/emitterc.go
+++ /dev/null
@@ -1,1685 +0,0 @@
-package yaml
-
-import (
-	"bytes"
-	"fmt"
-)
-
-// Flush the buffer if needed.
-func flush(emitter *yaml_emitter_t) bool {
-	if emitter.buffer_pos+5 >= len(emitter.buffer) {
-		return yaml_emitter_flush(emitter)
-	}
-	return true
-}
-
-// Put a character to the output buffer.
-func put(emitter *yaml_emitter_t, value byte) bool {
-	if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
-		return false
-	}
-	emitter.buffer[emitter.buffer_pos] = value
-	emitter.buffer_pos++
-	emitter.column++
-	return true
-}
-
-// Put a line break to the output buffer.
-func put_break(emitter *yaml_emitter_t) bool {
-	if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
-		return false
-	}
-	switch emitter.line_break {
-	case yaml_CR_BREAK:
-		emitter.buffer[emitter.buffer_pos] = '\r'
-		emitter.buffer_pos += 1
-	case yaml_LN_BREAK:
-		emitter.buffer[emitter.buffer_pos] = '\n'
-		emitter.buffer_pos += 1
-	case yaml_CRLN_BREAK:
-		emitter.buffer[emitter.buffer_pos+0] = '\r'
-		emitter.buffer[emitter.buffer_pos+1] = '\n'
-		emitter.buffer_pos += 2
-	default:
-		panic("unknown line break setting")
-	}
-	emitter.column = 0
-	emitter.line++
-	return true
-}
-
-// Copy a character from a string into buffer.
-func write(emitter *yaml_emitter_t, s []byte, i *int) bool {
-	if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
-		return false
-	}
-	p := emitter.buffer_pos
-	w := width(s[*i])
-	switch w {
-	case 4:
-		emitter.buffer[p+3] = s[*i+3]
-		fallthrough
-	case 3:
-		emitter.buffer[p+2] = s[*i+2]
-		fallthrough
-	case 2:
-		emitter.buffer[p+1] = s[*i+1]
-		fallthrough
-	case 1:
-		emitter.buffer[p+0] = s[*i+0]
-	default:
-		panic("unknown character width")
-	}
-	emitter.column++
-	emitter.buffer_pos += w
-	*i += w
-	return true
-}
-
-// Write a whole string into buffer.
-func write_all(emitter *yaml_emitter_t, s []byte) bool {
-	for i := 0; i < len(s); {
-		if !write(emitter, s, &i) {
-			return false
-		}
-	}
-	return true
-}
-
-// Copy a line break character from a string into buffer.
-func write_break(emitter *yaml_emitter_t, s []byte, i *int) bool {
-	if s[*i] == '\n' {
-		if !put_break(emitter) {
-			return false
-		}
-		*i++
-	} else {
-		if !write(emitter, s, i) {
-			return false
-		}
-		emitter.column = 0
-		emitter.line++
-	}
-	return true
-}
-
-// Set an emitter error and return false.
-func yaml_emitter_set_emitter_error(emitter *yaml_emitter_t, problem string) bool {
-	emitter.error = yaml_EMITTER_ERROR
-	emitter.problem = problem
-	return false
-}
-
-// Emit an event.
-func yaml_emitter_emit(emitter *yaml_emitter_t, event *yaml_event_t) bool {
-	emitter.events = append(emitter.events, *event)
-	for !yaml_emitter_need_more_events(emitter) {
-		event := &emitter.events[emitter.events_head]
-		if !yaml_emitter_analyze_event(emitter, event) {
-			return false
-		}
-		if !yaml_emitter_state_machine(emitter, event) {
-			return false
-		}
-		yaml_event_delete(event)
-		emitter.events_head++
-	}
-	return true
-}
-
-// Check if we need to accumulate more events before emitting.
-//
-// We accumulate extra
-//  - 1 event for DOCUMENT-START
-//  - 2 events for SEQUENCE-START
-//  - 3 events for MAPPING-START
-//
-func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool {
-	if emitter.events_head == len(emitter.events) {
-		return true
-	}
-	var accumulate int
-	switch emitter.events[emitter.events_head].typ {
-	case yaml_DOCUMENT_START_EVENT:
-		accumulate = 1
-		break
-	case yaml_SEQUENCE_START_EVENT:
-		accumulate = 2
-		break
-	case yaml_MAPPING_START_EVENT:
-		accumulate = 3
-		break
-	default:
-		return false
-	}
-	if len(emitter.events)-emitter.events_head > accumulate {
-		return false
-	}
-	var level int
-	for i := emitter.events_head; i < len(emitter.events); i++ {
-		switch emitter.events[i].typ {
-		case yaml_STREAM_START_EVENT, yaml_DOCUMENT_START_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT:
-			level++
-		case yaml_STREAM_END_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_END_EVENT, yaml_MAPPING_END_EVENT:
-			level--
-		}
-		if level == 0 {
-			return false
-		}
-	}
-	return true
-}
-
-// Append a directive to the directives stack.
-func yaml_emitter_append_tag_directive(emitter *yaml_emitter_t, value *yaml_tag_directive_t, allow_duplicates bool) bool {
-	for i := 0; i < len(emitter.tag_directives); i++ {
-		if bytes.Equal(value.handle, emitter.tag_directives[i].handle) {
-			if allow_duplicates {
-				return true
-			}
-			return yaml_emitter_set_emitter_error(emitter, "duplicate %TAG directive")
-		}
-	}
-
-	// [Go] Do we actually need to copy this given garbage collection
-	// and the lack of deallocating destructors?
-	tag_copy := yaml_tag_directive_t{
-		handle: make([]byte, len(value.handle)),
-		prefix: make([]byte, len(value.prefix)),
-	}
-	copy(tag_copy.handle, value.handle)
-	copy(tag_copy.prefix, value.prefix)
-	emitter.tag_directives = append(emitter.tag_directives, tag_copy)
-	return true
-}
-
-// Increase the indentation level.
-func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool) bool {
-	emitter.indents = append(emitter.indents, emitter.indent)
-	if emitter.indent < 0 {
-		if flow {
-			emitter.indent = emitter.best_indent
-		} else {
-			emitter.indent = 0
-		}
-	} else if !indentless {
-		emitter.indent += emitter.best_indent
-	}
-	return true
-}
-
-// State dispatcher.
-func yaml_emitter_state_machine(emitter *yaml_emitter_t, event *yaml_event_t) bool {
-	switch emitter.state {
-	default:
-	case yaml_EMIT_STREAM_START_STATE:
-		return yaml_emitter_emit_stream_start(emitter, event)
-
-	case yaml_EMIT_FIRST_DOCUMENT_START_STATE:
-		return yaml_emitter_emit_document_start(emitter, event, true)
-
-	case yaml_EMIT_DOCUMENT_START_STATE:
-		return yaml_emitter_emit_document_start(emitter, event, false)
-
-	case yaml_EMIT_DOCUMENT_CONTENT_STATE:
-		return yaml_emitter_emit_document_content(emitter, event)
-
-	case yaml_EMIT_DOCUMENT_END_STATE:
-		return yaml_emitter_emit_document_end(emitter, event)
-
-	case yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE:
-		return yaml_emitter_emit_flow_sequence_item(emitter, event, true)
-
-	case yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE:
-		return yaml_emitter_emit_flow_sequence_item(emitter, event, false)
-
-	case yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE:
-		return yaml_emitter_emit_flow_mapping_key(emitter, event, true)
-
-	case yaml_EMIT_FLOW_MAPPING_KEY_STATE:
-		return yaml_emitter_emit_flow_mapping_key(emitter, event, false)
-
-	case yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE:
-		return yaml_emitter_emit_flow_mapping_value(emitter, event, true)
-
-	case yaml_EMIT_FLOW_MAPPING_VALUE_STATE:
-		return yaml_emitter_emit_flow_mapping_value(emitter, event, false)
-
-	case yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE:
-		return yaml_emitter_emit_block_sequence_item(emitter, event, true)
-
-	case yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE:
-		return yaml_emitter_emit_block_sequence_item(emitter, event, false)
-
-	case yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE:
-		return yaml_emitter_emit_block_mapping_key(emitter, event, true)
-
-	case yaml_EMIT_BLOCK_MAPPING_KEY_STATE:
-		return yaml_emitter_emit_block_mapping_key(emitter, event, false)
-
-	case yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE:
-		return yaml_emitter_emit_block_mapping_value(emitter, event, true)
-
-	case yaml_EMIT_BLOCK_MAPPING_VALUE_STATE:
-		return yaml_emitter_emit_block_mapping_value(emitter, event, false)
-
-	case yaml_EMIT_END_STATE:
-		return yaml_emitter_set_emitter_error(emitter, "expected nothing after STREAM-END")
-	}
-	panic("invalid emitter state")
-}
-
-// Expect STREAM-START.
-func yaml_emitter_emit_stream_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
-	if event.typ != yaml_STREAM_START_EVENT {
-		return yaml_emitter_set_emitter_error(emitter, "expected STREAM-START")
-	}
-	if emitter.encoding == yaml_ANY_ENCODING {
-		emitter.encoding = event.encoding
-		if emitter.encoding == yaml_ANY_ENCODING {
-			emitter.encoding = yaml_UTF8_ENCODING
-		}
-	}
-	if emitter.best_indent < 2 || emitter.best_indent > 9 {
-		emitter.best_indent = 2
-	}
-	if emitter.best_width >= 0 && emitter.best_width <= emitter.best_indent*2 {
-		emitter.best_width = 80
-	}
-	if emitter.best_width < 0 {
-		emitter.best_width = 1<<31 - 1
-	}
-	if emitter.line_break == yaml_ANY_BREAK {
-		emitter.line_break = yaml_LN_BREAK
-	}
-
-	emitter.indent = -1
-	emitter.line = 0
-	emitter.column = 0
-	emitter.whitespace = true
-	emitter.indention = true
-
-	if emitter.encoding != yaml_UTF8_ENCODING {
-		if !yaml_emitter_write_bom(emitter) {
-			return false
-		}
-	}
-	emitter.state = yaml_EMIT_FIRST_DOCUMENT_START_STATE
-	return true
-}
-
-// Expect DOCUMENT-START or STREAM-END.
-func yaml_emitter_emit_document_start(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
-
-	if event.typ == yaml_DOCUMENT_START_EVENT {
-
-		if event.version_directive != nil {
-			if !yaml_emitter_analyze_version_directive(emitter, event.version_directive) {
-				return false
-			}
-		}
-
-		for i := 0; i < len(event.tag_directives); i++ {
-			tag_directive := &event.tag_directives[i]
-			if !yaml_emitter_analyze_tag_directive(emitter, tag_directive) {
-				return false
-			}
-			if !yaml_emitter_append_tag_directive(emitter, tag_directive, false) {
-				return false
-			}
-		}
-
-		for i := 0; i < len(default_tag_directives); i++ {
-			tag_directive := &default_tag_directives[i]
-			if !yaml_emitter_append_tag_directive(emitter, tag_directive, true) {
-				return false
-			}
-		}
-
-		implicit := event.implicit
-		if !first || emitter.canonical {
-			implicit = false
-		}
-
-		if emitter.open_ended && (event.version_directive != nil || len(event.tag_directives) > 0) {
-			if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
-				return false
-			}
-			if !yaml_emitter_write_indent(emitter) {
-				return false
-			}
-		}
-
-		if event.version_directive != nil {
-			implicit = false
-			if !yaml_emitter_write_indicator(emitter, []byte("%YAML"), true, false, false) {
-				return false
-			}
-			if !yaml_emitter_write_indicator(emitter, []byte("1.1"), true, false, false) {
-				return false
-			}
-			if !yaml_emitter_write_indent(emitter) {
-				return false
-			}
-		}
-
-		if len(event.tag_directives) > 0 {
-			implicit = false
-			for i := 0; i < len(event.tag_directives); i++ {
-				tag_directive := &event.tag_directives[i]
-				if !yaml_emitter_write_indicator(emitter, []byte("%TAG"), true, false, false) {
-					return false
-				}
-				if !yaml_emitter_write_tag_handle(emitter, tag_directive.handle) {
-					return false
-				}
-				if !yaml_emitter_write_tag_content(emitter, tag_directive.prefix, true) {
-					return false
-				}
-				if !yaml_emitter_write_indent(emitter) {
-					return false
-				}
-			}
-		}
-
-		if yaml_emitter_check_empty_document(emitter) {
-			implicit = false
-		}
-		if !implicit {
-			if !yaml_emitter_write_indent(emitter) {
-				return false
-			}
-			if !yaml_emitter_write_indicator(emitter, []byte("---"), true, false, false) {
-				return false
-			}
-			if emitter.canonical {
-				if !yaml_emitter_write_indent(emitter) {
-					return false
-				}
-			}
-		}
-
-		emitter.state = yaml_EMIT_DOCUMENT_CONTENT_STATE
-		return true
-	}
-
-	if event.typ == yaml_STREAM_END_EVENT {
-		if emitter.open_ended {
-			if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
-				return false
-			}
-			if !yaml_emitter_write_indent(emitter) {
-				return false
-			}
-		}
-		if !yaml_emitter_flush(emitter) {
-			return false
-		}
-		emitter.state = yaml_EMIT_END_STATE
-		return true
-	}
-
-	return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-START or STREAM-END")
-}
-
-// Expect the root node.
-func yaml_emitter_emit_document_content(emitter *yaml_emitter_t, event *yaml_event_t) bool {
-	emitter.states = append(emitter.states, yaml_EMIT_DOCUMENT_END_STATE)
-	return yaml_emitter_emit_node(emitter, event, true, false, false, false)
-}
-
-// Expect DOCUMENT-END.
-func yaml_emitter_emit_document_end(emitter *yaml_emitter_t, event *yaml_event_t) bool {
-	if event.typ != yaml_DOCUMENT_END_EVENT {
-		return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-END")
-	}
-	if !yaml_emitter_write_indent(emitter) {
-		return false
-	}
-	if !event.implicit {
-		// [Go] Allocate the slice elsewhere.
-		if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
-			return false
-		}
-		if !yaml_emitter_write_indent(emitter) {
-			return false
-		}
-	}
-	if !yaml_emitter_flush(emitter) {
-		return false
-	}
-	emitter.state = yaml_EMIT_DOCUMENT_START_STATE
-	emitter.tag_directives = emitter.tag_directives[:0]
-	return true
-}
-
-// Expect a flow item node.
-func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
-	if first {
-		if !yaml_emitter_write_indicator(emitter, []byte{'['}, true, true, false) {
-			return false
-		}
-		if !yaml_emitter_increase_indent(emitter, true, false) {
-			return false
-		}
-		emitter.flow_level++
-	}
-
-	if event.typ == yaml_SEQUENCE_END_EVENT {
-		emitter.flow_level--
-		emitter.indent = emitter.indents[len(emitter.indents)-1]
-		emitter.indents = emitter.indents[:len(emitter.indents)-1]
-		if emitter.canonical && !first {
-			if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
-				return false
-			}
-			if !yaml_emitter_write_indent(emitter) {
-				return false
-			}
-		}
-		if !yaml_emitter_write_indicator(emitter, []byte{']'}, false, false, false) {
-			return false
-		}
-		emitter.state = emitter.states[len(emitter.states)-1]
-		emitter.states = emitter.states[:len(emitter.states)-1]
-
-		return true
-	}
-
-	if !first {
-		if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
-			return false
-		}
-	}
-
-	if emitter.canonical || emitter.column > emitter.best_width {
-		if !yaml_emitter_write_indent(emitter) {
-			return false
-		}
-	}
-	emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE)
-	return yaml_emitter_emit_node(emitter, event, false, true, false, false)
-}
-
-// Expect a flow key node.
-func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
-	if first {
-		if !yaml_emitter_write_indicator(emitter, []byte{'{'}, true, true, false) {
-			return false
-		}
-		if !yaml_emitter_increase_indent(emitter, true, false) {
-			return false
-		}
-		emitter.flow_level++
-	}
-
-	if event.typ == yaml_MAPPING_END_EVENT {
-		emitter.flow_level--
-		emitter.indent = emitter.indents[len(emitter.indents)-1]
-		emitter.indents = emitter.indents[:len(emitter.indents)-1]
-		if emitter.canonical && !first {
-			if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
-				return false
-			}
-			if !yaml_emitter_write_indent(emitter) {
-				return false
-			}
-		}
-		if !yaml_emitter_write_indicator(emitter, []byte{'}'}, false, false, false) {
-			return false
-		}
-		emitter.state = emitter.states[len(emitter.states)-1]
-		emitter.states = emitter.states[:len(emitter.states)-1]
-		return true
-	}
-
-	if !first {
-		if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
-			return false
-		}
-	}
-	if emitter.canonical || emitter.column > emitter.best_width {
-		if !yaml_emitter_write_indent(emitter) {
-			return false
-		}
-	}
-
-	if !emitter.canonical && yaml_emitter_check_simple_key(emitter) {
-		emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE)
-		return yaml_emitter_emit_node(emitter, event, false, false, true, true)
-	}
-	if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, false) {
-		return false
-	}
-	emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_VALUE_STATE)
-	return yaml_emitter_emit_node(emitter, event, false, false, true, false)
-}
-
-// Expect a flow value node.
-func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool {
-	if simple {
-		if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) {
-			return false
-		}
-	} else {
-		if emitter.canonical || emitter.column > emitter.best_width {
-			if !yaml_emitter_write_indent(emitter) {
-				return false
-			}
-		}
-		if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, false) {
-			return false
-		}
-	}
-	emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_KEY_STATE)
-	return yaml_emitter_emit_node(emitter, event, false, false, true, false)
-}
-
-// Expect a block item node.
-func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
-	if first {
-		if !yaml_emitter_increase_indent(emitter, false, emitter.mapping_context && !emitter.indention) {
-			return false
-		}
-	}
-	if event.typ == yaml_SEQUENCE_END_EVENT {
-		emitter.indent = emitter.indents[len(emitter.indents)-1]
-		emitter.indents = emitter.indents[:len(emitter.indents)-1]
-		emitter.state = emitter.states[len(emitter.states)-1]
-		emitter.states = emitter.states[:len(emitter.states)-1]
-		return true
-	}
-	if !yaml_emitter_write_indent(emitter) {
-		return false
-	}
-	if !yaml_emitter_write_indicator(emitter, []byte{'-'}, true, false, true) {
-		return false
-	}
-	emitter.states = append(emitter.states, yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE)
-	return yaml_emitter_emit_node(emitter, event, false, true, false, false)
-}
-
-// Expect a block key node.
-func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
-	if first {
-		if !yaml_emitter_increase_indent(emitter, false, false) {
-			return false
-		}
-	}
-	if event.typ == yaml_MAPPING_END_EVENT {
-		emitter.indent = emitter.indents[len(emitter.indents)-1]
-		emitter.indents = emitter.indents[:len(emitter.indents)-1]
-		emitter.state = emitter.states[len(emitter.states)-1]
-		emitter.states = emitter.states[:len(emitter.states)-1]
-		return true
-	}
-	if !yaml_emitter_write_indent(emitter) {
-		return false
-	}
-	if yaml_emitter_check_simple_key(emitter) {
-		emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE)
-		return yaml_emitter_emit_node(emitter, event, false, false, true, true)
-	}
-	if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, true) {
-		return false
-	}
-	emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_VALUE_STATE)
-	return yaml_emitter_emit_node(emitter, event, false, false, true, false)
-}
-
-// Expect a block value node.
-func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool {
-	if simple {
-		if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) {
-			return false
-		}
-	} else {
-		if !yaml_emitter_write_indent(emitter) {
-			return false
-		}
-		if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, true) {
-			return false
-		}
-	}
-	emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_KEY_STATE)
-	return yaml_emitter_emit_node(emitter, event, false, false, true, false)
-}
-
-// Expect a node.
-func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t,
-	root bool, sequence bool, mapping bool, simple_key bool) bool {
-
-	emitter.root_context = root
-	emitter.sequence_context = sequence
-	emitter.mapping_context = mapping
-	emitter.simple_key_context = simple_key
-
-	switch event.typ {
-	case yaml_ALIAS_EVENT:
-		return yaml_emitter_emit_alias(emitter, event)
-	case yaml_SCALAR_EVENT:
-		return yaml_emitter_emit_scalar(emitter, event)
-	case yaml_SEQUENCE_START_EVENT:
-		return yaml_emitter_emit_sequence_start(emitter, event)
-	case yaml_MAPPING_START_EVENT:
-		return yaml_emitter_emit_mapping_start(emitter, event)
-	default:
-		return yaml_emitter_set_emitter_error(emitter,
-			fmt.Sprintf("expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, but got %v", event.typ))
-	}
-}
-
-// Expect ALIAS.
-func yaml_emitter_emit_alias(emitter *yaml_emitter_t, event *yaml_event_t) bool {
-	if !yaml_emitter_process_anchor(emitter) {
-		return false
-	}
-	emitter.state = emitter.states[len(emitter.states)-1]
-	emitter.states = emitter.states[:len(emitter.states)-1]
-	return true
-}
-
-// Expect SCALAR.
-func yaml_emitter_emit_scalar(emitter *yaml_emitter_t, event *yaml_event_t) bool {
-	if !yaml_emitter_select_scalar_style(emitter, event) {
-		return false
-	}
-	if !yaml_emitter_process_anchor(emitter) {
-		return false
-	}
-	if !yaml_emitter_process_tag(emitter) {
-		return false
-	}
-	if !yaml_emitter_increase_indent(emitter, true, false) {
-		return false
-	}
-	if !yaml_emitter_process_scalar(emitter) {
-		return false
-	}
-	emitter.indent = emitter.indents[len(emitter.indents)-1]
-	emitter.indents = emitter.indents[:len(emitter.indents)-1]
-	emitter.state = emitter.states[len(emitter.states)-1]
-	emitter.states = emitter.states[:len(emitter.states)-1]
-	return true
-}
-
-// Expect SEQUENCE-START.
-func yaml_emitter_emit_sequence_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
-	if !yaml_emitter_process_anchor(emitter) {
-		return false
-	}
-	if !yaml_emitter_process_tag(emitter) {
-		return false
-	}
-	if emitter.flow_level > 0 || emitter.canonical || event.sequence_style() == yaml_FLOW_SEQUENCE_STYLE ||
-		yaml_emitter_check_empty_sequence(emitter) {
-		emitter.state = yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE
-	} else {
-		emitter.state = yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE
-	}
-	return true
-}
-
-// Expect MAPPING-START.
-func yaml_emitter_emit_mapping_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
-	if !yaml_emitter_process_anchor(emitter) {
-		return false
-	}
-	if !yaml_emitter_process_tag(emitter) {
-		return false
-	}
-	if emitter.flow_level > 0 || emitter.canonical || event.mapping_style() == yaml_FLOW_MAPPING_STYLE ||
-		yaml_emitter_check_empty_mapping(emitter) {
-		emitter.state = yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE
-	} else {
-		emitter.state = yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE
-	}
-	return true
-}
-
-// Check if the document content is an empty scalar.
-func yaml_emitter_check_empty_document(emitter *yaml_emitter_t) bool {
-	return false // [Go] Huh?
-}
-
-// Check if the next events represent an empty sequence.
-func yaml_emitter_check_empty_sequence(emitter *yaml_emitter_t) bool {
-	if len(emitter.events)-emitter.events_head < 2 {
-		return false
-	}
-	return emitter.events[emitter.events_head].typ == yaml_SEQUENCE_START_EVENT &&
-		emitter.events[emitter.events_head+1].typ == yaml_SEQUENCE_END_EVENT
-}
-
-// Check if the next events represent an empty mapping.
-func yaml_emitter_check_empty_mapping(emitter *yaml_emitter_t) bool {
-	if len(emitter.events)-emitter.events_head < 2 {
-		return false
-	}
-	return emitter.events[emitter.events_head].typ == yaml_MAPPING_START_EVENT &&
-		emitter.events[emitter.events_head+1].typ == yaml_MAPPING_END_EVENT
-}
-
-// Check if the next node can be expressed as a simple key.
-func yaml_emitter_check_simple_key(emitter *yaml_emitter_t) bool {
-	length := 0
-	switch emitter.events[emitter.events_head].typ {
-	case yaml_ALIAS_EVENT:
-		length += len(emitter.anchor_data.anchor)
-	case yaml_SCALAR_EVENT:
-		if emitter.scalar_data.multiline {
-			return false
-		}
-		length += len(emitter.anchor_data.anchor) +
-			len(emitter.tag_data.handle) +
-			len(emitter.tag_data.suffix) +
-			len(emitter.scalar_data.value)
-	case yaml_SEQUENCE_START_EVENT:
-		if !yaml_emitter_check_empty_sequence(emitter) {
-			return false
-		}
-		length += len(emitter.anchor_data.anchor) +
-			len(emitter.tag_data.handle) +
-			len(emitter.tag_data.suffix)
-	case yaml_MAPPING_START_EVENT:
-		if !yaml_emitter_check_empty_mapping(emitter) {
-			return false
-		}
-		length += len(emitter.anchor_data.anchor) +
-			len(emitter.tag_data.handle) +
-			len(emitter.tag_data.suffix)
-	default:
-		return false
-	}
-	return length <= 128
-}
-
-// Determine an acceptable scalar style.
-func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t, event *yaml_event_t) bool {
-
-	no_tag := len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0
-	if no_tag && !event.implicit && !event.quoted_implicit {
-		return yaml_emitter_set_emitter_error(emitter, "neither tag nor implicit flags are specified")
-	}
-
-	style := event.scalar_style()
-	if style == yaml_ANY_SCALAR_STYLE {
-		style = yaml_PLAIN_SCALAR_STYLE
-	}
-	if emitter.canonical {
-		style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
-	}
-	if emitter.simple_key_context && emitter.scalar_data.multiline {
-		style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
-	}
-
-	if style == yaml_PLAIN_SCALAR_STYLE {
-		if emitter.flow_level > 0 && !emitter.scalar_data.flow_plain_allowed ||
-			emitter.flow_level == 0 && !emitter.scalar_data.block_plain_allowed {
-			style = yaml_SINGLE_QUOTED_SCALAR_STYLE
-		}
-		if len(emitter.scalar_data.value) == 0 && (emitter.flow_level > 0 || emitter.simple_key_context) {
-			style = yaml_SINGLE_QUOTED_SCALAR_STYLE
-		}
-		if no_tag && !event.implicit {
-			style = yaml_SINGLE_QUOTED_SCALAR_STYLE
-		}
-	}
-	if style == yaml_SINGLE_QUOTED_SCALAR_STYLE {
-		if !emitter.scalar_data.single_quoted_allowed {
-			style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
-		}
-	}
-	if style == yaml_LITERAL_SCALAR_STYLE || style == yaml_FOLDED_SCALAR_STYLE {
-		if !emitter.scalar_data.block_allowed || emitter.flow_level > 0 || emitter.simple_key_context {
-			style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
-		}
-	}
-
-	if no_tag && !event.quoted_implicit && style != yaml_PLAIN_SCALAR_STYLE {
-		emitter.tag_data.handle = []byte{'!'}
-	}
-	emitter.scalar_data.style = style
-	return true
-}
-
-// Write an anchor.
-func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool {
-	if emitter.anchor_data.anchor == nil {
-		return true
-	}
-	c := []byte{'&'}
-	if emitter.anchor_data.alias {
-		c[0] = '*'
-	}
-	if !yaml_emitter_write_indicator(emitter, c, true, false, false) {
-		return false
-	}
-	return yaml_emitter_write_anchor(emitter, emitter.anchor_data.anchor)
-}
-
-// Write a tag.
-func yaml_emitter_process_tag(emitter *yaml_emitter_t) bool {
-	if len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 {
-		return true
-	}
-	if len(emitter.tag_data.handle) > 0 {
-		if !yaml_emitter_write_tag_handle(emitter, emitter.tag_data.handle) {
-			return false
-		}
-		if len(emitter.tag_data.suffix) > 0 {
-			if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) {
-				return false
-			}
-		}
-	} else {
-		// [Go] Allocate these slices elsewhere.
-		if !yaml_emitter_write_indicator(emitter, []byte("!<"), true, false, false) {
-			return false
-		}
-		if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) {
-			return false
-		}
-		if !yaml_emitter_write_indicator(emitter, []byte{'>'}, false, false, false) {
-			return false
-		}
-	}
-	return true
-}
-
-// Write a scalar.
-func yaml_emitter_process_scalar(emitter *yaml_emitter_t) bool {
-	switch emitter.scalar_data.style {
-	case yaml_PLAIN_SCALAR_STYLE:
-		return yaml_emitter_write_plain_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
-
-	case yaml_SINGLE_QUOTED_SCALAR_STYLE:
-		return yaml_emitter_write_single_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
-
-	case yaml_DOUBLE_QUOTED_SCALAR_STYLE:
-		return yaml_emitter_write_double_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
-
-	case yaml_LITERAL_SCALAR_STYLE:
-		return yaml_emitter_write_literal_scalar(emitter, emitter.scalar_data.value)
-
-	case yaml_FOLDED_SCALAR_STYLE:
-		return yaml_emitter_write_folded_scalar(emitter, emitter.scalar_data.value)
-	}
-	panic("unknown scalar style")
-}
-
-// Check if a %YAML directive is valid.
-func yaml_emitter_analyze_version_directive(emitter *yaml_emitter_t, version_directive *yaml_version_directive_t) bool {
-	if version_directive.major != 1 || version_directive.minor != 1 {
-		return yaml_emitter_set_emitter_error(emitter, "incompatible %YAML directive")
-	}
-	return true
-}
-
-// Check if a %TAG directive is valid.
-func yaml_emitter_analyze_tag_directive(emitter *yaml_emitter_t, tag_directive *yaml_tag_directive_t) bool {
-	handle := tag_directive.handle
-	prefix := tag_directive.prefix
-	if len(handle) == 0 {
-		return yaml_emitter_set_emitter_error(emitter, "tag handle must not be empty")
-	}
-	if handle[0] != '!' {
-		return yaml_emitter_set_emitter_error(emitter, "tag handle must start with '!'")
-	}
-	if handle[len(handle)-1] != '!' {
-		return yaml_emitter_set_emitter_error(emitter, "tag handle must end with '!'")
-	}
-	for i := 1; i < len(handle)-1; i += width(handle[i]) {
-		if !is_alpha(handle, i) {
-			return yaml_emitter_set_emitter_error(emitter, "tag handle must contain alphanumerical characters only")
-		}
-	}
-	if len(prefix) == 0 {
-		return yaml_emitter_set_emitter_error(emitter, "tag prefix must not be empty")
-	}
-	return true
-}
-
-// Check if an anchor is valid.
-func yaml_emitter_analyze_anchor(emitter *yaml_emitter_t, anchor []byte, alias bool) bool {
-	if len(anchor) == 0 {
-		problem := "anchor value must not be empty"
-		if alias {
-			problem = "alias value must not be empty"
-		}
-		return yaml_emitter_set_emitter_error(emitter, problem)
-	}
-	for i := 0; i < len(anchor); i += width(anchor[i]) {
-		if !is_alpha(anchor, i) {
-			problem := "anchor value must contain alphanumerical characters only"
-			if alias {
-				problem = "alias value must contain alphanumerical characters only"
-			}
-			return yaml_emitter_set_emitter_error(emitter, problem)
-		}
-	}
-	emitter.anchor_data.anchor = anchor
-	emitter.anchor_data.alias = alias
-	return true
-}
-
-// Check if a tag is valid.
-func yaml_emitter_analyze_tag(emitter *yaml_emitter_t, tag []byte) bool {
-	if len(tag) == 0 {
-		return yaml_emitter_set_emitter_error(emitter, "tag value must not be empty")
-	}
-	for i := 0; i < len(emitter.tag_directives); i++ {
-		tag_directive := &emitter.tag_directives[i]
-		if bytes.HasPrefix(tag, tag_directive.prefix) {
-			emitter.tag_data.handle = tag_directive.handle
-			emitter.tag_data.suffix = tag[len(tag_directive.prefix):]
-			return true
-		}
-	}
-	emitter.tag_data.suffix = tag
-	return true
-}
-
-// Check if a scalar is valid.
-func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool {
-	var (
-		block_indicators   = false
-		flow_indicators    = false
-		line_breaks        = false
-		special_characters = false
-
-		leading_space  = false
-		leading_break  = false
-		trailing_space = false
-		trailing_break = false
-		break_space    = false
-		space_break    = false
-
-		preceded_by_whitespace = false
-		followed_by_whitespace = false
-		previous_space         = false
-		previous_break         = false
-	)
-
-	emitter.scalar_data.value = value
-
-	if len(value) == 0 {
-		emitter.scalar_data.multiline = false
-		emitter.scalar_data.flow_plain_allowed = false
-		emitter.scalar_data.block_plain_allowed = true
-		emitter.scalar_data.single_quoted_allowed = true
-		emitter.scalar_data.block_allowed = false
-		return true
-	}
-
-	if len(value) >= 3 && ((value[0] == '-' && value[1] == '-' && value[2] == '-') || (value[0] == '.' && value[1] == '.' && value[2] == '.')) {
-		block_indicators = true
-		flow_indicators = true
-	}
-
-	preceded_by_whitespace = true
-	for i, w := 0, 0; i < len(value); i += w {
-		w = width(value[i])
-		followed_by_whitespace = i+w >= len(value) || is_blank(value, i+w)
-
-		if i == 0 {
-			switch value[i] {
-			case '#', ',', '[', ']', '{', '}', '&', '*', '!', '|', '>', '\'', '"', '%', '@', '`':
-				flow_indicators = true
-				block_indicators = true
-			case '?', ':':
-				flow_indicators = true
-				if followed_by_whitespace {
-					block_indicators = true
-				}
-			case '-':
-				if followed_by_whitespace {
-					flow_indicators = true
-					block_indicators = true
-				}
-			}
-		} else {
-			switch value[i] {
-			case ',', '?', '[', ']', '{', '}':
-				flow_indicators = true
-			case ':':
-				flow_indicators = true
-				if followed_by_whitespace {
-					block_indicators = true
-				}
-			case '#':
-				if preceded_by_whitespace {
-					flow_indicators = true
-					block_indicators = true
-				}
-			}
-		}
-
-		if !is_printable(value, i) || !is_ascii(value, i) && !emitter.unicode {
-			special_characters = true
-		}
-		if is_space(value, i) {
-			if i == 0 {
-				leading_space = true
-			}
-			if i+width(value[i]) == len(value) {
-				trailing_space = true
-			}
-			if previous_break {
-				break_space = true
-			}
-			previous_space = true
-			previous_break = false
-		} else if is_break(value, i) {
-			line_breaks = true
-			if i == 0 {
-				leading_break = true
-			}
-			if i+width(value[i]) == len(value) {
-				trailing_break = true
-			}
-			if previous_space {
-				space_break = true
-			}
-			previous_space = false
-			previous_break = true
-		} else {
-			previous_space = false
-			previous_break = false
-		}
-
-		// [Go]: Why 'z'? Couldn't be the end of the string as that's the loop condition.
-		preceded_by_whitespace = is_blankz(value, i)
-	}
-
-	emitter.scalar_data.multiline = line_breaks
-	emitter.scalar_data.flow_plain_allowed = true
-	emitter.scalar_data.block_plain_allowed = true
-	emitter.scalar_data.single_quoted_allowed = true
-	emitter.scalar_data.block_allowed = true
-
-	if leading_space || leading_break || trailing_space || trailing_break {
-		emitter.scalar_data.flow_plain_allowed = false
-		emitter.scalar_data.block_plain_allowed = false
-	}
-	if trailing_space {
-		emitter.scalar_data.block_allowed = false
-	}
-	if break_space {
-		emitter.scalar_data.flow_plain_allowed = false
-		emitter.scalar_data.block_plain_allowed = false
-		emitter.scalar_data.single_quoted_allowed = false
-	}
-	if space_break || special_characters {
-		emitter.scalar_data.flow_plain_allowed = false
-		emitter.scalar_data.block_plain_allowed = false
-		emitter.scalar_data.single_quoted_allowed = false
-		emitter.scalar_data.block_allowed = false
-	}
-	if line_breaks {
-		emitter.scalar_data.flow_plain_allowed = false
-		emitter.scalar_data.block_plain_allowed = false
-	}
-	if flow_indicators {
-		emitter.scalar_data.flow_plain_allowed = false
-	}
-	if block_indicators {
-		emitter.scalar_data.block_plain_allowed = false
-	}
-	return true
-}
-
-// Check if the event data is valid.
-func yaml_emitter_analyze_event(emitter *yaml_emitter_t, event *yaml_event_t) bool {
-
-	emitter.anchor_data.anchor = nil
-	emitter.tag_data.handle = nil
-	emitter.tag_data.suffix = nil
-	emitter.scalar_data.value = nil
-
-	switch event.typ {
-	case yaml_ALIAS_EVENT:
-		if !yaml_emitter_analyze_anchor(emitter, event.anchor, true) {
-			return false
-		}
-
-	case yaml_SCALAR_EVENT:
-		if len(event.anchor) > 0 {
-			if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
-				return false
-			}
-		}
-		if len(event.tag) > 0 && (emitter.canonical || (!event.implicit && !event.quoted_implicit)) {
-			if !yaml_emitter_analyze_tag(emitter, event.tag) {
-				return false
-			}
-		}
-		if !yaml_emitter_analyze_scalar(emitter, event.value) {
-			return false
-		}
-
-	case yaml_SEQUENCE_START_EVENT:
-		if len(event.anchor) > 0 {
-			if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
-				return false
-			}
-		}
-		if len(event.tag) > 0 && (emitter.canonical || !event.implicit) {
-			if !yaml_emitter_analyze_tag(emitter, event.tag) {
-				return false
-			}
-		}
-
-	case yaml_MAPPING_START_EVENT:
-		if len(event.anchor) > 0 {
-			if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
-				return false
-			}
-		}
-		if len(event.tag) > 0 && (emitter.canonical || !event.implicit) {
-			if !yaml_emitter_analyze_tag(emitter, event.tag) {
-				return false
-			}
-		}
-	}
-	return true
-}
-
-// Write the BOM character.
-func yaml_emitter_write_bom(emitter *yaml_emitter_t) bool {
-	if !flush(emitter) {
-		return false
-	}
-	pos := emitter.buffer_pos
-	emitter.buffer[pos+0] = '\xEF'
-	emitter.buffer[pos+1] = '\xBB'
-	emitter.buffer[pos+2] = '\xBF'
-	emitter.buffer_pos += 3
-	return true
-}
-
-func yaml_emitter_write_indent(emitter *yaml_emitter_t) bool {
-	indent := emitter.indent
-	if indent < 0 {
-		indent = 0
-	}
-	if !emitter.indention || emitter.column > indent || (emitter.column == indent && !emitter.whitespace) {
-		if !put_break(emitter) {
-			return false
-		}
-	}
-	for emitter.column < indent {
-		if !put(emitter, ' ') {
-			return false
-		}
-	}
-	emitter.whitespace = true
-	emitter.indention = true
-	return true
-}
-
-func yaml_emitter_write_indicator(emitter *yaml_emitter_t, indicator []byte, need_whitespace, is_whitespace, is_indention bool) bool {
-	if need_whitespace && !emitter.whitespace {
-		if !put(emitter, ' ') {
-			return false
-		}
-	}
-	if !write_all(emitter, indicator) {
-		return false
-	}
-	emitter.whitespace = is_whitespace
-	emitter.indention = (emitter.indention && is_indention)
-	emitter.open_ended = false
-	return true
-}
-
-func yaml_emitter_write_anchor(emitter *yaml_emitter_t, value []byte) bool {
-	if !write_all(emitter, value) {
-		return false
-	}
-	emitter.whitespace = false
-	emitter.indention = false
-	return true
-}
-
-func yaml_emitter_write_tag_handle(emitter *yaml_emitter_t, value []byte) bool {
-	if !emitter.whitespace {
-		if !put(emitter, ' ') {
-			return false
-		}
-	}
-	if !write_all(emitter, value) {
-		return false
-	}
-	emitter.whitespace = false
-	emitter.indention = false
-	return true
-}
-
-func yaml_emitter_write_tag_content(emitter *yaml_emitter_t, value []byte, need_whitespace bool) bool {
-	if need_whitespace && !emitter.whitespace {
-		if !put(emitter, ' ') {
-			return false
-		}
-	}
-	for i := 0; i < len(value); {
-		var must_write bool
-		switch value[i] {
-		case ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '_', '.', '~', '*', '\'', '(', ')', '[', ']':
-			must_write = true
-		default:
-			must_write = is_alpha(value, i)
-		}
-		if must_write {
-			if !write(emitter, value, &i) {
-				return false
-			}
-		} else {
-			w := width(value[i])
-			for k := 0; k < w; k++ {
-				octet := value[i]
-				i++
-				if !put(emitter, '%') {
-					return false
-				}
-
-				c := octet >> 4
-				if c < 10 {
-					c += '0'
-				} else {
-					c += 'A' - 10
-				}
-				if !put(emitter, c) {
-					return false
-				}
-
-				c = octet & 0x0f
-				if c < 10 {
-					c += '0'
-				} else {
-					c += 'A' - 10
-				}
-				if !put(emitter, c) {
-					return false
-				}
-			}
-		}
-	}
-	emitter.whitespace = false
-	emitter.indention = false
-	return true
-}
-
-func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
-	if !emitter.whitespace {
-		if !put(emitter, ' ') {
-			return false
-		}
-	}
-
-	spaces := false
-	breaks := false
-	for i := 0; i < len(value); {
-		if is_space(value, i) {
-			if allow_breaks && !spaces && emitter.column > emitter.best_width && !is_space(value, i+1) {
-				if !yaml_emitter_write_indent(emitter) {
-					return false
-				}
-				i += width(value[i])
-			} else {
-				if !write(emitter, value, &i) {
-					return false
-				}
-			}
-			spaces = true
-		} else if is_break(value, i) {
-			if !breaks && value[i] == '\n' {
-				if !put_break(emitter) {
-					return false
-				}
-			}
-			if !write_break(emitter, value, &i) {
-				return false
-			}
-			emitter.indention = true
-			breaks = true
-		} else {
-			if breaks {
-				if !yaml_emitter_write_indent(emitter) {
-					return false
-				}
-			}
-			if !write(emitter, value, &i) {
-				return false
-			}
-			emitter.indention = false
-			spaces = false
-			breaks = false
-		}
-	}
-
-	emitter.whitespace = false
-	emitter.indention = false
-	if emitter.root_context {
-		emitter.open_ended = true
-	}
-
-	return true
-}
-
-func yaml_emitter_write_single_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
-
-	if !yaml_emitter_write_indicator(emitter, []byte{'\''}, true, false, false) {
-		return false
-	}
-
-	spaces := false
-	breaks := false
-	for i := 0; i < len(value); {
-		if is_space(value, i) {
-			if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 && !is_space(value, i+1) {
-				if !yaml_emitter_write_indent(emitter) {
-					return false
-				}
-				i += width(value[i])
-			} else {
-				if !write(emitter, value, &i) {
-					return false
-				}
-			}
-			spaces = true
-		} else if is_break(value, i) {
-			if !breaks && value[i] == '\n' {
-				if !put_break(emitter) {
-					return false
-				}
-			}
-			if !write_break(emitter, value, &i) {
-				return false
-			}
-			emitter.indention = true
-			breaks = true
-		} else {
-			if breaks {
-				if !yaml_emitter_write_indent(emitter) {
-					return false
-				}
-			}
-			if value[i] == '\'' {
-				if !put(emitter, '\'') {
-					return false
-				}
-			}
-			if !write(emitter, value, &i) {
-				return false
-			}
-			emitter.indention = false
-			spaces = false
-			breaks = false
-		}
-	}
-	if !yaml_emitter_write_indicator(emitter, []byte{'\''}, false, false, false) {
-		return false
-	}
-	emitter.whitespace = false
-	emitter.indention = false
-	return true
-}
-
-func yaml_emitter_write_double_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
-	spaces := false
-	if !yaml_emitter_write_indicator(emitter, []byte{'"'}, true, false, false) {
-		return false
-	}
-
-	for i := 0; i < len(value); {
-		if !is_printable(value, i) || (!emitter.unicode && !is_ascii(value, i)) ||
-			is_bom(value, i) || is_break(value, i) ||
-			value[i] == '"' || value[i] == '\\' {
-
-			octet := value[i]
-
-			var w int
-			var v rune
-			switch {
-			case octet&0x80 == 0x00:
-				w, v = 1, rune(octet&0x7F)
-			case octet&0xE0 == 0xC0:
-				w, v = 2, rune(octet&0x1F)
-			case octet&0xF0 == 0xE0:
-				w, v = 3, rune(octet&0x0F)
-			case octet&0xF8 == 0xF0:
-				w, v = 4, rune(octet&0x07)
-			}
-			for k := 1; k < w; k++ {
-				octet = value[i+k]
-				v = (v << 6) + (rune(octet) & 0x3F)
-			}
-			i += w
-
-			if !put(emitter, '\\') {
-				return false
-			}
-
-			var ok bool
-			switch v {
-			case 0x00:
-				ok = put(emitter, '0')
-			case 0x07:
-				ok = put(emitter, 'a')
-			case 0x08:
-				ok = put(emitter, 'b')
-			case 0x09:
-				ok = put(emitter, 't')
-			case 0x0A:
-				ok = put(emitter, 'n')
-			case 0x0b:
-				ok = put(emitter, 'v')
-			case 0x0c:
-				ok = put(emitter, 'f')
-			case 0x0d:
-				ok = put(emitter, 'r')
-			case 0x1b:
-				ok = put(emitter, 'e')
-			case 0x22:
-				ok = put(emitter, '"')
-			case 0x5c:
-				ok = put(emitter, '\\')
-			case 0x85:
-				ok = put(emitter, 'N')
-			case 0xA0:
-				ok = put(emitter, '_')
-			case 0x2028:
-				ok = put(emitter, 'L')
-			case 0x2029:
-				ok = put(emitter, 'P')
-			default:
-				if v <= 0xFF {
-					ok = put(emitter, 'x')
-					w = 2
-				} else if v <= 0xFFFF {
-					ok = put(emitter, 'u')
-					w = 4
-				} else {
-					ok = put(emitter, 'U')
-					w = 8
-				}
-				for k := (w - 1) * 4; ok && k >= 0; k -= 4 {
-					digit := byte((v >> uint(k)) & 0x0F)
-					if digit < 10 {
-						ok = put(emitter, digit+'0')
-					} else {
-						ok = put(emitter, digit+'A'-10)
-					}
-				}
-			}
-			if !ok {
-				return false
-			}
-			spaces = false
-		} else if is_space(value, i) {
-			if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 {
-				if !yaml_emitter_write_indent(emitter) {
-					return false
-				}
-				if is_space(value, i+1) {
-					if !put(emitter, '\\') {
-						return false
-					}
-				}
-				i += width(value[i])
-			} else if !write(emitter, value, &i) {
-				return false
-			}
-			spaces = true
-		} else {
-			if !write(emitter, value, &i) {
-				return false
-			}
-			spaces = false
-		}
-	}
-	if !yaml_emitter_write_indicator(emitter, []byte{'"'}, false, false, false) {
-		return false
-	}
-	emitter.whitespace = false
-	emitter.indention = false
-	return true
-}
-
-func yaml_emitter_write_block_scalar_hints(emitter *yaml_emitter_t, value []byte) bool {
-	if is_space(value, 0) || is_break(value, 0) {
-		indent_hint := []byte{'0' + byte(emitter.best_indent)}
-		if !yaml_emitter_write_indicator(emitter, indent_hint, false, false, false) {
-			return false
-		}
-	}
-
-	emitter.open_ended = false
-
-	var chomp_hint [1]byte
-	if len(value) == 0 {
-		chomp_hint[0] = '-'
-	} else {
-		i := len(value) - 1
-		for value[i]&0xC0 == 0x80 {
-			i--
-		}
-		if !is_break(value, i) {
-			chomp_hint[0] = '-'
-		} else if i == 0 {
-			chomp_hint[0] = '+'
-			emitter.open_ended = true
-		} else {
-			i--
-			for value[i]&0xC0 == 0x80 {
-				i--
-			}
-			if is_break(value, i) {
-				chomp_hint[0] = '+'
-				emitter.open_ended = true
-			}
-		}
-	}
-	if chomp_hint[0] != 0 {
-		if !yaml_emitter_write_indicator(emitter, chomp_hint[:], false, false, false) {
-			return false
-		}
-	}
-	return true
-}
-
-func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []byte) bool {
-	if !yaml_emitter_write_indicator(emitter, []byte{'|'}, true, false, false) {
-		return false
-	}
-	if !yaml_emitter_write_block_scalar_hints(emitter, value) {
-		return false
-	}
-	if !put_break(emitter) {
-		return false
-	}
-	emitter.indention = true
-	emitter.whitespace = true
-	breaks := true
-	for i := 0; i < len(value); {
-		if is_break(value, i) {
-			if !write_break(emitter, value, &i) {
-				return false
-			}
-			emitter.indention = true
-			breaks = true
-		} else {
-			if breaks {
-				if !yaml_emitter_write_indent(emitter) {
-					return false
-				}
-			}
-			if !write(emitter, value, &i) {
-				return false
-			}
-			emitter.indention = false
-			breaks = false
-		}
-	}
-
-	return true
-}
-
-func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []byte) bool {
-	if !yaml_emitter_write_indicator(emitter, []byte{'>'}, true, false, false) {
-		return false
-	}
-	if !yaml_emitter_write_block_scalar_hints(emitter, value) {
-		return false
-	}
-
-	if !put_break(emitter) {
-		return false
-	}
-	emitter.indention = true
-	emitter.whitespace = true
-
-	breaks := true
-	leading_spaces := true
-	for i := 0; i < len(value); {
-		if is_break(value, i) {
-			if !breaks && !leading_spaces && value[i] == '\n' {
-				k := 0
-				for is_break(value, k) {
-					k += width(value[k])
-				}
-				if !is_blankz(value, k) {
-					if !put_break(emitter) {
-						return false
-					}
-				}
-			}
-			if !write_break(emitter, value, &i) {
-				return false
-			}
-			emitter.indention = true
-			breaks = true
-		} else {
-			if breaks {
-				if !yaml_emitter_write_indent(emitter) {
-					return false
-				}
-				leading_spaces = is_blank(value, i)
-			}
-			if !breaks && is_space(value, i) && !is_space(value, i+1) && emitter.column > emitter.best_width {
-				if !yaml_emitter_write_indent(emitter) {
-					return false
-				}
-				i += width(value[i])
-			} else {
-				if !write(emitter, value, &i) {
-					return false
-				}
-			}
-			emitter.indention = false
-			breaks = false
-		}
-	}
-	return true
-}
diff --git a/internal/third_party/yaml/encode.go b/internal/third_party/yaml/encode.go
deleted file mode 100644
index a14435e..0000000
--- a/internal/third_party/yaml/encode.go
+++ /dev/null
@@ -1,362 +0,0 @@
-package yaml
-
-import (
-	"encoding"
-	"fmt"
-	"io"
-	"reflect"
-	"regexp"
-	"sort"
-	"strconv"
-	"strings"
-	"time"
-	"unicode/utf8"
-)
-
-type encoder struct {
-	emitter yaml_emitter_t
-	event   yaml_event_t
-	out     []byte
-	flow    bool
-	// doneInit holds whether the initial stream_start_event has been
-	// emitted.
-	doneInit bool
-}
-
-func newEncoder() *encoder {
-	e := &encoder{}
-	yaml_emitter_initialize(&e.emitter)
-	yaml_emitter_set_output_string(&e.emitter, &e.out)
-	yaml_emitter_set_unicode(&e.emitter, true)
-	return e
-}
-
-func newEncoderWithWriter(w io.Writer) *encoder {
-	e := &encoder{}
-	yaml_emitter_initialize(&e.emitter)
-	yaml_emitter_set_output_writer(&e.emitter, w)
-	yaml_emitter_set_unicode(&e.emitter, true)
-	return e
-}
-
-func (e *encoder) init() {
-	if e.doneInit {
-		return
-	}
-	yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING)
-	e.emit()
-	e.doneInit = true
-}
-
-func (e *encoder) finish() {
-	e.emitter.open_ended = false
-	yaml_stream_end_event_initialize(&e.event)
-	e.emit()
-}
-
-func (e *encoder) destroy() {
-	yaml_emitter_delete(&e.emitter)
-}
-
-func (e *encoder) emit() {
-	// This will internally delete the e.event value.
-	e.must(yaml_emitter_emit(&e.emitter, &e.event))
-}
-
-func (e *encoder) must(ok bool) {
-	if !ok {
-		msg := e.emitter.problem
-		if msg == "" {
-			msg = "unknown problem generating YAML content"
-		}
-		failf("%s", msg)
-	}
-}
-
-func (e *encoder) marshalDoc(tag string, in reflect.Value) {
-	e.init()
-	yaml_document_start_event_initialize(&e.event, nil, nil, true)
-	e.emit()
-	e.marshal(tag, in)
-	yaml_document_end_event_initialize(&e.event, true)
-	e.emit()
-}
-
-func (e *encoder) marshal(tag string, in reflect.Value) {
-	if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() {
-		e.nilv()
-		return
-	}
-	iface := in.Interface()
-	switch m := iface.(type) {
-	case time.Time, *time.Time:
-		// Although time.Time implements TextMarshaler,
-		// we don't want to treat it as a string for YAML
-		// purposes because YAML has special support for
-		// timestamps.
-	case Marshaler:
-		v, err := m.MarshalYAML()
-		if err != nil {
-			fail(err)
-		}
-		if v == nil {
-			e.nilv()
-			return
-		}
-		in = reflect.ValueOf(v)
-	case encoding.TextMarshaler:
-		text, err := m.MarshalText()
-		if err != nil {
-			fail(err)
-		}
-		in = reflect.ValueOf(string(text))
-	case nil:
-		e.nilv()
-		return
-	}
-	switch in.Kind() {
-	case reflect.Interface:
-		e.marshal(tag, in.Elem())
-	case reflect.Map:
-		e.mapv(tag, in)
-	case reflect.Ptr:
-		if in.Type() == ptrTimeType {
-			e.timev(tag, in.Elem())
-		} else {
-			e.marshal(tag, in.Elem())
-		}
-	case reflect.Struct:
-		if in.Type() == timeType {
-			e.timev(tag, in)
-		} else {
-			e.structv(tag, in)
-		}
-	case reflect.Slice, reflect.Array:
-		if in.Type().Elem() == mapItemType {
-			e.itemsv(tag, in)
-		} else {
-			e.slicev(tag, in)
-		}
-	case reflect.String:
-		e.stringv(tag, in)
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		if in.Type() == durationType {
-			e.stringv(tag, reflect.ValueOf(iface.(time.Duration).String()))
-		} else {
-			e.intv(tag, in)
-		}
-	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-		e.uintv(tag, in)
-	case reflect.Float32, reflect.Float64:
-		e.floatv(tag, in)
-	case reflect.Bool:
-		e.boolv(tag, in)
-	default:
-		panic("cannot marshal type: " + in.Type().String())
-	}
-}
-
-func (e *encoder) mapv(tag string, in reflect.Value) {
-	e.mappingv(tag, func() {
-		keys := keyList(in.MapKeys())
-		sort.Sort(keys)
-		for _, k := range keys {
-			e.marshal("", k)
-			e.marshal("", in.MapIndex(k))
-		}
-	})
-}
-
-func (e *encoder) itemsv(tag string, in reflect.Value) {
-	e.mappingv(tag, func() {
-		slice := in.Convert(reflect.TypeOf([]MapItem{})).Interface().([]MapItem)
-		for _, item := range slice {
-			e.marshal("", reflect.ValueOf(item.Key))
-			e.marshal("", reflect.ValueOf(item.Value))
-		}
-	})
-}
-
-func (e *encoder) structv(tag string, in reflect.Value) {
-	sinfo, err := getStructInfo(in.Type())
-	if err != nil {
-		panic(err)
-	}
-	e.mappingv(tag, func() {
-		for _, info := range sinfo.FieldsList {
-			var value reflect.Value
-			if info.Inline == nil {
-				value = in.Field(info.Num)
-			} else {
-				value = in.FieldByIndex(info.Inline)
-			}
-			if info.OmitEmpty && isZero(value) {
-				continue
-			}
-			e.marshal("", reflect.ValueOf(info.Key))
-			e.flow = info.Flow
-			e.marshal("", value)
-		}
-		if sinfo.InlineMap >= 0 {
-			m := in.Field(sinfo.InlineMap)
-			if m.Len() > 0 {
-				e.flow = false
-				keys := keyList(m.MapKeys())
-				sort.Sort(keys)
-				for _, k := range keys {
-					if _, found := sinfo.FieldsMap[k.String()]; found {
-						panic(fmt.Sprintf("Can't have key %q in inlined map; conflicts with struct field", k.String()))
-					}
-					e.marshal("", k)
-					e.flow = false
-					e.marshal("", m.MapIndex(k))
-				}
-			}
-		}
-	})
-}
-
-func (e *encoder) mappingv(tag string, f func()) {
-	implicit := tag == ""
-	style := yaml_BLOCK_MAPPING_STYLE
-	if e.flow {
-		e.flow = false
-		style = yaml_FLOW_MAPPING_STYLE
-	}
-	yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)
-	e.emit()
-	f()
-	yaml_mapping_end_event_initialize(&e.event)
-	e.emit()
-}
-
-func (e *encoder) slicev(tag string, in reflect.Value) {
-	implicit := tag == ""
-	style := yaml_BLOCK_SEQUENCE_STYLE
-	if e.flow {
-		e.flow = false
-		style = yaml_FLOW_SEQUENCE_STYLE
-	}
-	e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style))
-	e.emit()
-	n := in.Len()
-	for i := 0; i < n; i++ {
-		e.marshal("", in.Index(i))
-	}
-	e.must(yaml_sequence_end_event_initialize(&e.event))
-	e.emit()
-}
-
-// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1.
-//
-// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported
-// in YAML 1.2 and by this package, but these should be marshalled quoted for
-// the time being for compatibility with other parsers.
-func isBase60Float(s string) (result bool) {
-	// Fast path.
-	if s == "" {
-		return false
-	}
-	c := s[0]
-	if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 {
-		return false
-	}
-	// Do the full match.
-	return base60float.MatchString(s)
-}
-
-// From http://yaml.org/type/float.html, except the regular expression there
-// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix.
-var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`)
-
-func (e *encoder) stringv(tag string, in reflect.Value) {
-	var style yaml_scalar_style_t
-	s := in.String()
-	canUsePlain := true
-	switch {
-	case !utf8.ValidString(s):
-		if tag == yaml_BINARY_TAG {
-			failf("explicitly tagged !!binary data must be base64-encoded")
-		}
-		if tag != "" {
-			failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag))
-		}
-		// It can't be encoded directly as YAML so use a binary tag
-		// and encode it as base64.
-		tag = yaml_BINARY_TAG
-		s = encodeBase64(s)
-	case tag == "":
-		// Check to see if it would resolve to a specific
-		// tag when encoded unquoted. If it doesn't,
-		// there's no need to quote it.
-		rtag, _ := resolve("", s)
-		canUsePlain = rtag == yaml_STR_TAG && !isBase60Float(s)
-	}
-	// Note: it's possible for user code to emit invalid YAML
-	// if they explicitly specify a tag and a string containing
-	// text that's incompatible with that tag.
-	switch {
-	case strings.Contains(s, "\n"):
-		style = yaml_LITERAL_SCALAR_STYLE
-	case canUsePlain:
-		style = yaml_PLAIN_SCALAR_STYLE
-	default:
-		style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
-	}
-	e.emitScalar(s, "", tag, style)
-}
-
-func (e *encoder) boolv(tag string, in reflect.Value) {
-	var s string
-	if in.Bool() {
-		s = "true"
-	} else {
-		s = "false"
-	}
-	e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
-}
-
-func (e *encoder) intv(tag string, in reflect.Value) {
-	s := strconv.FormatInt(in.Int(), 10)
-	e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
-}
-
-func (e *encoder) uintv(tag string, in reflect.Value) {
-	s := strconv.FormatUint(in.Uint(), 10)
-	e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
-}
-
-func (e *encoder) timev(tag string, in reflect.Value) {
-	t := in.Interface().(time.Time)
-	s := t.Format(time.RFC3339Nano)
-	e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
-}
-
-func (e *encoder) floatv(tag string, in reflect.Value) {
-	// Issue #352: When formatting, use the precision of the underlying value
-	precision := 64
-	if in.Kind() == reflect.Float32 {
-		precision = 32
-	}
-
-	s := strconv.FormatFloat(in.Float(), 'g', -1, precision)
-	switch s {
-	case "+Inf":
-		s = ".inf"
-	case "-Inf":
-		s = "-.inf"
-	case "NaN":
-		s = ".nan"
-	}
-	e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
-}
-
-func (e *encoder) nilv() {
-	e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE)
-}
-
-func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t) {
-	implicit := tag == ""
-	e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style))
-	e.emit()
-}
diff --git a/internal/third_party/yaml/encode_test.go b/internal/third_party/yaml/encode_test.go
deleted file mode 100644
index f0911a7..0000000
--- a/internal/third_party/yaml/encode_test.go
+++ /dev/null
@@ -1,595 +0,0 @@
-package yaml_test
-
-import (
-	"bytes"
-	"fmt"
-	"math"
-	"strconv"
-	"strings"
-	"time"
-
-	"net"
-	"os"
-
-	. "gopkg.in/check.v1"
-	"gopkg.in/yaml.v2"
-)
-
-var marshalIntTest = 123
-
-var marshalTests = []struct {
-	value interface{}
-	data  string
-}{
-	{
-		nil,
-		"null\n",
-	}, {
-		(*marshalerType)(nil),
-		"null\n",
-	}, {
-		&struct{}{},
-		"{}\n",
-	}, {
-		map[string]string{"v": "hi"},
-		"v: hi\n",
-	}, {
-		map[string]interface{}{"v": "hi"},
-		"v: hi\n",
-	}, {
-		map[string]string{"v": "true"},
-		"v: \"true\"\n",
-	}, {
-		map[string]string{"v": "false"},
-		"v: \"false\"\n",
-	}, {
-		map[string]interface{}{"v": true},
-		"v: true\n",
-	}, {
-		map[string]interface{}{"v": false},
-		"v: false\n",
-	}, {
-		map[string]interface{}{"v": 10},
-		"v: 10\n",
-	}, {
-		map[string]interface{}{"v": -10},
-		"v: -10\n",
-	}, {
-		map[string]uint{"v": 42},
-		"v: 42\n",
-	}, {
-		map[string]interface{}{"v": int64(4294967296)},
-		"v: 4294967296\n",
-	}, {
-		map[string]int64{"v": int64(4294967296)},
-		"v: 4294967296\n",
-	}, {
-		map[string]uint64{"v": 4294967296},
-		"v: 4294967296\n",
-	}, {
-		map[string]interface{}{"v": "10"},
-		"v: \"10\"\n",
-	}, {
-		map[string]interface{}{"v": 0.1},
-		"v: 0.1\n",
-	}, {
-		map[string]interface{}{"v": float64(0.1)},
-		"v: 0.1\n",
-	}, {
-		map[string]interface{}{"v": float32(0.99)},
-		"v: 0.99\n",
-	}, {
-		map[string]interface{}{"v": -0.1},
-		"v: -0.1\n",
-	}, {
-		map[string]interface{}{"v": math.Inf(+1)},
-		"v: .inf\n",
-	}, {
-		map[string]interface{}{"v": math.Inf(-1)},
-		"v: -.inf\n",
-	}, {
-		map[string]interface{}{"v": math.NaN()},
-		"v: .nan\n",
-	}, {
-		map[string]interface{}{"v": nil},
-		"v: null\n",
-	}, {
-		map[string]interface{}{"v": ""},
-		"v: \"\"\n",
-	}, {
-		map[string][]string{"v": []string{"A", "B"}},
-		"v:\n- A\n- B\n",
-	}, {
-		map[string][]string{"v": []string{"A", "B\nC"}},
-		"v:\n- A\n- |-\n  B\n  C\n",
-	}, {
-		map[string][]interface{}{"v": []interface{}{"A", 1, map[string][]int{"B": []int{2, 3}}}},
-		"v:\n- A\n- 1\n- B:\n  - 2\n  - 3\n",
-	}, {
-		map[string]interface{}{"a": map[interface{}]interface{}{"b": "c"}},
-		"a:\n  b: c\n",
-	}, {
-		map[string]interface{}{"a": "-"},
-		"a: '-'\n",
-	},
-
-	// Simple values.
-	{
-		&marshalIntTest,
-		"123\n",
-	},
-
-	// Structures
-	{
-		&struct{ Hello string }{"world"},
-		"hello: world\n",
-	}, {
-		&struct {
-			A struct {
-				B string
-			}
-		}{struct{ B string }{"c"}},
-		"a:\n  b: c\n",
-	}, {
-		&struct {
-			A *struct {
-				B string
-			}
-		}{&struct{ B string }{"c"}},
-		"a:\n  b: c\n",
-	}, {
-		&struct {
-			A *struct {
-				B string
-			}
-		}{},
-		"a: null\n",
-	}, {
-		&struct{ A int }{1},
-		"a: 1\n",
-	}, {
-		&struct{ A []int }{[]int{1, 2}},
-		"a:\n- 1\n- 2\n",
-	}, {
-		&struct{ A [2]int }{[2]int{1, 2}},
-		"a:\n- 1\n- 2\n",
-	}, {
-		&struct {
-			B int "a"
-		}{1},
-		"a: 1\n",
-	}, {
-		&struct{ A bool }{true},
-		"a: true\n",
-	},
-
-	// Conditional flag
-	{
-		&struct {
-			A int "a,omitempty"
-			B int "b,omitempty"
-		}{1, 0},
-		"a: 1\n",
-	}, {
-		&struct {
-			A int "a,omitempty"
-			B int "b,omitempty"
-		}{0, 0},
-		"{}\n",
-	}, {
-		&struct {
-			A *struct{ X, y int } "a,omitempty,flow"
-		}{&struct{ X, y int }{1, 2}},
-		"a: {x: 1}\n",
-	}, {
-		&struct {
-			A *struct{ X, y int } "a,omitempty,flow"
-		}{nil},
-		"{}\n",
-	}, {
-		&struct {
-			A *struct{ X, y int } "a,omitempty,flow"
-		}{&struct{ X, y int }{}},
-		"a: {x: 0}\n",
-	}, {
-		&struct {
-			A struct{ X, y int } "a,omitempty,flow"
-		}{struct{ X, y int }{1, 2}},
-		"a: {x: 1}\n",
-	}, {
-		&struct {
-			A struct{ X, y int } "a,omitempty,flow"
-		}{struct{ X, y int }{0, 1}},
-		"{}\n",
-	}, {
-		&struct {
-			A float64 "a,omitempty"
-			B float64 "b,omitempty"
-		}{1, 0},
-		"a: 1\n",
-	},
-	{
-		&struct {
-			T1 time.Time  "t1,omitempty"
-			T2 time.Time  "t2,omitempty"
-			T3 *time.Time "t3,omitempty"
-			T4 *time.Time "t4,omitempty"
-		}{
-			T2: time.Date(2018, 1, 9, 10, 40, 47, 0, time.UTC),
-			T4: newTime(time.Date(2098, 1, 9, 10, 40, 47, 0, time.UTC)),
-		},
-		"t2: 2018-01-09T10:40:47Z\nt4: 2098-01-09T10:40:47Z\n",
-	},
-	// Nil interface that implements Marshaler.
-	{
-		map[string]yaml.Marshaler{
-			"a": nil,
-		},
-		"a: null\n",
-	},
-
-	// Flow flag
-	{
-		&struct {
-			A []int "a,flow"
-		}{[]int{1, 2}},
-		"a: [1, 2]\n",
-	}, {
-		&struct {
-			A map[string]string "a,flow"
-		}{map[string]string{"b": "c", "d": "e"}},
-		"a: {b: c, d: e}\n",
-	}, {
-		&struct {
-			A struct {
-				B, D string
-			} "a,flow"
-		}{struct{ B, D string }{"c", "e"}},
-		"a: {b: c, d: e}\n",
-	},
-
-	// Unexported field
-	{
-		&struct {
-			u int
-			A int
-		}{0, 1},
-		"a: 1\n",
-	},
-
-	// Ignored field
-	{
-		&struct {
-			A int
-			B int "-"
-		}{1, 2},
-		"a: 1\n",
-	},
-
-	// Struct inlining
-	{
-		&struct {
-			A int
-			C inlineB `yaml:",inline"`
-		}{1, inlineB{2, inlineC{3}}},
-		"a: 1\nb: 2\nc: 3\n",
-	},
-
-	// Map inlining
-	{
-		&struct {
-			A int
-			C map[string]int `yaml:",inline"`
-		}{1, map[string]int{"b": 2, "c": 3}},
-		"a: 1\nb: 2\nc: 3\n",
-	},
-
-	// Duration
-	{
-		map[string]time.Duration{"a": 3 * time.Second},
-		"a: 3s\n",
-	},
-
-	// Issue #24: bug in map merging logic.
-	{
-		map[string]string{"a": "<foo>"},
-		"a: <foo>\n",
-	},
-
-	// Issue #34: marshal unsupported base 60 floats quoted for compatibility
-	// with old YAML 1.1 parsers.
-	{
-		map[string]string{"a": "1:1"},
-		"a: \"1:1\"\n",
-	},
-
-	// Binary data.
-	{
-		map[string]string{"a": "\x00"},
-		"a: \"\\0\"\n",
-	}, {
-		map[string]string{"a": "\x80\x81\x82"},
-		"a: !!binary gIGC\n",
-	}, {
-		map[string]string{"a": strings.Repeat("\x90", 54)},
-		"a: !!binary |\n  " + strings.Repeat("kJCQ", 17) + "kJ\n  CQ\n",
-	},
-
-	// Ordered maps.
-	{
-		&yaml.MapSlice{{"b", 2}, {"a", 1}, {"d", 4}, {"c", 3}, {"sub", yaml.MapSlice{{"e", 5}}}},
-		"b: 2\na: 1\nd: 4\nc: 3\nsub:\n  e: 5\n",
-	},
-
-	// Encode unicode as utf-8 rather than in escaped form.
-	{
-		map[string]string{"a": "你好"},
-		"a: 你好\n",
-	},
-
-	// Support encoding.TextMarshaler.
-	{
-		map[string]net.IP{"a": net.IPv4(1, 2, 3, 4)},
-		"a: 1.2.3.4\n",
-	},
-	// time.Time gets a timestamp tag.
-	{
-		map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, 0, time.UTC)},
-		"a: 2015-02-24T18:19:39Z\n",
-	},
-	{
-		map[string]*time.Time{"a": newTime(time.Date(2015, 2, 24, 18, 19, 39, 0, time.UTC))},
-		"a: 2015-02-24T18:19:39Z\n",
-	},
-	{
-		// This is confirmed to be properly decoded in Python (libyaml) without a timestamp tag.
-		map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, 123456789, time.FixedZone("FOO", -3*60*60))},
-		"a: 2015-02-24T18:19:39.123456789-03:00\n",
-	},
-	// Ensure timestamp-like strings are quoted.
-	{
-		map[string]string{"a": "2015-02-24T18:19:39Z"},
-		"a: \"2015-02-24T18:19:39Z\"\n",
-	},
-
-	// Ensure strings containing ": " are quoted (reported as PR #43, but not reproducible).
-	{
-		map[string]string{"a": "b: c"},
-		"a: 'b: c'\n",
-	},
-
-	// Containing hash mark ('#') in string should be quoted
-	{
-		map[string]string{"a": "Hello #comment"},
-		"a: 'Hello #comment'\n",
-	},
-	{
-		map[string]string{"a": "你好 #comment"},
-		"a: '你好 #comment'\n",
-	},
-}
-
-func (s *S) TestMarshal(c *C) {
-	defer os.Setenv("TZ", os.Getenv("TZ"))
-	os.Setenv("TZ", "UTC")
-	for i, item := range marshalTests {
-		c.Logf("test %d: %q", i, item.data)
-		data, err := yaml.Marshal(item.value)
-		c.Assert(err, IsNil)
-		c.Assert(string(data), Equals, item.data)
-	}
-}
-
-func (s *S) TestEncoderSingleDocument(c *C) {
-	for i, item := range marshalTests {
-		c.Logf("test %d. %q", i, item.data)
-		var buf bytes.Buffer
-		enc := yaml.NewEncoder(&buf)
-		err := enc.Encode(item.value)
-		c.Assert(err, Equals, nil)
-		err = enc.Close()
-		c.Assert(err, Equals, nil)
-		c.Assert(buf.String(), Equals, item.data)
-	}
-}
-
-func (s *S) TestEncoderMultipleDocuments(c *C) {
-	var buf bytes.Buffer
-	enc := yaml.NewEncoder(&buf)
-	err := enc.Encode(map[string]string{"a": "b"})
-	c.Assert(err, Equals, nil)
-	err = enc.Encode(map[string]string{"c": "d"})
-	c.Assert(err, Equals, nil)
-	err = enc.Close()
-	c.Assert(err, Equals, nil)
-	c.Assert(buf.String(), Equals, "a: b\n---\nc: d\n")
-}
-
-func (s *S) TestEncoderWriteError(c *C) {
-	enc := yaml.NewEncoder(errorWriter{})
-	err := enc.Encode(map[string]string{"a": "b"})
-	c.Assert(err, ErrorMatches, `yaml: write error: some write error`) // Data not flushed yet
-}
-
-type errorWriter struct{}
-
-func (errorWriter) Write([]byte) (int, error) {
-	return 0, fmt.Errorf("some write error")
-}
-
-var marshalErrorTests = []struct {
-	value interface{}
-	error string
-	panic string
-}{{
-	value: &struct {
-		B       int
-		inlineB ",inline"
-	}{1, inlineB{2, inlineC{3}}},
-	panic: `Duplicated key 'b' in struct struct \{ B int; .*`,
-}, {
-	value: &struct {
-		A int
-		B map[string]int ",inline"
-	}{1, map[string]int{"a": 2}},
-	panic: `Can't have key "a" in inlined map; conflicts with struct field`,
-}}
-
-func (s *S) TestMarshalErrors(c *C) {
-	for _, item := range marshalErrorTests {
-		if item.panic != "" {
-			c.Assert(func() { yaml.Marshal(item.value) }, PanicMatches, item.panic)
-		} else {
-			_, err := yaml.Marshal(item.value)
-			c.Assert(err, ErrorMatches, item.error)
-		}
-	}
-}
-
-func (s *S) TestMarshalTypeCache(c *C) {
-	var data []byte
-	var err error
-	func() {
-		type T struct{ A int }
-		data, err = yaml.Marshal(&T{})
-		c.Assert(err, IsNil)
-	}()
-	func() {
-		type T struct{ B int }
-		data, err = yaml.Marshal(&T{})
-		c.Assert(err, IsNil)
-	}()
-	c.Assert(string(data), Equals, "b: 0\n")
-}
-
-var marshalerTests = []struct {
-	data  string
-	value interface{}
-}{
-	{"_:\n  hi: there\n", map[interface{}]interface{}{"hi": "there"}},
-	{"_:\n- 1\n- A\n", []interface{}{1, "A"}},
-	{"_: 10\n", 10},
-	{"_: null\n", nil},
-	{"_: BAR!\n", "BAR!"},
-}
-
-type marshalerType struct {
-	value interface{}
-}
-
-func (o marshalerType) MarshalText() ([]byte, error) {
-	panic("MarshalText called on type with MarshalYAML")
-}
-
-func (o marshalerType) MarshalYAML() (interface{}, error) {
-	return o.value, nil
-}
-
-type marshalerValue struct {
-	Field marshalerType "_"
-}
-
-func (s *S) TestMarshaler(c *C) {
-	for _, item := range marshalerTests {
-		obj := &marshalerValue{}
-		obj.Field.value = item.value
-		data, err := yaml.Marshal(obj)
-		c.Assert(err, IsNil)
-		c.Assert(string(data), Equals, string(item.data))
-	}
-}
-
-func (s *S) TestMarshalerWholeDocument(c *C) {
-	obj := &marshalerType{}
-	obj.value = map[string]string{"hello": "world!"}
-	data, err := yaml.Marshal(obj)
-	c.Assert(err, IsNil)
-	c.Assert(string(data), Equals, "hello: world!\n")
-}
-
-type failingMarshaler struct{}
-
-func (ft *failingMarshaler) MarshalYAML() (interface{}, error) {
-	return nil, failingErr
-}
-
-func (s *S) TestMarshalerError(c *C) {
-	_, err := yaml.Marshal(&failingMarshaler{})
-	c.Assert(err, Equals, failingErr)
-}
-
-func (s *S) TestSortedOutput(c *C) {
-	order := []interface{}{
-		false,
-		true,
-		1,
-		uint(1),
-		1.0,
-		1.1,
-		1.2,
-		2,
-		uint(2),
-		2.0,
-		2.1,
-		"",
-		".1",
-		".2",
-		".a",
-		"1",
-		"2",
-		"a!10",
-		"a/0001",
-		"a/002",
-		"a/3",
-		"a/10",
-		"a/11",
-		"a/0012",
-		"a/100",
-		"a~10",
-		"ab/1",
-		"b/1",
-		"b/01",
-		"b/2",
-		"b/02",
-		"b/3",
-		"b/03",
-		"b1",
-		"b01",
-		"b3",
-		"c2.10",
-		"c10.2",
-		"d1",
-		"d7",
-		"d7abc",
-		"d12",
-		"d12a",
-	}
-	m := make(map[interface{}]int)
-	for _, k := range order {
-		m[k] = 1
-	}
-	data, err := yaml.Marshal(m)
-	c.Assert(err, IsNil)
-	out := "\n" + string(data)
-	last := 0
-	for i, k := range order {
-		repr := fmt.Sprint(k)
-		if s, ok := k.(string); ok {
-			if _, err = strconv.ParseFloat(repr, 32); s == "" || err == nil {
-				repr = `"` + repr + `"`
-			}
-		}
-		index := strings.Index(out, "\n"+repr+":")
-		if index == -1 {
-			c.Fatalf("%#v is not in the output: %#v", k, out)
-		}
-		if index < last {
-			c.Fatalf("%#v was generated before %#v: %q", k, order[i-1], out)
-		}
-		last = index
-	}
-}
-
-func newTime(t time.Time) *time.Time {
-	return &t
-}
diff --git a/internal/third_party/yaml/example_embedded_test.go b/internal/third_party/yaml/example_embedded_test.go
deleted file mode 100644
index 171c093..0000000
--- a/internal/third_party/yaml/example_embedded_test.go
+++ /dev/null
@@ -1,41 +0,0 @@
-package yaml_test
-
-import (
-	"fmt"
-	"log"
-
-	"gopkg.in/yaml.v2"
-)
-
-// An example showing how to unmarshal embedded
-// structs from YAML.
-
-type StructA struct {
-	A string `yaml:"a"`
-}
-
-type StructB struct {
-	// Embedded structs are not treated as embedded in YAML by default. To do that,
-	// add the ",inline" annotation below
-	StructA `yaml:",inline"`
-	B       string `yaml:"b"`
-}
-
-var data = `
-a: a string from struct A
-b: a string from struct B
-`
-
-func ExampleUnmarshal_embedded() {
-	var b StructB
-
-	err := yaml.Unmarshal([]byte(data), &b)
-	if err != nil {
-		log.Fatalf("cannot unmarshal data: %v", err)
-	}
-	fmt.Println(b.A)
-	fmt.Println(b.B)
-	// Output:
-	// a string from struct A
-	// a string from struct B
-}
diff --git a/internal/third_party/yaml/parserc.go b/internal/third_party/yaml/parserc.go
index 81d05df..52d8f74 100644
--- a/internal/third_party/yaml/parserc.go
+++ b/internal/third_party/yaml/parserc.go
@@ -2,6 +2,8 @@
 
 import (
 	"bytes"
+
+	"cuelang.org/go/cue/token"
 )
 
 // The parser implements the following grammar:
@@ -58,6 +60,14 @@
 	parser.tokens_head++
 }
 
+func add_comment(parser *yaml_parser_t, p token.RelPos, m yaml_mark_t, text string) {
+	parser.comments = append(parser.comments, yaml_comment_t{
+		pos:  p,
+		mark: m,
+		text: text,
+	})
+}
+
 // Get the next event.
 func yaml_parser_parse(parser *yaml_parser_t, event *yaml_event_t) bool {
 	// Erase the event object.
@@ -1010,8 +1020,7 @@
 }
 
 // Parse directives.
-func yaml_parser_process_directives(parser *yaml_parser_t,
-	version_directive_ref **yaml_version_directive_t,
+func yaml_parser_process_directives(parser *yaml_parser_t, version_directive_ref **yaml_version_directive_t,
 	tag_directives_ref *[]yaml_tag_directive_t) bool {
 
 	var version_directive *yaml_version_directive_t
diff --git a/internal/third_party/yaml/readerc.go b/internal/third_party/yaml/readerc.go
index 7c1f5fa..b0c436c 100644
--- a/internal/third_party/yaml/readerc.go
+++ b/internal/third_party/yaml/readerc.go
@@ -95,7 +95,7 @@
 
 	// [Go] This function was changed to guarantee the requested length size at EOF.
 	// The fact we need to do this is pretty awful, but the description above implies
-	// for that to be the case, and there are tests 
+	// for that to be the case, and there are tests
 
 	// If the EOF flag is set and the raw buffer is empty, do nothing.
 	if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) {
diff --git a/internal/third_party/yaml/resolve.go b/internal/third_party/yaml/resolve.go
index 6c151db..bfe67c4 100644
--- a/internal/third_party/yaml/resolve.go
+++ b/internal/third_party/yaml/resolve.go
@@ -83,7 +83,9 @@
 
 var yamlStyleFloat = regexp.MustCompile(`^[-+]?[0-9]*\.?[0-9]+([eE][-+][0-9]+)?$`)
 
-func resolve(tag string, in string) (rtag string, out interface{}) {
+func (d *decoder) resolve(n *node) (rtag string, out interface{}) {
+	tag := n.tag
+	in := n.value
 	if !resolvableTag(tag) {
 		return tag, in
 	}
@@ -106,7 +108,7 @@
 				}
 			}
 		}
-		failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag))
+		d.p.failf(n.startPos.line, "cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag))
 	}()
 
 	// Any data is accepted as a !!str or !!binary.
@@ -180,7 +182,7 @@
 					return yaml_INT_TAG, uintv
 				}
 			} else if strings.HasPrefix(plain, "-0b") {
-				intv, err := strconv.ParseInt("-" + plain[3:], 2, 64)
+				intv, err := strconv.ParseInt("-"+plain[3:], 2, 64)
 				if err == nil {
 					if true || intv == int64(int(intv)) {
 						return yaml_INT_TAG, int(intv)
diff --git a/internal/third_party/yaml/scannerc.go b/internal/third_party/yaml/scannerc.go
index 077fd1d..2229abc 100644
--- a/internal/third_party/yaml/scannerc.go
+++ b/internal/third_party/yaml/scannerc.go
@@ -1427,6 +1427,9 @@
 // Eat whitespaces and comments until the next token is found.
 func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool {
 
+	parser.linesSinceLast = 0
+	parser.spacesSinceLast = 0
+
 	// Until the next token is not found.
 	for {
 		// Allow the BOM mark to start a line.
@@ -1448,6 +1451,7 @@
 
 		for parser.buffer[parser.buffer_pos] == ' ' || ((parser.flow_level > 0 || !parser.simple_key_allowed) && parser.buffer[parser.buffer_pos] == '\t') {
 			skip(parser)
+			parser.spacesSinceLast++
 			if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
 				return false
 			}
@@ -1455,12 +1459,19 @@
 
 		// Eat a comment until a line break.
 		if parser.buffer[parser.buffer_pos] == '#' {
+			rel := parser.relPos()
+			m := parser.mark
+			parser.comment_buffer = parser.comment_buffer[:0]
 			for !is_breakz(parser.buffer, parser.buffer_pos) {
+				p := parser.buffer_pos
 				skip(parser)
+				parser.comment_buffer = append(parser.comment_buffer,
+					parser.buffer[p:parser.buffer_pos]...)
 				if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
 					return false
 				}
 			}
+			add_comment(parser, rel, m, string(parser.comment_buffer))
 		}
 
 		// If it is a line break, eat it.
@@ -1469,6 +1480,7 @@
 				return false
 			}
 			skip_line(parser)
+			parser.linesSinceLast++
 
 			// In the block context, a new line may start a simple key.
 			if parser.flow_level == 0 {
@@ -1557,12 +1569,19 @@
 	}
 
 	if parser.buffer[parser.buffer_pos] == '#' {
+		rel := parser.relPos()
+		m := parser.mark
+		parser.comment_buffer = parser.comment_buffer[:0]
 		for !is_breakz(parser.buffer, parser.buffer_pos) {
+			p := parser.buffer_pos
 			skip(parser)
+			parser.comment_buffer = append(parser.comment_buffer,
+				parser.buffer[p:parser.buffer_pos]...)
 			if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
 				return false
 			}
 		}
+		add_comment(parser, rel, m, string(parser.comment_buffer))
 	}
 
 	// Check if we are at the end of the line.
@@ -2127,12 +2146,19 @@
 		}
 	}
 	if parser.buffer[parser.buffer_pos] == '#' {
+		rel := parser.relPos()
+		m := parser.mark
+		parser.comment_buffer = parser.comment_buffer[:0]
 		for !is_breakz(parser.buffer, parser.buffer_pos) {
+			p := parser.buffer_pos
 			skip(parser)
+			parser.comment_buffer = append(parser.comment_buffer,
+				parser.buffer[p:parser.buffer_pos]...)
 			if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
 				return false
 			}
 		}
+		add_comment(parser, rel, m, string(parser.comment_buffer))
 	}
 
 	// Check if we are at the end of the line.
diff --git a/internal/third_party/yaml/sorter.go b/internal/third_party/yaml/sorter.go
deleted file mode 100644
index 4c45e66..0000000
--- a/internal/third_party/yaml/sorter.go
+++ /dev/null
@@ -1,113 +0,0 @@
-package yaml
-
-import (
-	"reflect"
-	"unicode"
-)
-
-type keyList []reflect.Value
-
-func (l keyList) Len() int      { return len(l) }
-func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
-func (l keyList) Less(i, j int) bool {
-	a := l[i]
-	b := l[j]
-	ak := a.Kind()
-	bk := b.Kind()
-	for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() {
-		a = a.Elem()
-		ak = a.Kind()
-	}
-	for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() {
-		b = b.Elem()
-		bk = b.Kind()
-	}
-	af, aok := keyFloat(a)
-	bf, bok := keyFloat(b)
-	if aok && bok {
-		if af != bf {
-			return af < bf
-		}
-		if ak != bk {
-			return ak < bk
-		}
-		return numLess(a, b)
-	}
-	if ak != reflect.String || bk != reflect.String {
-		return ak < bk
-	}
-	ar, br := []rune(a.String()), []rune(b.String())
-	for i := 0; i < len(ar) && i < len(br); i++ {
-		if ar[i] == br[i] {
-			continue
-		}
-		al := unicode.IsLetter(ar[i])
-		bl := unicode.IsLetter(br[i])
-		if al && bl {
-			return ar[i] < br[i]
-		}
-		if al || bl {
-			return bl
-		}
-		var ai, bi int
-		var an, bn int64
-		if ar[i] == '0' || br[i] == '0' {
-			for j := i-1; j >= 0 && unicode.IsDigit(ar[j]); j-- {
-				if ar[j] != '0' {
-					an = 1
-					bn = 1
-					break
-				}
-			}
-		}
-		for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ {
-			an = an*10 + int64(ar[ai]-'0')
-		}
-		for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ {
-			bn = bn*10 + int64(br[bi]-'0')
-		}
-		if an != bn {
-			return an < bn
-		}
-		if ai != bi {
-			return ai < bi
-		}
-		return ar[i] < br[i]
-	}
-	return len(ar) < len(br)
-}
-
-// keyFloat returns a float value for v if it is a number/bool
-// and whether it is a number/bool or not.
-func keyFloat(v reflect.Value) (f float64, ok bool) {
-	switch v.Kind() {
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		return float64(v.Int()), true
-	case reflect.Float32, reflect.Float64:
-		return v.Float(), true
-	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-		return float64(v.Uint()), true
-	case reflect.Bool:
-		if v.Bool() {
-			return 1, true
-		}
-		return 0, true
-	}
-	return 0, false
-}
-
-// numLess returns whether a < b.
-// a and b must necessarily have the same kind.
-func numLess(a, b reflect.Value) bool {
-	switch a.Kind() {
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		return a.Int() < b.Int()
-	case reflect.Float32, reflect.Float64:
-		return a.Float() < b.Float()
-	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-		return a.Uint() < b.Uint()
-	case reflect.Bool:
-		return !a.Bool() && b.Bool()
-	}
-	panic("not a number")
-}
diff --git a/internal/third_party/yaml/suite_test.go b/internal/third_party/yaml/suite_test.go
deleted file mode 100644
index c5cf1ed..0000000
--- a/internal/third_party/yaml/suite_test.go
+++ /dev/null
@@ -1,12 +0,0 @@
-package yaml_test
-
-import (
-	. "gopkg.in/check.v1"
-	"testing"
-)
-
-func Test(t *testing.T) { TestingT(t) }
-
-type S struct{}
-
-var _ = Suite(&S{})
diff --git a/internal/third_party/yaml/testdata/merge.out b/internal/third_party/yaml/testdata/merge.out
new file mode 100644
index 0000000..e3edf5a
--- /dev/null
+++ b/internal/third_party/yaml/testdata/merge.out
@@ -0,0 +1,69 @@
+// From http://yaml.org/type/merge.html
+// Test
+anchors list: [{
+	x: 1
+	y: 2
+}, {
+	x: 0
+	y: 2
+}, {
+	r: 10
+}, {
+	r: 1
+}]
+// All the following maps are equal:
+plain: {
+	// Explicit keys
+	x:     1
+	y:     2
+	r:     10
+	label: "center/big"
+}
+mergeOne: {
+	x: 1
+	y: 2
+	// Merge one map
+	r:     10
+	label: "center/big"
+}
+mergeMultiple: {
+	r: 10
+	x: 1
+	y: 2
+	// Merge multiple maps
+	label: "center/big"
+}
+override: {
+	r:     10
+	x:     1
+	y:     2
+	label: "center/big"
+}
+shortTag: {
+	r: 10
+	x: 1
+	y: 2
+	// Explicit short merge tag
+	label: "center/big"
+}
+longTag: {
+	r: 10
+	x: 1
+	y: 2
+	// Explicit merge long tag
+	label: "center/big"
+}
+inlineMap: {
+	// Inlined map
+	x:     1
+	y:     2
+	r:     10
+	label: "center/big"
+}
+inlineSequenceMap: {
+	// Inlined map in sequence
+	r:     10
+	x:     1
+	y:     2
+	label: "center/big"
+}
\ No newline at end of file
diff --git a/internal/third_party/yaml/testdata/merge.test b/internal/third_party/yaml/testdata/merge.test
new file mode 100644
index 0000000..733ba2b
--- /dev/null
+++ b/internal/third_party/yaml/testdata/merge.test
@@ -0,0 +1,54 @@
+# From http://yaml.org/type/merge.html
+# Test
+anchors:
+  list:
+    - &CENTER { "x": 1, "y": 2 }
+    - &LEFT   { "x": 0, "y": 2 }
+    - &BIG    { "r": 10 }
+    - &SMALL  { "r": 1 }
+
+# All the following maps are equal:
+
+plain:
+  # Explicit keys
+  "x": 1
+  "y": 2
+  "r": 10
+  label: center/big
+
+mergeOne:
+  # Merge one map
+  << : *CENTER
+  "r": 10
+  label: center/big
+
+mergeMultiple:
+  # Merge multiple maps
+  << : [ *CENTER, *BIG ]
+  label: center/big
+
+override:
+  # Override
+  << : [ *BIG, *LEFT, *SMALL ]
+  "x": 1
+  label: center/big
+
+shortTag:
+  # Explicit short merge tag
+  !!merge "<<" : [ *CENTER, *BIG ]
+  label: center/big
+
+longTag:
+  # Explicit merge long tag
+  !<tag:yaml.org,2002:merge> "<<" : [ *CENTER, *BIG ]
+  label: center/big
+
+inlineMap:
+  # Inlined map
+  << : {"x": 1, "y": 2, "r": 10}
+  label: center/big
+
+inlineSequenceMap:
+  # Inlined map in sequence
+  << : [ *CENTER, {"r": 10} ]
+  label: center/big
\ No newline at end of file
diff --git a/internal/third_party/yaml/writerc.go b/internal/third_party/yaml/writerc.go
deleted file mode 100644
index a2dde60..0000000
--- a/internal/third_party/yaml/writerc.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package yaml
-
-// Set the writer error and return false.
-func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool {
-	emitter.error = yaml_WRITER_ERROR
-	emitter.problem = problem
-	return false
-}
-
-// Flush the output buffer.
-func yaml_emitter_flush(emitter *yaml_emitter_t) bool {
-	if emitter.write_handler == nil {
-		panic("write handler not set")
-	}
-
-	// Check if the buffer is empty.
-	if emitter.buffer_pos == 0 {
-		return true
-	}
-
-	if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil {
-		return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error())
-	}
-	emitter.buffer_pos = 0
-	return true
-}
diff --git a/internal/third_party/yaml/yaml.go b/internal/third_party/yaml/yaml.go
index de85aa4..8251f39 100644
--- a/internal/third_party/yaml/yaml.go
+++ b/internal/third_party/yaml/yaml.go
@@ -4,15 +4,19 @@
 //
 //   https://github.com/go-yaml/yaml
 //
-package yaml
+package yaml // import "cuelang.org/go/internal/third_party/yaml"
 
 import (
 	"errors"
 	"fmt"
 	"io"
 	"reflect"
+	"strconv"
 	"strings"
 	"sync"
+
+	"cuelang.org/go/cue/ast"
+	"cuelang.org/go/cue/token"
 )
 
 // MapSlice encodes and decodes as a YAML map.
@@ -77,16 +81,8 @@
 // See the documentation of Marshal for the format of tags and a list of
 // supported tag options.
 //
-func Unmarshal(in []byte, out interface{}) (err error) {
-	return unmarshal(in, out, false)
-}
-
-// UnmarshalStrict is like Unmarshal except that any fields that are found
-// in the data that do not have corresponding struct members, or mapping
-// keys that are duplicates, will result in
-// an error.
-func UnmarshalStrict(in []byte, out interface{}) (err error) {
-	return unmarshal(in, out, true)
+func Unmarshal(fset *token.FileSet, filename string, in []byte) (expr ast.Expr, err error) {
+	return unmarshal(fset, filename, in)
 }
 
 // A Decorder reads and decodes YAML values from an input stream.
@@ -99,16 +95,12 @@
 //
 // The decoder introduces its own buffering and may read
 // data from r beyond the YAML values requested.
-func NewDecoder(r io.Reader) *Decoder {
-	return &Decoder{
-		parser: newParserFromReader(r),
+func NewDecoder(fset *token.FileSet, filename string, r io.Reader) (*Decoder, error) {
+	d, err := newParser(fset, filename, r)
+	if err != nil {
+		return nil, err
 	}
-}
-
-// SetStrict sets whether strict decoding behaviour is enabled when
-// decoding items in the data (see UnmarshalStrict). By default, decoding is not strict.
-func (dec *Decoder) SetStrict(strict bool) {
-	dec.strict = strict
+	return &Decoder{parser: d}, nil
 }
 
 // Decode reads the next YAML-encoded value from its input
@@ -116,129 +108,36 @@
 //
 // See the documentation for Unmarshal for details about the
 // conversion of YAML into a Go value.
-func (dec *Decoder) Decode(v interface{}) (err error) {
-	d := newDecoder(dec.strict)
+func (dec *Decoder) Decode() (expr ast.Expr, err error) {
+	d := newDecoder(dec.parser)
 	defer handleErr(&err)
 	node := dec.parser.parse()
 	if node == nil {
-		return io.EOF
+		return nil, io.EOF
 	}
-	out := reflect.ValueOf(v)
-	if out.Kind() == reflect.Ptr && !out.IsNil() {
-		out = out.Elem()
-	}
-	d.unmarshal(node, out)
+	expr = d.unmarshal(node)
 	if len(d.terrors) > 0 {
-		return &TypeError{d.terrors}
+		return nil, &TypeError{d.terrors}
 	}
-	return nil
+	return expr, nil
 }
 
-func unmarshal(in []byte, out interface{}, strict bool) (err error) {
+func unmarshal(fset *token.FileSet, filename string, in []byte) (expr ast.Expr, err error) {
 	defer handleErr(&err)
-	d := newDecoder(strict)
-	p := newParser(in)
+	p, err := newParser(fset, filename, in)
+	if err != nil {
+		return nil, err
+	}
 	defer p.destroy()
 	node := p.parse()
+	d := newDecoder(p)
 	if node != nil {
-		v := reflect.ValueOf(out)
-		if v.Kind() == reflect.Ptr && !v.IsNil() {
-			v = v.Elem()
-		}
-		d.unmarshal(node, v)
+		expr = d.unmarshal(node)
 	}
 	if len(d.terrors) > 0 {
-		return &TypeError{d.terrors}
+		return nil, &TypeError{d.terrors}
 	}
-	return nil
-}
-
-// Marshal serializes the value provided into a YAML document. The structure
-// of the generated document will reflect the structure of the value itself.
-// Maps and pointers (to struct, string, int, etc) are accepted as the in value.
-//
-// Struct fields are only marshalled if they are exported (have an upper case
-// first letter), and are marshalled using the field name lowercased as the
-// default key. Custom keys may be defined via the "yaml" name in the field
-// tag: the content preceding the first comma is used as the key, and the
-// following comma-separated options are used to tweak the marshalling process.
-// Conflicting names result in a runtime error.
-//
-// The field tag format accepted is:
-//
-//     `(...) yaml:"[<key>][,<flag1>[,<flag2>]]" (...)`
-//
-// The following flags are currently supported:
-//
-//     omitempty    Only include the field if it's not set to the zero
-//                  value for the type or to empty slices or maps.
-//                  Zero valued structs will be omitted if all their public
-//                  fields are zero, unless they implement an IsZero
-//                  method (see the IsZeroer interface type), in which
-//                  case the field will be included if that method returns true.
-//
-//     flow         Marshal using a flow style (useful for structs,
-//                  sequences and maps).
-//
-//     inline       Inline the field, which must be a struct or a map,
-//                  causing all of its fields or keys to be processed as if
-//                  they were part of the outer struct. For maps, keys must
-//                  not conflict with the yaml keys of other struct fields.
-//
-// In addition, if the key is "-", the field is ignored.
-//
-// For example:
-//
-//     type T struct {
-//         F int `yaml:"a,omitempty"`
-//         B int
-//     }
-//     yaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
-//     yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n"
-//
-func Marshal(in interface{}) (out []byte, err error) {
-	defer handleErr(&err)
-	e := newEncoder()
-	defer e.destroy()
-	e.marshalDoc("", reflect.ValueOf(in))
-	e.finish()
-	out = e.out
-	return
-}
-
-// An Encoder writes YAML values to an output stream.
-type Encoder struct {
-	encoder *encoder
-}
-
-// NewEncoder returns a new encoder that writes to w.
-// The Encoder should be closed after use to flush all data
-// to w.
-func NewEncoder(w io.Writer) *Encoder {
-	return &Encoder{
-		encoder: newEncoderWithWriter(w),
-	}
-}
-
-// Encode writes the YAML encoding of v to the stream.
-// If multiple items are encoded to the stream, the
-// second and subsequent document will be preceded
-// with a "---" document separator, but the first will not.
-//
-// See the documentation for Marshal for details about the conversion of Go
-// values to YAML.
-func (e *Encoder) Encode(v interface{}) (err error) {
-	defer handleErr(&err)
-	e.encoder.marshalDoc("", reflect.ValueOf(v))
-	return nil
-}
-
-// Close closes the encoder by writing any remaining data.
-// It does not write a stream terminating string "...".
-func (e *Encoder) Close() (err error) {
-	defer handleErr(&err)
-	e.encoder.finish()
-	return nil
+	return expr, nil
 }
 
 func handleErr(err *error) {
@@ -255,12 +154,11 @@
 	err error
 }
 
-func fail(err error) {
-	panic(yamlError{err})
-}
-
-func failf(format string, args ...interface{}) {
-	panic(yamlError{fmt.Errorf("yaml: "+format, args...)})
+func (p *parser) failf(line int, format string, args ...interface{}) {
+	where := p.parser.filename + ":"
+	line++
+	where += strconv.Itoa(line) + ": "
+	panic(yamlError{fmt.Errorf(where+format, args...)})
 }
 
 // A TypeError is returned by Unmarshal when one or more fields in
diff --git a/internal/third_party/yaml/yamlh.go b/internal/third_party/yaml/yamlh.go
index e25cee5..93ab268 100644
--- a/internal/third_party/yaml/yamlh.go
+++ b/internal/third_party/yaml/yamlh.go
@@ -3,6 +3,8 @@
 import (
 	"fmt"
 	"io"
+
+	"cuelang.org/go/cue/token"
 )
 
 // The version directive data.
@@ -518,6 +520,29 @@
 	mark   yaml_mark_t // The anchor mark.
 }
 
+type yaml_comment_t struct {
+	pos  token.RelPos
+	mark yaml_mark_t
+	text string
+}
+
+func (p *yaml_parser_t) relPos() (pos token.RelPos) {
+	switch {
+	case p.linesSinceLast > 1:
+		pos = token.NewSection
+	case p.linesSinceLast == 1:
+		pos = token.Newline
+	case p.spacesSinceLast > 0:
+		pos = token.Blank
+	default:
+		pos = token.NoSpace
+	}
+	p.linesSinceLast = 0
+	p.spacesSinceLast = 0
+	// fmt.Println("REL", pos)
+	return token.NoRelPos
+}
+
 // The parser structure.
 //
 // All members are internal. Manage the structure using the
@@ -526,6 +551,8 @@
 
 	// Error handling
 
+	filename string
+
 	error yaml_error_type_t // Error type.
 
 	problem string // Error description.
@@ -557,11 +584,16 @@
 	raw_buffer     []byte // The raw buffer.
 	raw_buffer_pos int    // The current position of the buffer.
 
+	comment_buffer []byte
+
 	encoding yaml_encoding_t // The input encoding.
 
 	offset int         // The offset of the current position (in bytes).
 	mark   yaml_mark_t // The mark of the current position.
 
+	linesSinceLast  int
+	spacesSinceLast int
+
 	// Scanner stuff
 
 	stream_start_produced bool // Have we started to scan the input stream?
@@ -574,6 +606,8 @@
 	tokens_parsed   int            // The number of tokens fetched from the queue.
 	token_available bool           // Does the tokens queue contain a token ready for dequeueing.
 
+	comments []yaml_comment_t
+
 	indent  int   // The current indentation level.
 	indents []int // The indentation levels stack.