code: func (t *tree) parseMsg(token item) ast.Node {
  	const ctx = "msg"
  	var attrs = t.parseAttrs("desc", "meaning", "hidden")
  	if _, ok := attrs["desc"]; !ok {
  		t.errorf("Tag 'msg' must have a 'desc' attribute")
  	}
  	t.expect(itemRightDelim, ctx)
  
  	// Parse the message body.
  	t.inmsg = true
  	var contents = t.itemList(itemMsgEnd)
  	t.inmsg = false
  
  	// Replace children nodes with placeholders.
  	var node = &ast.MsgNode{token.pos, 0, attrs["meaning"], attrs["desc"], t.placeholderize(contents)}
  
  	// Validate: if there's a plural tag, it should be the only child
  	var hasPlural = false
  	for _, child := range node.Body.Children() {
  		if _, ok := child.(*ast.MsgPluralNode); ok {
  			hasPlural = true
  		}
  	}
  	if hasPlural && len(node.Body.Children()) != 1 {
  		t.errorf("content not allowed outside plural tag")
  	}
  
  	t.expect(itemRightDelim, ctx)
  	return node
  }
docs: // "msg" has just been read.