// Parse returns all of the documents in the stream. func (parser *Parser) Parse() (docs []*Document, err error) { docs = make([]*Document, 0, 1) docLoop: for { var newDoc *Document // Parse document newDoc, err = parser.ParseDocument() if err != nil { return } // Add document to array if cap(docs) < len(docs)+1 { newDocs := make([]*Document, len(docs), cap(docs)*2) copy(newDocs, docs) docs = newDocs } docs = docs[0 : len(docs)+1] docs[len(docs)-1] = newDoc // Eat up any end document tokens endDocLoop: for { var tok scanner.Token if tok, err = parser.scan(); err != nil { return } switch tok.GetKind() { case token.DOCUMENT_END: // Ignore case token.STREAM_END: break docLoop default: parser.unscan(tok) break endDocLoop } } } return }
func (parser *Parser) parseDocHeader() (err error) { startedHeader := false for { var tok scanner.Token tok, err = parser.scan() if err != nil { return } switch tok.GetKind() { case token.STREAM_START: // Ignore case token.VERSION_DIRECTIVE: startedHeader = true versionDir := tok.(scanner.VersionDirective) parser.doc.MajorVersion, parser.doc.MinorVersion = versionDir.Major, versionDir.Minor case token.TAG_DIRECTIVE: startedHeader = true if err = parser.handleTagDirective(tok.(scanner.TagDirective)); err != nil { return } case token.DOCUMENT_START: return case token.DOCUMENT_END: if startedHeader { err = errors.New("End document token appeared after directives") return } default: parser.unscan(tok) return } } // This should never be reached. return nil }
func (parser *Parser) parseMapping(block bool) (node *Mapping, err error) { var tok scanner.Token var sentinel token.Token // Discard opening token if tok, err = parser.scan(); err != nil { return } if block { sentinel = token.BLOCK_END } else { sentinel = token.FLOW_MAPPING_END } node = new(Mapping) node.basicNode = new(basicNode) node.pos = tok.GetStart() node.Pairs = make([]KeyValuePair, 0, 2) pairCount := 0 for err == nil && tok.GetKind() != sentinel { var pair KeyValuePair // Scan key tok, err = parser.scan() if err != nil { return } else if tok.GetKind() != token.KEY { err = errors.New("Expected key") return } pair.Key, err = parser.parseNode() if err != nil { return } // Scan value tok, err = parser.scan() if err != nil { return } else if tok.GetKind() != token.VALUE { err = errors.New("Expected value") return } pair.Value, err = parser.parseNode() if err != nil { return } // Add pair to node if cap(node.Pairs) < pairCount+1 { newPairs := make([]KeyValuePair, pairCount, cap(node.Pairs)*2) copy(newPairs, node.Pairs) node.Pairs = newPairs } node.Pairs = node.Pairs[0 : pairCount+1] node.Pairs[pairCount] = pair pairCount++ // Find closure // Wouldn't it be great if it were always this easy? tok, err = parser.scan() if err != nil { return } else if !(tok.GetKind() == sentinel || (!block && tok.GetKind() == token.FLOW_ENTRY) || (block && tok.GetKind() == token.KEY)) { err = errors.New("Unexpected token in mapping: " + tok.GetKind().String() + " " + tok.String()) return } if tok.GetKind() == token.KEY { parser.unscan(tok) } } return }
func (parser *Parser) parseSequence(block bool) (node *Sequence, err error) { var tok scanner.Token var sep, sentinel token.Token // Discard opening token if tok, err = parser.scan(); err != nil { return } if block { sep, sentinel = token.BLOCK_ENTRY, token.BLOCK_END } else { sep, sentinel = token.FLOW_ENTRY, token.FLOW_SEQUENCE_END } node = new(Sequence) node.basicNode = new(basicNode) node.pos = tok.GetStart() node.Nodes = make([]Node, 0, 2) childCount := 0 // Block sequences have a leading separator if block { tok, err = parser.scan() if tok.GetKind() != sep { err = errors.New("Expected leading block entry token") return } } for err == nil && tok.GetKind() != sentinel { var child Node // Scan child if child, err = parser.parseNode(); err != nil { return } // Add child to node if cap(node.Nodes) < childCount+1 { newNodes := make([]Node, childCount, cap(node.Nodes)*2) copy(newNodes, node.Nodes) node.Nodes = newNodes } node.Nodes = node.Nodes[0 : childCount+1] node.Nodes[childCount] = child childCount++ // Check for separator tok, err = parser.scan() if err != nil { return } else if tok.GetKind() != sep && tok.GetKind() != sentinel { err = errors.New("Unexpected token in sequence: " + tok.String()) return } } return }
func (parser *Parser) parseNodeProperties() (anchor, tag string, err error) { var tok, tagTok scanner.Token if tok, err = parser.scan(); err != nil { return } if tok.GetKind() == token.ANCHOR { anchor = tok.String() if tok, err = parser.peek(); err != nil { return } if tok.GetKind() == token.TAG { tagTok = tok parser.scan() } } else if tok.GetKind() == token.TAG { tagTok = tok if tok, err = parser.peek(); err != nil { return } if tok.GetKind() == token.ANCHOR { anchor = tok.String() parser.scan() } } else { parser.unscan(tok) } if tagTok != nil { tag, err = parser.resolveTag(tagTok.(scanner.TagToken)) } return }