An INI schema for validating INI schemas
Written by Alexander Nicholi https://nich.fi/
Copyright © 2025 Aquefir Consulting LLC https://aquefir.co/
Released under the Creative Commons Attribution-NoDerivatives 3.0
Unported license
You are free to:
- Share — copy and redistribute the material in any medium or format for any purpose, even commercially.
The licensor cannot revoke these freedoms as long as you follow the license terms.
Under the following terms:
- Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
- NoDerivatives — If you remix, transform, or build upon the material, you may not distribute the modified material.
No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits.
Read the licence deed and the full legal code on the Web at https://creativecommons.org/licenses/by-nd/3.0/.
So you want to understand INI schemas.
First, some basic rules:
- All keys and values are not whitespace-stripped in any direction.
- This makes INIs behave like Hex Workshop TBL files; for
example, a line
bla===is a key namedblawith a value of==.
- This makes INIs behave like Hex Workshop TBL files; for
example, a line
- Coterminus with rule 1, equal signs are not possible in keys.
- Likewise, square brackets are also not possible in section names.
- All regular expression parsing is done to the substrings in question; this implies newline characters cannot appear in test strings for said regular expressions.
- INIs do not have ‘data types’, ergo there are only strings here.
- No concept of ‘nesting’ is provided with sections or keys. There is ONE level of hierarchy: sections and their entries.
- This is a schema for parsing INI files, not lexing them; concerns regarding text encoding or newline styles are out of scope here.
- INI schema parsers should at a minimum support the PCRE subset
provided by the Super Light Regular Expressions Library.
- A declarative list of these syntax features is in the project README; the project can be found on the Web at https://github.com/aquefir/slre.
With all of that said, INI schemas take a simple approach that makes real world usage of them fairly self-evident, even though it makes this schema (the ‘meta-schema’) read a bit like performance art.
INI schemas use section names with some special formatting rules to contain their valid form, key names, and characteristics. This is elucidated mechanistically in this meta-schema, but in English:
- All schemas must have two global key-value entries named
caseinsensandmscommentswhich decides whether section names and key names are treated case-insensitively and whether semicolons are used instead of hashes to start line comments, respectively.- This is provided to make Win32 API compatibility tractable.
- Every section without a colon describes a section formula.
- Section formulae have one key-value entry called
valwhere a regular expression constrains the possible values inside the square brackets.
- Section formulae have one key-value entry called
- Every section with a colon describes an entry formula, where the
portion before the colon refers to an existing section formula, and
the portion after the colon denotes the literal key name.
- Entry formulae have one key-value entry called
valwhere a regular expression constrains the possible values on the other side of the equal sign from the key name.
- Entry formulae have one key-value entry called
- Entry formulae may also be suffixed with a plus sign
+; this means they may appear under the same name multiple times in a given INI file, but are required to appear at least once. - Entry formulae may also be suffixed with an asterisk
*; this means they may appear under the same name multiple times in a given INI file, and are also optional and so may be omitted. - Entry formulae may also be suffixed with a question mark
?; this means they are optional and so may be omitted. - Sections themselves can be marked as optional with a question mark
?, marked to repeat with a plus sign+, or marked as optional and repeating with an asterisk*in the same way that entry formulae are. - Every section with a colon where the left hand side is empty, ergo
they begin with the string
[:, are entry formulae for the global section.- The ‘global section’ is simply the list of key-value pairs that comes before any sections appear in the INI file.
- Only line comments are allowed.
- If hashes or semicolons appear after a value has started, they are considered part of the value.
- If hashes or semicolons appear on a section line or before an equal sign after a value has started, it is an error.
- Line comments MAY be preceded by whitespace, ergo a line of the
form
# commentis valid.
It’s best to understand the left hand side of an entry formula as a kind of identifier that one uses by reference in their schema design. The right hand side constitutes a literal and is used as-is to find and validate keys, but in the case of section formulae where there is no right hand side, the contents are still an identifier and don't show up in the files themselves.
While INIs themselves are typically found with the .ini extension,
schemas should use the .inf extension instead, since generally
they do constitute ‘setup information’ and besides being
treated synonymously by virtually all tools give a nice sense of
contrast to denote the fact that they are schemas. Therefore, this file
has a canonical name of schema.inf. 😊
caseinsens=0
mscomments=0
[:caseinsens]
val=^[01]$
[globalsection]
val=^:[^:\+\*\?]+[\+\*\?]?$
[globalsection:val]
val=^.+$
[section]
val=^[^:\+\*\?]+[\+\*\?]?$
[section:val]
val=^.+$
[reqentry]
val=^[^:\+\*\?]+:[^:\+\*\?]+$
[reqentry:val]
val=^.+$
[optentry]
val=^[^:\+\*\?]+:[^:\+\*\?]+\?$
[optentry:val]
val=^.+$
[multientry]
val=^[^:\+\*\?]+:[^:\+\*\?]+\*$
[multientry:val]
val=^.+$GitHub Gist ID: 05cae747b0d3a8928c85c12d65187ff3