RAMP: Readable Assignment Markup Protocol

what it is

RAMP is a human-friendly data format for configuration files and manifests. It is designed to be easy to read, write, and parse across programming languages.

The syntax is intentionally small: key-value assignments, dotted paths, bullets, inline arrays, and two forms of comments. There is no indentation-based nesting and no multi-line string syntax. If you can read a terminal, you can read RAMP.

no significant whitespace

RAMP does not use tabs or spaces to define structure. Indentation is never meaningful. Leading and trailing whitespace on a line is ignored. Spaces and tabs may appear freely for alignment or readability, but they never change the meaning of a document.

Structure comes only from explicit tokens: keys, assignment operators, bullets, brackets, and commas. You can write every statement starting at column zero, or pad keys for visual columns; both are valid and produce the same result.

why ramp

Most configuration formats force a trade-off. JSON is unambiguous but hostile to humans. YAML is flexible but full of edge cases that trip up both writers and parsers. TOML is clean yet becomes noisy once nesting deepens. RAMP takes a different path: keep the surface language tiny, make every construct explicit, and leave no room for surprising behaviour.

The result is a format you can learn in minutes, audit by eye, and implement without a large dependency.

design goals

exact definitions

Document
A RAMP document is a sequence of lines. Each line may contain at most one statement, optional surrounding whitespace, and an optional line comment. Empty lines and pure comment lines are allowed.

Statement
A statement is either a key-value assignment or a bullet item. Statements form an ordered sequence. Order is part of the abstract document model (see "ordering" below).

Key path
A key path is one or more segments separated by dots (.). Each segment begins with a letter or underscore and may continue with letters, digits, underscores, or hyphens. Example: server.port, db.credentials.user.

Assignment
A key path is followed by either = or : and then a value. Both operators are equivalent. Whitespace around the operator is optional and ignored.

Bullet item
A line that begins with a hyphen followed by whitespace (- ) introduces a bullet. The remainder of the line is either a key-value assignment or a bare value.

Bullets produce an ordered list of items. When a bullet contains a key-value assignment, the item is a single-entry map. There is no additional nesting syntax under a bullet and no native map-as-value construct. Related fields are written as successive bullets with dotted keys, or the application groups them after parsing.

This keeps the grammar flat and the parser simple. The cost is that lists of objects are more verbose than in TOML or JSON, and most applications will post-process bullet sequences into richer structures. That post-processing step is expected and intentional.

Value
A value is either a scalar or an inline array. There is no native syntax for a map as a value. Nested maps are recovered by the host from dotted key paths after parsing. The RAMP document model is therefore a flat ordered sequence of statements; the host language model (nested maps and arrays) is derived from it.

Null
Written as null or ~. These two forms are the only null literals. All other capitalisations are rejected.

Boolean
Written as true or false (lowercase only). Any other capitalisation is a syntax error.

Integer
An optional sign followed by one or more digits: 42, -7, +100.

Float
An optional sign, digits, a decimal point, more digits, and an optional scientific exponent: 3.14, -0.5, 1.5e+10.

Quoted string
Enclosed in double quotes. Supports the escapes \", \\, \n, \t, \r, and \uXXXX (four hex digits). Use quoted strings whenever the value contains spaces or special characters. In practice almost any non-trivial string will be quoted; the unquoted form is reserved for simple identifiers and tokens.

Unquoted string
A single contiguous sequence of characters that does not contain space, tab, newline, or any of the special characters , = : # " [ ] { } ( ). An unquoted string is exactly one token; it cannot contain spaces. If a value needs spaces or any special character, it must be written as a quoted string.

Example: mode = production is valid. mode = production mode is a syntax error (two tokens where one value is expected). Write mode = "production mode" instead.

Inline array
Square brackets containing zero or more values separated by commas. Whitespace around elements and a trailing comma are both allowed: [ "a", "b", "c", ].

Line comment
Starts with # and continues to the end of the line. Everything after the # is ignored.

Block comment
Starts with (# and ends with #). Block comments may appear anywhere whitespace is allowed, including in the middle of a statement: port = (# default #) 8080.

ordering

A RAMP document is an ordered sequence of statements. Parsers must preserve that order in their intermediate representation.

When mapping into a host language:

Applications that care about order (for example, generating output that round-trips) should use an ordered map or keep the original statement list.

multi-line values and large content

RAMP has no multi-line string syntax. Every value lives on a single line. Long text must be written as one quoted string, split into an array of strings that the application joins, or referenced from an external file.

External file references are the recommended way to handle certificates, multi-line scripts, long messages, or any content that does not fit comfortably on one line. A conventional pattern is a string value that the application treats as a path:

tls.cert = "./certs/server.pem"
tls.key  = "./certs/server.key"
script   = "./scripts/deploy.sh"

The format itself does not open or interpret those paths; that is the application's responsibility. This keeps the parser simple and avoids inventing ad-hoc "join this array" conventions inside the language.

The absence of multi-line strings is a deliberate trade-off. It eliminates an entire class of whitespace and chomping rules. RAMP is aimed at configuration and manifests where values are usually short. For documents dominated by long free-form text, a different format is more appropriate.

document model vs host model

The RAMP document model is intentionally flat: an ordered sequence of statements (assignments and bullets). Nested maps and richer object lists are not expressed directly in the syntax. They are recovered by the host after parsing, typically by:

This separation keeps the parser small and the grammar unambiguous. The cost is that the on-disk form is further from the in-memory form than in JSON. That is accepted: the on-disk form prioritises human readability and implementability; the host is free to build whatever structure it needs.

example

a single document that exercises every construct

# line comment at the top

# both assignment operators are equivalent
name        = "edge-proxy"
version     : 1.4.2

# null forms (only null and ~)
cache.ttl    = null
cache.backup = ~

# booleans (lowercase only)
debug       = false
strict      = true

# integers (signed and unsigned)
workers     = 4
retries     = -1
max_conns   = +1024

# floats, including scientific notation
timeouts.connect = 2.5
timeouts.backoff = 1.5e+3
timeouts.jitter  = -0.25

# quoted strings with escapes and spaces
message     = "hello\tworld\n"
path        = "C:\\data\\file.txt"
unicode     = "smile \u263A"
title       = "production mode"

# unquoted strings (single token, no spaces)
mode        = production
region      = us-east-1

# inline arrays (trailing comma allowed)
features    = [ "gzip", "http2", "metrics", ]
ports       = [ 80, 443, 8080 ]
mixed       = [ true, 42, "ok", null, ]

# dotted key paths (nesting recovered by host)
listen.host = 0.0.0.0
listen.port = 8080
db.credentials.user = app
db.credentials.pass = "s3cret"

# external file references for large content
tls.cert    = "./certs/server.pem"
tls.key     = "./certs/server.key"

# block comment mid-statement
log.level   = (# production only #) "warn"
log.path    = (# unused in test #) "/var/log/app.log"

# bullets with key-value pairs
# (flat list of single-entry maps; host may group into objects)
- id     = primary
- url    = "https://api.example.com"
- weight = 10

# bullets with bare values
- "first item"
- second-item
- 42
- true
- ~

# empty lines and trailing comments are fine
end         = true   # done

what ramp is not

implementing ramp

Because the language has no significant whitespace and a very small set of tokens, a conforming parser can be written in a few hundred lines of most languages. Recommended behaviour:

status

RAMP v1.0 is frozen. The language prioritises clarity and implementability. Future revisions will be numbered and remain backward-compatible with documents that validate against the v1.0 rules.