Login
rsconf.md at tip
Login

File docs/rsconf.md from the latest check-in


# RSConf - A data format somewhere between JSON and Hjson

Author: Remilia Scarlet<br/>
Version: 1.3.1<br/>
Last Updated: 31 July 2026

## Introduction

RSConf has a few more features than JSON that make it nicer for config files,
such as comments, not needing commas, and unquoted keys.  But it is less strict
and has fewer features than Hjson to keep parsing simple.

It was created to fill a niche and scratch an itch for a nice, easy-to-use
config format that doubles as a data serialization format.  JSON is nice and
(usually) easy to visually parse as a human, but is too strict with its syntax,
and doesn't have comments.  YAML is nice, but has far too many bells and
whistles, leading to all sorts of strange edge cases, and a large space for
possible security problems.  TOML is ugly, and I just don't like it.  Hjson is
nice, but has a few too many unnecessary features for my liking, and is a bit
too flexible.  Thus, RSConf was born to fill the hole left by these other
formats.

As a high-level overview, RSConf is like JSON, but:

* Keys don't need quoting if they do not contain spaces.
* Commas don't need to come after values/key-value pairs unless there are
  multiple values/key-value pairs on the same line.
* Top-level braces (`{` and `}`) can be omitted if the top-level is an object.
* Integers and floats are differentiated.
* Integers can be in hex, octal, or binary.  Floats can be in decimal or
  "scientific notation" (and accept either `e` or `d` for their character).
* The null value is called `nil`.
* Comments are allowed and use semicolons (`;`)
* Explicit minimum limits for integers and floats.
* Stricter whitespace.

It is also a lot like hsjon, except:

* All strings are multi-line strings; no separate syntax.
* No quoteless strings.
* Integers can be in hex, octal, or binary.  Floats can be in decimal or
  "scientific notation" (and accept either `e` or `d` for their character).
* The null value is called `nil`.
* Comments are allowed and use semicolons (`;`)
* No multi-line comments.
* Explicit minimum limits for integers and floats.
* Slightly stricter whitespace.

Some well-formatted example RSConf data:

```
;;;;
;;;; Example Document
;;;;

some-object: {
  values: [ 1, 2, 3 ] ;; Recommended syntax for short arrays

  ;; Better syntax for larger arrays, or ones with long values.
  values-2: [
    "foo"
    "bar"
    "baz"
  ]

  name: "test"
  sub-obj: {
    id: 1, ;; Comma here is optional
    enabled: false ;; or `true`
    something-else: nil ;; Null values are represented with `nil`
  }
}
```

### Notation Used

This spec document uses Common Lisp-style hexadecimal/octal/binary numbers.
This means #xA7 instead of 0xA7, #o25 instead of 025, and #b1011 instead of
0b1011.

## Specification

The name of the format is RSConf, with that capitalization.  It is pronounced
"Arr-Ess-Konf" and stands for Remilia Scarlet's Config Format.

### Encoding

Files *MUST* be UTF-8 encoded without a byte-order marker.  No other encoding is
valid.  The two recommended file extensions are .rsconf and .rsc

