class Bindgen::ConfigReader::Parser

Overview

Pull parser for YAML configuration files, offering conditional branches and access to external dependencies.

If you want to read a configuration see ConfigReader.from_yaml.

This is done by hooking into the pull parser, manually checking for the conditional fields, and applying them accordingly.

Apart from this logic, the configuration file is still valid YAML.

Note: Conditionals and dependencies are only supported in mappings (Hash in Crystal). Any such syntax encountered in something other than a mapping will not trigger any special behaviour.

Condition syntax

YAML documents can define conditional parts in mappings by having a conditional key, with mapping value. If the condition matches, the mapping value will be transparently embedded. If it does not match, the value will be transparently skipped.

Condition keys look like if_X or elsif_X or else. X is the condition, and it looks like Y_is_Z or Y_match_Z. You can also use (one or more) spaces () instead of exactly one underscore (_) to separate the words.

A condition block is opened by the first if. Later condition keys can use elsif or else (or if to open a new condition block).

Note: elsif or else without an if will raise an exception.

Their behaviour is like in Crystal: if starts a condition block, elsif starts an alternative condition block, and else is used if none of if or elsif matched. It's possible to mix condition key-values with normal key-values.

Note: Conditions can be used in every mapping, even in mappings of a conditional. Each mapping acts as its own scope.

Variables

Variables are set by the user of the class (Probably through ConfigReader.from_yaml). All variable values are strings.

Variable names are case-sensitive. A missing variable will be treated as having an empty value ("").

Examples

foo: # A normal mapping
  bar: 1

# A condition: Matches if `platform` equals "arm".
if_platform_is_arm: # In Crystal: `if platform == "arm"`
  company: ARM et al

# You can mix in values between conditionals.  It won't "break" following
# elsif or else blocks.
not_a_condition: Hello

# An elsif: Matches if 1) the previous conditions didn't match
# 2) its own condition matches.
elsif_platform_match_x86: # In Crystal: `elsif platform =~ /x86/`
  company: Many different

# An else: Matches if all previous conditions didn't match.
else:
  company: No idea

# At any time, you can start a new if sequence.
"if today is friday": # You can use spaces instead of underscores too
  hooray: true

Dependencies

To modularize the configuration, you can require ("merge") external yaml files from within your configuration.

This is triggered by using a key named <<, and writing the file name as value: <<: my_dependency.yml. The file-extension can also be omitted: <<: my_dependency in which case an .yml extension is assumed.

The dependency path is relative to the currently processed YAML file.

You can also require multiple dependencies into the same mapping:

types:
  Something: true # You can mix dependencies with normal fields.
  <<: simple_types.yml
  <<: complex_types.yml
  <<: ignores.yml

The dependency will be embedded into the open mapping: It's transparent to the client code.

It's perfectly possible to mix conditionals with dependencies:

if_os_is_windows:
  <<: windows-specific.yml

Errors

An exception will be raised if any of the following occur:

Defined in:

bindgen/config_reader/parser.cr

Constant Summary

MAX_DEPTH = 10

Maximum dependency load depth.

Constructors

Class Method Summary

Instance Method Summary

Constructor Detail

def self.new(content : String | IO, evaluator : ConditionEvaluator, path : String, loader : Bindgen::ConfigReader::Loader = @@loader, depth : Int32 = 1) #

[View source]

Class Method Detail

def self.loader : Loader #

Default loader for dependencies.


[View source]
def self.loader=(loader : Loader) #

Default loader for dependencies.


[View source]

Instance Method Detail

def depth : Int32 #

Parser depth, bounded by MAX_DEPTH


[View source]
def evaluator : ConditionEvaluator #

Evaluator for conditionals.


[View source]
def loader : Loader #

Instance local loader


[View source]
def path : String #

Path to the root YAML file.


[View source]