Support map merging.

Fixes #1.
diff --git a/decode.go b/decode.go
index 75a2c42..ab2b8f7 100644
--- a/decode.go
+++ b/decode.go
@@ -438,6 +438,10 @@
 	}
 	l := len(n.children)
 	for i := 0; i < l; i += 2 {
+		if isMerge(n.children[i]) {
+			d.merge(n.children[i+1], out)
+			continue
+		}
 		k := reflect.New(kt).Elem()
 		if d.unmarshal(n.children[i], k) {
 			e := reflect.New(et).Elem()
@@ -457,7 +461,12 @@
 	name := settableValueOf("")
 	l := len(n.children)
 	for i := 0; i < l; i += 2 {
-		if !d.unmarshal(n.children[i], name) {
+		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 {
@@ -472,3 +481,37 @@
 	}
 	return true
 }
+
+func (d *decoder) merge(n *node, out reflect.Value) {
+	const wantMap = "map merge requires map or sequence of maps as the value"
+	switch n.kind {
+	case mappingNode:
+		d.unmarshal(n, out)
+	case aliasNode:
+		an, ok := d.doc.anchors[n.value]
+		if ok && an.kind != mappingNode {
+			panic(wantMap)
+		}
+		d.unmarshal(n, out)
+	case sequenceNode:
+		// Step backwards as earlier nodes take precedence.
+		for i := len(n.children)-1; i >= 0; i-- {
+			ni := n.children[i]
+			if ni.kind == aliasNode {
+				an, ok := d.doc.anchors[ni.value]
+				if ok && an.kind != mappingNode {
+					panic(wantMap)
+				}
+			} else if ni.kind != mappingNode {
+				panic(wantMap)
+			}
+			d.unmarshal(ni, out)
+		}
+	default:
+		panic(wantMap)
+	}
+}
+
+func isMerge(n *node) bool {
+	return n.kind == scalarNode && n.value == "<<" && (n.implicit == true || n.tag == "!!merge" || n.tag == "tag:yaml.org,2002:merge")
+}
diff --git a/decode_test.go b/decode_test.go
index 55db804..5702909 100644
--- a/decode_test.go
+++ b/decode_test.go
@@ -505,6 +505,98 @@
 	c.Assert(m["ghi"].value, Equals, 3)
 }
 
+// From http://yaml.org/type/merge.html
+var mergeTests = `
+anchors:
+  - &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[string]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 data []byte
 //func init() {
 //	var err error
diff --git a/resolve.go b/resolve.go
index dbda017..fdc4909 100644
--- a/resolve.go
+++ b/resolve.go
@@ -45,6 +45,7 @@
 		{math.Inf(+1), "!!float", []string{".inf", ".Inf", ".INF"}},
 		{math.Inf(+1), "!!float", []string{"+.inf", "+.Inf", "+.INF"}},
 		{math.Inf(-1), "!!float", []string{"-.inf", "-.Inf", "-.INF"}},
+		{"<<", "!!merge", []string{"<<"}},
 	}
 
 	m := resolveMap
@@ -139,9 +140,6 @@
 		}
 	// XXX Handle timestamps here.
 
-	case '<':
-		// XXX Handle merge (<<) here.
-
 	default:
 		panic("resolveTable item not yet handled: " +
 			string([]byte{c}) + " (with " + in + ")")