The following Unicode codepoints are considered whitespace (note the absence of
#x0D, Return): #x0A (newline), #x20 (space), and #x09 (tab).  Other UTF-8
codepoints that are normally considered whitespace are not allowed, except
within string values.  Encountering other whitespace codepoints outside of a
quoted string value MUST signal an error.  Additionally, it is highly
recommended, but not required, that you use spaces (#x20) instead of tabs (#x09)
for RSConf files.

### Line Endings

Line endings must be "Unix-Style", meaning only the newline character (UTF-8
character #x0A).  Any return character (#x0D) or page/form feed character (#x0C)
outside of a string must raise an error and must not be counted as whitespace.
All other valid whitespace characters, as defined in the Encoding section above,
are counted as whitespace and ignored outside of strings.

### Comments

There are only single-line comments, which always start with one or more
semicolons and continues to a newline (#x0A).  Lisp-style comments, where the
number of semicolons vary according to the nesting depth, is recommended.
Comments **MUST NOT** contain parsing directives or similar.  Conforming
implementations **MUST NOT** allow parsing directives, or they cannot claim to
be conforming to the RSConf specification, nor claim to support RSConf.  RSConf
explicitly disallows any sort of data or metadata within comments that can be
used during or after parsing.  Comments are there for human eyes only.

### Scalar Values

There are five types of scalar values: integers, floats, strings, booleans, and
the null value.

Integer values can be in decimal (12345), hexadecimal (#xA7, #xDEADBEEF), octal
(#o64, #o23), or binary (#b1100101, #b1011).  Non-decimal values must start with
an ASCII `#` (#x23) followed by a letter.  This letter indicates the radix.  The
entire value, regardless of radix (or lack of radix), continues to the end of
the line, a comma (#x2C), a comment character, or other whitespace as defined in
the Encoding section above.

There are restrictions on the allowed characters in integer values, depending on
the radix.

* For decimal, there must not be a radix.  The value must only contain ASCII `0`
  through `9`.
* For binary, the radix must be indicated with the ASCII letter `b` or `B` (#x62
  or #x42).  The value must only contain ASCII `0` or `1`.
* For octal, the radix must be indicated with the ASCII letter `o` or `O` (#x6F
  or #x4F).  The value must only contain ASCII `0` through `7`.
* For hexadecimal, the radix must be indicated with the ASCII letter `x` or `X`
  (#x78 or #x58).  The value must only contain ASCII `0` through `9`, and either
  ASCII `A` through `F` or `a` through `f` (or a mixture of these ranges).
* There may be a sign character, `+` or `-` (#x2B or #x2D), immediately
  preceding the numeric literal to indicate a positive or negative value.  No
  whitespace is permitted between the sign character and literal.

Implementing parsers must support integer values that can be represented as
64-bit signed integers.  Greater limits are allowed.

Floats can only use decimal or "scientific notation".  Decimal format starts
with a number, then continues until a period (`.`, #x2E) is reached.  After that
may be additional decimal numbers.  The float continues to the end of the line,
a comma, a comment character, or other whitespace as defined in the Encoding
section above.  Only the ASCII digits are allowed (#x30 through #x39) for the
digits.  There is no support for floats using any other radix.

Floats can use "scientific notation" in the form `X.Ye+Z` or `X.Ye-Z` or `X.YeZ`
if desired.  This form uses the ASCII letter `E` (#x45) or `e` (#x65).  The
ASCII letter `D` (#x44) or `d` (#x64) can be used in place of `E` or `e` as
well.  This is done for compatibility with Common Lisp.  Implementing parsers
must support values that can be represented with *at least* 50 bits of
mantissa/significand precision and a signed exponent size of at least 8 bits;
larger significand and exponent sizes are allowed.  These minimums were
specifically chosen so that they can be satisfied by both a IEEE 754
double-precision floating point format (binary64), and the minimum capabilities
of a Common Lisp `DOUBLE-FLOAT` as [defined by the Common Lisp
Hyperspec](https://www.lispworks.com/documentation/HyperSpec/Body/t_short_.htm).

Deserialization of RSConf data may still place stricter/looser restrictions on
the integer and float values as-needed.  For example, deserialization code can
place a constraint on an integer key so that it must contain an 8-bit unsigned
integer.  But they must allow for values up to at least the minimum limits
described above.

String values must be quoted.  They start with a double quote (character #x22)
and continue to another double quote.  This means all strings may span multiple
lines (i.e.  "multi-line" strings).  There is not a separate syntax for strings
spanning multiple lines.

The backslash character (`\`, #x5C) is used for escaping characters in a string.
Double quotes that appear within strings must be escaped, e.g. the string
`"hello \"world\""`.

Unicode codepoints may optionally be escaped with `\u{X}`, where `X` is always
in hexadecimal and is the Unicode code point.  It must be at least one hex digit
long.

Given this, the only special escapes that do anything within strings are for
double-quotes (`\"`) and for Unicode codepoints (`\u{X}`).  All other escapes
simply produce the character they escape, e.g. `"foo\abar"` results in the same
string as `"fooabar"`.

Strings can contain any type of UTF-8 whitespace, not just #x0A (newline), #x20
(space), and #x09 (tab).

Booleans are the symbols `true` or `false`; these are case-sensitive and must be
lower-case.

The null value is the symbol `nil`.  This is also case-sensitive and must be
lower-case.

### Composite Values

There are two types of composite values in RSConf: objects and arrays.

An object starts with an open brace (`{`, character #x7B) and ends with a close
brace (`}`, character #x7D).  Within these braces are zero or more key-value
pairs.

Arrays start with an open bracket (`[`, character #x5B) and end with a close
bracket (`]`, character #x5D).  Within these brackets are zero or more values
(never key-value pairs).

### Keys and Values

Keys can be quoted or unquoted.  For an unquoted key, the key name starts with a
non-whitespace character and continues until whitespace or a colon (character
#x3A) is reached.  "Whitespace" here means whitespace as defined in the Encoding
section above.  A newline (#x0A) is **not** permitted in an unquoted key between
the key name and a colon; a colon must appear on the same line as the unquoted
key name it terminates.  All whitespace before an unquoted key name is ignored.
All whitespace except for the newline (#x0A) after the key name and before the
colon is ignored.

Quoted keys are treated like string scalars, and thus all characters within them
are accepted.  All whitespace, as defined in the Encoding section above, that
comes before the opening double-quote is ignored.  All whitespace except for
newlines (#x0A) after the closing double-quote is ignored.  Quoted keys
**cannot** have a newline character between its ending quote and the colon.

Key names cannot be an empty string (`""`).  Key names are always
case-sensitive.

It is recommended that you use unquoted keys whenever possible.  Lowercase
skewer-case names (e.g. `key-name`, `this-is-a-key`) that don't need quoting are
highly recommended, but not required.  Underscores in key names are allowed, but
highly discouraged.

The value associated with the key comes after the colon character.  All
whitespace (as defined in the Encoding section above) after the colon and before
the value is ignored.

Values, whether as part of a key-value pair or as a value within an array, may
optionally be terminated with a comma (character #x2C).  This comma **MUST** be
on the same line as the value it terminates; all whitespace as defined in the
Encoding section above, except for a newline (character #x0A), is ignored
between the value and a comma.

As an alternative, multiple key-value pairs and values may exist on the same
line in both objects and arrays, but **MUST** be separated by commas.  If no
additional keys come after the final value, then the trailing comma (character
#x2C) is optional.  To put this another way, multiple key-value pairs within an
object, or multiple values within an array, may appear on the same line, but
adjacent items MUST be separated by commas. A trailing comma after the final
item is optional.

Empty values, and multiple commas in succession (regardless of whitespace
between them), are not allowed and must signal an error.

### Documents

The top-level is called the "document".  A document must consist of a single
object or a single array.  When a document consists of an object, then the
top-level braces (`{` and `}`) may optionally be omitted and it is assumed all
key-value pairs are part of the top-level object.

Duplicate keys (more than one key with the same name at the same level) are
allowed, but later keys override earlier keys.  It's highly recommended that a
warning be presented in some way when duplicate keys at the same level are
detected, but this is not required.

## Changelog

* v1.3.1, 31 July 2026: No significant changes.  Clarified definitions of
  numeric literals and floats.  Fixed some hex values.
* v1.3, 12 Mar 2026: Clarified the characters allowed in integers, the radix for
  integers, and floats.  Clarified that mixed-case hexadecimal is allowed.
* v1.2, 31 Dec 2025: Whitespace outside of string values is now more strictly
  defined.  Specifically, only ASCII spaces, newlines, and tabs are allowed.
* v1.1, 25 Sep 2025: Changed how escapes work so that it matches other
  languages.