How to Parse YAML from Files or Input Streams with yaml-cpp

You can parse YAML in yaml‑cpp using the header‑only convenience functions YAML::Load, YAML::LoadFile, and YAML::LoadAll, which internally instantiate a Parser and NodeBuilder to transform any std::istream or file into a tree of YAML::Node objects.

The yaml‑cpp library (available at jbeder/yaml‑cpp) provides a high‑level C++ API for consuming YAML documents. Whether you are reading from strings, files, or arbitrary input streams, the library exposes a concise interface that hides a sophisticated pipeline of lexical scanning, directive processing, and node construction. Understanding this architecture helps you choose the right entry point for your specific use case.

The Internal Parsing Pipeline

When you call any of the public Load* functions, the library creates a Parser object that orchestrates the conversion from raw text to structured data. The flow through src/parser.cpp follows four distinct phases:

  1. Stream initialization – The Parser::Parser(std::istream&) constructor (defined in src/parser.cpp at line 22) initializes a Scanner over the supplied stream and prepares a fresh Directives container to track %YAML and %TAG directives.
  2. Directive processing – Parser::ParseDirectives (line 56) consumes any leading directives and stores them in the Directives object.
  3. Document parsing – Parser::HandleNextDocument (line 27) instantiates a SingleDocParser that walks the token stream, generates parsing events, and feeds them to an EventHandler.
  4. Node construction – A NodeBuilder receives the events and assembles the final Node tree, returning the root node to the caller.

This design deliberately separates lexical scanning (Scanner), directive handling (Directives), document parsing (SingleDocParser), and node construction (NodeBuilder), making the internals extensible while keeping the public API simple.

Public API Functions for Loading YAML

The convenient entry points are implemented in src/parse.cpp and declared in include/yaml-cpp/parser.h. Each function handles a specific source type:

  • YAML::Load(std::istream&) – The core entry point that constructs a Parser, attaches a NodeBuilder, and invokes HandleNextDocument to return a single Node.
  • YAML::Load(const std::string&) – Wraps the string in a std::stringstream and forwards to the stream overload.
  • YAML::Load(const char*) – Identical to the string version for C‑string literals.
  • YAML::LoadFile(const std::string&) – Opens an std::ifstream, throws YAML::BadFile on failure, and forwards to Load(stream).
  • YAML::LoadAll(std::istream&) – Parses multiple YAML documents from a single stream, looping HandleNextDocument until exhaustion and collecting each root node into a std::vector<Node>.
  • YAML::LoadAllFromFile(const std::string&) – Combines file opening with multi‑document parsing.

These functions are defined at lines 12, 17, 22, 32, 50, and 65 of src/parse.cpp respectively.

Parsing a Single Document from a File

For configuration files or single‑document inputs, use YAML::LoadFile. This function handles stream lifetime internally and throws YAML::BadFile if the file cannot be opened.

#include <yaml-cpp/yaml.h>
#include <iostream>

int main() {
    try {
        YAML::Node config = YAML::LoadFile("config.yaml");
        std::cout << "Host: " << config["host"].as<std::string>() << "\n";
        std::cout << "Port: " << config["port"].as<int>() << "\n";
    } catch (const YAML::BadFile& e) {
        std::cerr << "Cannot open file: " << e.what() << "\n";
    } catch (const YAML::ParserException& e) {
        std::cerr << "YAML error: " << e.what() << "\n";
    }
}

Parsing Multiple Documents from a String

YAML streams may contain multiple documents separated by ---. The YAML::LoadAll family returns a std::vector<YAML::Node> containing each document’s root node.

#include <yaml-cpp/yaml.h>
#include <iostream>

int main() {
    const char* yaml = R"(---
name: Alice
---
name: Bob
---)";

    std::vector<YAML::Node> docs = YAML::LoadAll(yaml);
    for (std::size_t i = 0; i < docs.size(); ++i) {
        std::cout << "Doc " << i << " name: " << docs[i]["name"].as<std::string>() << "\n";
    }
}

Streaming Parsing from Standard Input

Because YAML::Load accepts any std::istream&, you can parse directly from std::cin, a std::stringstream, or a custom stream implementation without intermediate buffering.

#include <yaml-cpp/yaml.h>
#include <iostream>

int main() {
    std::cout << "Enter YAML (Ctrl-D to finish):\n";
    YAML::Node root = YAML::Load(std::cin);
    
    if (root["greeting"]) {
        std::cout << "Greeting: " << root["greeting"].as<std::string>() << "\n";
    }
}

Summary

  • High‑level convenience – YAML::Load, YAML::LoadFile, and YAML::LoadAll in src/parse.cpp provide the primary interface for parsing YAML from files or input streams.
  • Internal architecture – The library constructs a Parser (in src/parser.cpp) that drives a Scanner and SingleDocParser, feeding events to a NodeBuilder to produce the final Node tree defined in include/yaml-cpp/node/node.h.
  • Flexible input – All public functions accept std::istream&, allowing seamless integration with files, strings, and standard input.
  • Error handling – Expect YAML::BadFile for filesystem errors and YAML::ParserException for malformed YAML content.

Frequently Asked Questions

How do I parse YAML from a string instead of a file?

Use YAML::Load(const std::string&). According to the implementation in src/parse.cpp (line 12), this overload creates a std::stringstream internally and forwards it to the core Load(std::istream&) function, so you do not need to manually wrap your string.

What is the difference between Load and LoadAll?

YAML::Load parses exactly one document from the stream and returns a single Node, whereas YAML::LoadAll continues reading after document boundaries (---) and returns a std::vector<Node> containing every document found in the stream. The implementation in src/parse.cpp (lines 50–65) shows that LoadAll simply loops HandleNextDocument until the scanner reports no more content.

Can I parse from a custom C++ stream class?

Yes. Because YAML::Load takes a std::istream& reference (as seen in src/parse.cpp line 22), any class inheriting from std::istream—including std::stringstream, std::ifstream, or your own custom implementation—works transparently with the parser.

What exceptions should I catch when loading a file?

Catch YAML::BadFile (thrown in LoadFile at src/parse.cpp line 32 when the std::ifstream fails to open) and YAML::ParserException (thrown by the Parser or SingleDocParser when encountering invalid YAML syntax). Catching std::exception will also handle these cases, but specific catches allow more granular error reporting.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →