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/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