Version: 1.0
Status: Draft
Date: 2025-01-14
- Overview
- Design Goals
- Grammar
- Lexical Analysis
- Data Types
- String Literals
- Comments
- Arrays
- Objects
- Whitespace and Formatting
- Reserved Words
- Path Notation
- Duplicate Keys
- Complete Examples
- Parsing Algorithm
- Error Handling
- File Format
- Implementation Guidelines
- Security Considerations
- Performance Requirements
- Validation and Schema
- Comparison to Other Formats
- Migration Guide
- Future Considerations
- References
VIBE (Values In Bracket Expression) is a hierarchical configuration file format designed to optimize both human readability and machine parsing performance. It combines the visual clarity of bracket-delimited structures with minimal syntax overhead, making it ideal for configuration files, data serialization, and human-editable structured data.
VIBE addresses common pain points in existing configuration formats: it eliminates YAML's indentation sensitivity, removes JSON's syntactic overhead (trailing commas, excessive quotes), and provides clearer visual hierarchy than INI files while maintaining simplicity.
- Readable: Structure is immediately apparent through visual inspection, with clear delimiters and minimal noise
- Writable: Simple syntax rules make hand-editing natural and error-resistant
- Parseable: Deterministic LL(1) grammar enables single-pass parsing with O(n) complexity
- Unambiguous: Each data structure has exactly one canonical representation
- Efficient: Minimal memory overhead during parsing and low implementation complexity
The structure of data should be instantly recognizable through visual inspection alone. Nested objects use braces {} that create clear visual boundaries, while arrays use brackets [] for unambiguous collection identification. This bracket-based syntax provides immediate structural context without requiring counting indentation levels or tracking implicit scope.
VIBE uses exactly 6 core token types (identifiers, strings, numbers, booleans, braces, brackets), making it one of the simplest structured formats to learn and implement. The absence of mandatory commas, semicolons, or colons reduces syntactic noise and simplifies both human editing and parser implementation.
Each data structure has exactly one canonical representation in VIBE. This eliminates formatting debates, ensures consistent machine generation, and enables reliable diffing and version control. The deterministic grammar means there are no edge cases or surprising interpretations.
The grammar enables single-pass, O(n) parsing using a simple state machine. No backtracking, unbounded lookahead, or complex grammar rules are required. This design choice ensures predictable performance characteristics and low memory overhead, making VIBE suitable for resource-constrained environments.
Clear, deterministic type inference rules ensure that values are consistently interpreted across all implementations. Numbers, booleans, and strings are unambiguously distinguished through syntax, eliminating the need for explicit type annotations while maintaining type safety.
The syntax is optimized for human reading and writing. Whitespace is non-significant (except as token separation), comments are allowed anywhere, and unquoted strings reduce visual clutter for simple values. Error messages should provide clear context and actionable guidance for resolution.
config = { statement } ;
statement = ( assignment | object | array | comment ) [ comment ] newline ;
assignment = identifier ( scalar_value | object | array ) ;
object = identifier "{" { statement } "}" ;
array = identifier "[" [ value_list ] "]" ;
value_list = scalar_value { ( whitespace | newline ) scalar_value } ;
scalar_value = string | number | boolean | identifier ;
comment = "#" { any_char - newline } ;
identifier = ( letter | "_" ) { letter | digit | "_" | "-" } ;
string = quoted_string | unquoted_string ;
quoted_string = '"' { char | escape_sequence } '"' ;
unquoted_string = ( letter | digit | "_" | "-" | "." | "/" | ":" )
{ letter | digit | "_" | "-" | "." | "/" | ":" } ;
number = [ "-" ] ( integer | float ) ;
integer = digit { digit } ;
float = digit { digit } "." digit { digit } ;
boolean = "true" | "false" ;
escape_sequence = "\" ( '"' | "\" | "n" | "t" | "r" | "u" hex_digit hex_digit hex_digit hex_digit ) ;
VIBE recognizes exactly 5 token types:
- IDENTIFIER -
[a-zA-Z_][a-zA-Z0-9_-]* - STRING - Quoted or unquoted text
- LEFT_BRACE -
{ - RIGHT_BRACE -
} - LEFT_BRACKET -
[ - RIGHT_BRACKET -
]
key value
- Key must be a valid identifier
- Value continues until end of line or special character
- Multiple words in value require quotes
name {
statements...
}
- Opens a new scope with nested statements
- Can contain assignments, objects, or arrays
- Must be closed with matching
}
name [value1 value2 value3]
or multi-line:
name [
value1
value2
value3
]
- Space or newline separated items
- No commas or other separators
- Must be closed with matching
]
The lexer processes the input character by character, maintaining state to determine token boundaries:
- Whitespace Handling: Spaces, tabs, and newlines are used as separators but are not significant tokens
- Comment Recognition:
#starts a comment that continues to end of line - String Recognition: Quoted strings begin with
"and end with matching" - Identifier Recognition: Alphanumeric characters, underscores, and hyphens
- Operator Recognition: Braces and brackets are single-character tokens
ALPHA = [a-zA-Z]
DIGIT = [0-9]
ALNUM = ALPHA | DIGIT
IDENT_START = ALPHA | "_"
IDENT_CHAR = ALNUM | "_" | "-"
UNQUOTED_CHAR = [0x21-0x7E] - [{}[]#] - WHITESPACE
WHITESPACE = " " | "\t" | "\r"
NEWLINE = "\n"
# Valid identifiers
server
database_host
ssl-enabled
_private
config2
# Valid unquoted strings
localhost
192.168.1.1
/usr/local/bin
example.com:8080
# Invalid identifiers (would be treated as strings)
2servers # starts with digit
server.host # contains dot (would be unquoted string)
配置 # Unicode not allowed in identifiers
VIBE supports 5 fundamental data types with automatic type inference based on syntax patterns:
Type determination follows a strict precedence order to ensure unambiguous interpretation:
function inferType(value):
stripped = strip_whitespace(value)
# Check in order of specificity
if stripped matches /^-?\d+$/
return INTEGER
else if stripped matches /^-?\d+\.\d+$/
return FLOAT
else if stripped == "true" or stripped == "false"
return BOOLEAN
else if starts_with(stripped, '"') and ends_with(stripped, '"')
return STRING (quoted, with escape sequence processing)
else
return STRING (unquoted, literal value)
Key Points:
- Type inference is deterministic and order-independent
- No ambiguity between types - each syntax pattern maps to exactly one type
- Implementations must follow this exact algorithm for compatibility
Definition: A sequence of digits optionally preceded by a minus sign, representing whole numbers.
Syntax Pattern: -?[0-9]+
Range: Implementations MUST support at least 64-bit signed integers (−2^63 to 2^63−1). Values outside this range MAY be rejected or promoted to arbitrary precision integers.
Examples:
count 42
negative -17
zero 0
large 9223372036854775807
min_value -9223372036854775808
Rules:
- Leading zeros are allowed but discouraged (e.g.,
007is valid but should be written as7) - No thousands separators (commas, underscores, or spaces)
- Plus sign prefix is not supported (use unsigned form)
- Scientific notation is not supported for integers
Invalid Syntax:
with_comma 1,000 # Commas not allowed
with_space 1 000 # Spaces not allowed
with_plus +42 # Plus sign not supported
hex 0xFF # Only decimal notation supported
Definition: A sequence of digits with exactly one decimal point, representing real numbers.
Syntax Pattern: -?[0-9]+\.[0-9]+
Range: Implementations MUST support at least IEEE 754 double precision (64-bit floating point).
Examples:
pi 3.14159
negative -0.5
zero 0.0
small 0.001
precise 123.456789012345
Rules:
- Decimal point is REQUIRED (distinguishes from integers)
- At least one digit must appear on both sides of decimal point
- Scientific/exponential notation is NOT supported in VIBE 1.0
- Leading zeros after decimal are significant (0.001 ≠ 0.1)
Special Values: Implementations MAY support these unquoted string literals with special float semantics:
inforInfinity- positive infinity-infor-Infinity- negative infinitynanorNaN- not a number
Invalid Syntax:
no_decimal 42 # Missing decimal point (this is an integer)
scientific 1.23e10 # Scientific notation not supported
trailing_dot 42. # Requires digits after decimal
leading_dot .42 # Requires digits before decimal
Definition: Logical true/false values represented by the exact literals true or false.
Syntax: Lowercase keywords only: true | false
Case Sensitivity: VIBE is case-sensitive for boolean literals. True, TRUE, False, FALSE, or any other capitalization variants are treated as unquoted strings, not booleans.
Examples:
enabled true
debug false
production true
maintenance_mode false
Common Mistakes:
enabled True # This is a STRING "True", not boolean
debug FALSE # This is a STRING "FALSE", not boolean
active yes # This is a STRING "yes", not boolean
disabled no # This is a STRING "no", not boolean
Design Rationale: Using only lowercase true and false eliminates ambiguity and aligns with most programming languages (JavaScript, Python, JSON). Alternative boolean representations (yes/no, on/off, 1/0) can be used as strings and interpreted by application logic if needed.
Strings represent textual data and come in two forms: quoted and unquoted.
Unquoted strings provide a cleaner syntax for simple identifiers and values without spaces or special characters.
Syntax: Any sequence of non-whitespace, non-special characters
Valid Characters: Letters, digits, and the characters: _, -, ., /, :, @
Termination: Unquoted strings end at:
- Whitespace (space, tab, newline)
- Structural characters (
{,},[,]) - Comment start (
#)
Restrictions:
- MUST NOT match the pattern of a number (integer or float)
- MUST NOT be exactly
trueorfalse(reserved for booleans) - MUST NOT contain spaces or special characters that could create ambiguity
- Unicode characters beyond ASCII require quoted strings
Examples:
hostname server1.example.com
path /usr/local/bin
email admin@example.com
version 2.1.0-beta
identifier user_id_123
url_path /api/v1/users
When to Quote: Use quoted strings when:
- Value contains spaces
- Value matches a number pattern but should be a string
- Value is
trueorfalsebut should be a string - Value contains special characters (
#,{,},[,]) - Value contains Unicode characters beyond ASCII protocol https url https://api.example.com/v1 email user@example.com port_name 8080 # String, not number, because of underscore password s3cr3t!@#$%^&*() connection_string postgres://user:pass@host:5432/db
language "中文" protocol "сервер" port "データベース"
config_with_braces "{"key": "value"}" array_syntax "[1, 2, 3]" comment_text "This contains # a hash"
#### Quoted Strings
**Delimiters**: Double quotes `"`
**Required When**:
- Value contains whitespace
- Value contains special characters: `# { } [ ]`
- Value has leading/trailing whitespace
- Value contains Unicode (non-ASCII) characters
- Value would otherwise be ambiguous
**Examples**:
message "Hello, world!" path_with_spaces "/Program Files/App" special "value with # comment character" empty "" just_spaces " " unicode_string "你好 世界" # Unicode requires quotes mixed_special "配置 # with comment char"
### Array Type
**Definition**: Ordered collection of scalar values (integers, floats, booleans, strings)
**Syntax**: Values separated by whitespace, enclosed in `[]`
**Restrictions**:
- Arrays can only contain scalar values (no nested objects or arrays)
- All values are parsed independently as primitives
- Use named objects instead of object arrays for complex data
**Examples**:
numbers [1 2 3] strings [hello world foo] mixed [42 "hello" true 3.14] hosts [server1.com server2.com server3.com] flags [enabled debug verbose]
**Invalid** (objects in arrays not allowed):
servers [ { host server1.com port 8080 } ]
**Use this pattern instead**:
servers { primary { host server1.com port 8080 } secondary { host server2.com port 8081 } }
### Object Type
**Definition**: Unordered collection of key-value pairs
**Syntax**: Statements enclosed in `{}`
**Examples**:
config { host localhost port 8080 }
## String Literals
### Escape Sequences
Quoted strings support the following escape sequences:
| Escape | Character | Unicode | Description |
|--------|-----------|---------|-------------|
| `\"` | `"` | U+0022 | Double quote |
| `\\` | `\` | U+005C | Backslash |
| `\n` | | U+000A | Newline (LF) |
| `\r` | | U+000D | Carriage return (CR) |
| `\t` | | U+0009 | Horizontal tab |
| `\uXXXX` | | U+XXXX | Unicode codepoint (4 hex digits) |
### Unicode Support
- Files must be valid UTF-8
- Unicode characters can appear directly in quoted strings and comments only
- `\uXXXX` escape sequences support Basic Multilingual Plane
- No support for surrogate pairs or `\UXXXXXXXX` sequences
- **Identifiers and unquoted strings are strictly ASCII-only** for simplicity and performance
**Examples**:
greeting "Hello, world! 🌍" path "C:\Users\Name\Documents" escaped "She said "Hello"" unicode "Emoji: \u1F44D" multiline "Line 1\nLine 2\nLine 3"
configuration "aplicación" # ASCII identifier, quoted Unicode value settings "сервер" config "データベース" language english # ASCII identifier and unquoted ASCII value language "español" # ASCII identifier, quoted Unicode value
### String Parsing Rules
1. **Unquoted String Parsing**:
- Starts with first non-whitespace character
- Continues until whitespace, special character, or end of line
- Cannot contain `# { } [ ]`
- ASCII-only: `[a-zA-Z0-9_-./:]`
2. **Quoted String Parsing**:
- Starts with `"`
- Continues until matching `"` (not escaped)
- Must be closed on same logical line
- Processes escape sequences
3. **Empty Strings**:
- Only possible with quoted strings: `""`
- Unquoted empty values are not allowed
## Comments
### Syntax
Comments start with `#` and continue to the end of the line.
key value # This is an inline comment
### Rules
1. **Placement**: Comments can appear anywhere except inside quoted strings
2. **Preservation**: Comments are not preserved in the parsed data structure
3. **Escaping**: `#` inside quoted strings is literal, not a comment start
4. **Unicode**: Comments can contain any valid UTF-8 characters
### Examples
app { name "My App" # Application display name version 1.0 # Semantic version
}
database {
host localhost # Development database port 5432 # PostgreSQL default port name "app_db" # Database name with # character }
### Comment Best Practices
1. Use comments to explain non-obvious configuration choices
2. Include units for numeric values when relevant
3. Document valid value ranges or formats
4. Explain the purpose of complex nested structures
5. Feel free to add encouraging comments - good vibes are contagious!
timeout 30 # seconds - just enough time to grab a coffee ☕ retries 3 # third time's the charm!
## Arrays
### Syntax Variants
#### Inline Arrays
ports [8080 8081 8082] hosts [server1 server2 server3]
#### Multi-line Arrays
servers [ prod.example.com staging.example.com dev.example.com ]
#### Mixed Format (Not Recommended)
mixed [item1 item2 item3 item4]
### Array Content Rules
1. **Type Mixing**: Arrays can contain values of different types
2. **Nesting**: Arrays cannot directly contain other arrays or objects
3. **Empty Arrays**: `[]` represents an empty array
4. **Whitespace**: Items separated by any amount of whitespace
5. **Comments**: Comments can appear between array items
### Examples
numbers [1 2 3 4 5] strings [apple orange banana] booleans [true false true]
mixed [42 "hello" true 3.14]
servers [
prod1.example.com prod2.example.com
staging.example.com ]
empty_list []
### Array Access
Arrays are typically accessed by index in implementations:
- `servers[0]` → `"prod1.example.com"`
- `numbers[2]` → `3`
## Objects
### Syntax
Objects are defined using braces and can contain any number of statements:
object_name { key1 value1 key2 value2 nested_object { nested_key nested_value } }
### Nesting Rules
1. **Unlimited Depth**: Objects can be nested to arbitrary depth (subject to implementation limits)
2. **Mixed Content**: Objects can contain assignments, nested objects, and arrays
3. **Empty Objects**: `{}` represents an empty object
4. **Scope**: Each object creates a new scope for key names
### Examples
server { host localhost port 8080 }
application { name "My App"
database { host db.example.com port 5432
connection_pool {
min_size 5
max_size 20
timeout 30.0
}
}
cache { type redis host cache.example.com
settings {
max_memory 1gb
eviction_policy lru
}
} }
web_server { hosts [ web1.example.com web2.example.com ]
ssl { enabled true protocols [TLSv1.2 TLSv1.3] } }
### Object Access
Objects are typically accessed using dot notation:
- `server.host` → `"localhost"`
- `application.database.port` → `5432`
- `web_server.ssl.protocols[0]` → `"TLSv1.2"`
## Whitespace and Formatting
### Whitespace Rules
1. **Insignificant Indentation**: Indentation is purely visual and not syntactically meaningful
2. **Flexible Spacing**: Any amount of whitespace can separate tokens
3. **Line Breaks**: Statements are separated by newlines
4. **Visual Alignment**: Encouraged for readability but not required
### Recommended Style
server { host localhost port 8080
ssl { enabled true cert_path /etc/ssl/cert.pem } }
server { host localhost port 8080 ssl { enabled true cert_path /etc/ssl/cert.pem } }
server { host localhost port 8080 }
### Formatting Guidelines
1. **Indentation**: Use 2 or 4 spaces consistently
2. **Blank Lines**: Use blank lines to separate logical sections
3. **Alignment**: Align values for related keys when it improves readability
4. **Array Formatting**: Use multi-line format for arrays with more than 3-4 items
## Reserved Words
**None.** VIBE has no reserved words. Any valid identifier can be used as a key name. We don't believe in gatekeeping - all words are welcome in the VIBE family.
true true false false null null if conditional for loop_config class object_type vibe excellent # meta!
chinese_name "配置" russian_name "сервер" spanish_name "configuración"
This design choice prioritizes flexibility and eliminates the need to escape or quote common configuration key names. Because reserving words is just not the vibe.
## Path Notation
For programmatic access to nested values, implementations should support dot notation:
### Syntax
object.property object.nested_object.property object.array[index] object.nested_object.array[index].property
### Examples
Given this VIBE configuration:
app { name "My Application" version 1.0
database { hosts [db1.example.com db2.example.com] port 5432 }
features [auth api cache] }
Path access:
- `app.name` → `"My Application"`
- `app.version` → `1.0`
- `app.database.port` → `5432`
- `app.database.hosts[0]` → `"db1.example.com"`
- `app.features[1]` → `"api"`
### Implementation Notes
1. **Case Sensitivity**: Paths are case-sensitive
2. **Array Bounds**: Out-of-bounds array access should return null/undefined
3. **Missing Keys**: Access to non-existent keys should return null/undefined
4. **Type Safety**: Implementations may provide typed access methods
## Duplicate Keys
### Behavior Options
Implementations must define their behavior for duplicate keys:
#### Option 1: Last Value Wins (Recommended)
port 8080 host localhost port 9000 # This value is used: 9000
Sometimes you change your mind - that's totally valid! VIBE just goes with your latest decision.
#### Option 2: Error on Duplicate
Parsers reject files with duplicate keys in the same scope. For those who like their configs strict and unambiguous.
#### Option 3: Array Conversion
Some implementations may convert duplicate keys into arrays. Why choose when you can have both? (Though this might confuse the vibe a bit.)
### Scope Rules
Duplicate keys are only considered within the same scope:
server { port 8080 # Different scope }
client { port 3000 # Different scope - this is allowed }
## Complete Examples
### Web Application Configuration
application { name "E-commerce API" version 2.1.4 environment production debug false
server { host 0.0.0.0 port 8080
ssl {
enabled true
cert_file /etc/ssl/certs/api.crt
key_file /etc/ssl/private/api.key
protocols [TLSv1.2 TLSv1.3]
}
timeouts {
read 30
write 30
idle 120
shutdown 10
}
}
database { primary { driver postgresql host db-primary.internal port 5432 database ecommerce_prod username api_user password_file /etc/secrets/db_password
pool {
min_connections 10
max_connections 50
idle_timeout 300
max_lifetime 3600
}
}
replicas [
db-replica1.internal:5432
db-replica2.internal:5432
db-replica3.internal:5432
]
migrations {
auto_migrate false
directory /app/migrations
}
}
cache { type redis
primary {
host cache-primary.internal
port 6379
database 0
max_connections 20
}
cluster [
cache1.internal:6379
cache2.internal:6379
cache3.internal:6379
]
settings {
default_ttl 3600
max_memory 2gb
eviction_policy allkeys-lru
}
}
logging { level info format json
outputs [
stdout
/var/log/app/application.log
/var/log/app/errors.log
]
loggers {
database {
level debug
output /var/log/app/database.log
}
security {
level warn
output /var/log/app/security.log
}
}
}
features { payment_v2 true recommendation_engine true beta_checkout false advanced_search true }
services { payment_gateway { url https://api.payments.example.com api_key_file /etc/secrets/payment_api_key timeout 10 retry_attempts 3 }
email {
provider sendgrid
api_key_file /etc/secrets/sendgrid_api_key
from_address "noreply@mystore.com"
templates {
welcome_email template_123
order_confirmation template_456
password_reset template_789
}
}
analytics {
provider google_analytics
tracking_id "GA-XXXXXXXX-X"
events [
page_view
purchase
signup
cart_abandonment
]
}
}
security { cors { enabled true allowed_origins [ https://mystore.com https://admin.mystore.com ] allowed_methods [GET POST PUT DELETE OPTIONS] max_age 86400 }
rate_limiting {
enabled true
requests_per_minute 60
burst_size 10
endpoints {
"/api/auth/login" {
requests_per_minute 5
burst_size 2
}
"/api/orders" {
requests_per_minute 30
burst_size 5
}
}
}
jwt {
secret_file /etc/secrets/jwt_secret
expiry 3600
refresh_expiry 604800
issuer "mystore-api"
}
}
monitoring { health_check { enabled true path /health interval 30 timeout 5 }
metrics {
enabled true
provider prometheus
path /metrics
custom_metrics [
order_processing_time
cart_conversion_rate
api_response_time
]
}
alerts {
error_rate_threshold 5.0
response_time_threshold 500
notifications {
email admin@mystore.com
slack "#alerts"
pagerduty true
}
}
} }
### Development Environment Override
application { environment development debug true
server { port 3000
ssl {
enabled false
}
}
database { primary { host localhost database ecommerce_dev username dev_user password "dev_password_123" }
replicas [] # No replicas in development
}
cache { type memory # In-memory cache for development }
logging { level debug format text outputs [stdout] }
features { payment_v2 true beta_checkout true # Enable beta features in dev } }
## Parsing Algorithm
### State Machine
The VIBE parser is implemented as a state machine with the following states:
States:
- ROOT: Expecting top-level statements
- OBJECT: Inside an object, expecting statements
- ARRAY: Inside an array, expecting values
- VALUE: Reading a value
- COMMENT: Reading a comment
### Parsing Process
- Initialize parser state to ROOT
- Read next token
- Based on current state and token type:
-
ROOT state:
- IDENTIFIER: Read as key, transition to VALUE
- IDENTIFIER + '{': Create object, push OBJECT state
- IDENTIFIER + '[': Create array, push ARRAY state
- '#': Transition to COMMENT state
- EOF: End parsing
-
OBJECT state:
- IDENTIFIER: Read as key, transition to VALUE
- IDENTIFIER + '{': Create nested object, push OBJECT state
- IDENTIFIER + '[': Create array, push ARRAY state
- '}': Pop state, return to previous
- '#': Transition to COMMENT state
-
ARRAY state:
- STRING/NUMBER/BOOLEAN/IDENTIFIER: Add to array
- ']': Pop state, return to previous
- '#': Transition to COMMENT state
-
VALUE state:
- STRING/NUMBER/BOOLEAN/IDENTIFIER: Set value, return to previous state
-
COMMENT state:
- NEWLINE: Return to previous state
- Any other: Continue reading comment
-
### Parser Implementation Example (Pseudocode)
```c
typedef struct {
TokenType type;
char* value;
int line;
int column;
} Token;
typedef struct {
ParseState state;
int depth;
VibeValue* current_object;
char* current_key;
} Parser;
VibeValue* parse_vibe(char* input) {
Parser parser = {0};
parser.state = ROOT;
parser.current_object = create_object();
Lexer lexer = init_lexer(input);
Token token;
while ((token = next_token(&lexer)).type != EOF_TOKEN) {
switch (parser.state) {
case ROOT:
case OBJECT:
if (token.type == IDENTIFIER) {
parser.current_key = token.value;
Token next = peek_token(&lexer);
if (next.type == LEFT_BRACE) {
consume_token(&lexer); // consume '{'
push_object(&parser, token.value);
} else if (next.type == LEFT_BRACKET) {
consume_token(&lexer); // consume '['
push_array(&parser, token.value);
} else {
parser.state = VALUE;
}
} else if (token.type == RIGHT_BRACE) {
pop_state(&parser);
}
break;
case ARRAY:
if (token.type == RIGHT_BRACKET) {
pop_state(&parser);
} else {
add_array_value(&parser, parse_value(token));
}
break;
case VALUE:
set_object_value(&parser, parser.current_key, parse_value(token));
parser.state = (parser.depth > 0) ? OBJECT : ROOT;
break;
}
}
return parser.current_object;
}
- Lexical Errors: Invalid character sequences
- Syntax Errors: Invalid grammar
- Semantic Errors: Valid syntax but invalid meaning
- Type Errors: Type inference failures
Parsers should provide detailed error information:
Error: Unexpected token '}' on line 15, column 8
ssl {
^
Expected identifier or closing brace
Error: Unclosed object on line 12
server {
^
Expected '}' before end of file
(Looks like this object needs some closure 😉)
Error: Invalid escape sequence '\x' on line 8, column 15
path "C:\Users\name"
^
Valid escape sequences: \" \\ \n \t \r \uXXXX
(That backslash is trying to escape reality, but VIBE keeps it real!)
Error: Duplicate key 'port' on line 16
port 9000
^
Previously defined on line 14
(Déjà vu! This key is having an identity crisis.)
Error: Expected ']' on line 10, column 25
servers [web1.com web2.com
^
Arrays must be closed with ']'
(This array is feeling a bit... open-ended. Let's give it some closure!)
- Panic Mode: Skip tokens until a synchronization point (e.g., newline, brace)
- Error Production: Define grammar rules for common errors
- Insertion: Insert missing tokens when obvious
- Deletion: Skip unexpected tokens
Recommended: .vibe
Alternative extensions: .vb, .config, .conf
Proposed: application/vibe
Alternative: text/vibe
Required: UTF-8 without BOM
Byte Order Mark: Not permitted. Files must not start with UTF-8 BOM (EF BB BF).
Supported:
- Unix (LF):
\n - Windows (CRLF):
\r\n - Legacy Mac (CR):
\r
Recommended: Unix line endings for cross-platform compatibility.
Recommended Limits:
- Maximum file size: 10 MB
- Maximum line length: 1000 characters
- Maximum nesting depth: 64 levels
- Maximum identifier length: 255 characters
- Maximum string length: 1 MB
- Streaming Parser: Support parsing files larger than available memory
- Memory Efficiency: Parsed structure should not exceed 2x file size
- Reference Counting: Implement proper cleanup for nested structures
- String Interning: Consider interning common string values
- Parse Speed: > 100 MB/s on modern hardware (3+ GHz CPU)
- Memory Usage: < 2x input file size
- Latency: < 1ms for files under 1KB
- Scalability: Linear time complexity O(n) with input size
// C API example
typedef struct VibeParser VibeParser;
VibeParser* vibe_parser_new();
void vibe_parser_free(VibeParser* parser);
VibeValue* vibe_parse_string(VibeParser* parser, const char* input);
VibeValue* vibe_parse_file(VibeParser* parser, const char* filename);
VibeError vibe_get_last_error(VibeParser* parser);// Type-safe accessors
const char* vibe_get_string(VibeValue* value, const char* path);
int64_t vibe_get_int(VibeValue* value, const char* path);
double vibe_get_float(VibeValue* value, const char* path);
bool vibe_get_bool(VibeValue* value, const char* path);
VibeArray* vibe_get_array(VibeValue* value, const char* path);
VibeObject* vibe_get_object(VibeValue* value, const char* path);Implementations should specify thread safety guarantees:
- Parser Objects: Not thread-safe (one parser per thread)
- Parsed Values: Immutable and thread-safe for reading
- Concurrent Parsing: Multiple parsers can operate concurrently
Implementations should include:
- Unit Tests: Individual component testing
- Integration Tests: End-to-end parsing tests
- Performance Tests: Benchmarks with various file sizes
- Fuzz Tests: Random input testing for robustness
- Compatibility Tests: Cross-implementation compatibility
# Basic parsing tests
test_simple_assignment()
test_nested_objects()
test_arrays()
test_comments()
test_string_escaping()
# Error handling tests
test_syntax_errors()
test_unclosed_braces()
test_invalid_escape_sequences()
# Edge cases
test_empty_file()
test_large_files()
test_deep_nesting()
test_unicode_content()
# Performance tests
benchmark_parsing_speed()
benchmark_memory_usage()
profile_large_file_parsing()
- File Size Limits: Prevent memory exhaustion attacks
- Nesting Depth: Prevent stack overflow with deep structures
- String Length: Limit individual string sizes
- Identifier Length: Limit key name lengths
MAX_FILE_SIZE = 10 MB
MAX_NESTING_DEPTH = 64
MAX_STRING_LENGTH = 1 MB
MAX_IDENTIFIER_LENGTH = 255 characters
MAX_ARRAY_SIZE = 10,000 elements
MAX_OBJECT_KEYS = 10,000 keys
Prevent exponential memory growth through nested structures:
# Potential attack - deeply nested objects
level1 {
level2 {
level3 {
# ... continues for many levels
}
}
}
Mitigation: Enforce maximum nesting depth
Large arrays or strings can consume excessive memory:
# Potential attack - huge array
huge_array [item1 item2 ... (millions of items)]
Mitigation: Enforce size limits and streaming parsing
Certain input patterns may cause quadratic parsing time:
# Potential attack - many duplicate keys
key value
key value
# ... repeated thousands of times
Mitigation: Implement linear-time duplicate detection
- Validate Input: Check file size before parsing
- Resource Limits: Set timeouts and memory limits
- Sanitize Output: Validate parsed values before use
- Error Handling: Don't expose internal parser state in errors
- Logging: Log parsing attempts for security monitoring
- Small: 1KB configuration file
- Medium: 100KB structured data
- Large: 10MB complex configuration
- Deep: Maximum nesting depth file
- Wide: Many top-level keys
- Parse Time: Wall clock time to parse file
- Memory Usage: Peak memory consumption during parsing
- Memory Efficiency: Ratio of parsed structure size to file size
- Throughput: MB/s processing rate
| File Size | Parse Time | Memory Usage | Throughput |
|---|---|---|---|
| 1KB | < 0.1ms | < 10KB | > 10 MB/s |
| 100KB | < 10ms | < 1MB | > 100 MB/s |
| 10MB | < 1s | < 50MB | > 100 MB/s |
- Single-Pass Parsing: No backtracking or multiple passes
- String Interning: Reuse common strings
- Memory Pooling: Reduce allocation overhead
- SIMD Instructions: Use vectorized operations for scanning
- Branch Prediction: Optimize hot parsing paths
While VIBE itself has no built-in schema validation, implementations may provide schema languages for validation.
# Example schema definition
schema ApplicationConfig {
app {
name: string
version: string
debug: boolean? # Optional field
}
server {
host: string
port: integer(1..65535) # Range constraint
ssl?: { # Optional object
enabled: boolean
cert: string
}
}
features: [string] # Array of strings
}
- Type Checking: Ensure values match expected types
- Required Fields: Validate presence of mandatory keys
- Range Constraints: Check numeric values are within bounds
- Format Validation: Validate strings match patterns (e.g., URLs, emails)
- Cross-Field Validation: Validate relationships between fields
| Feature | VIBE | JSON | YAML | TOML | XML |
|---|---|---|---|---|---|
| Human Readable | ✓ | ✗ | ✓ | ✓ | ✗ |
| Minimal Syntax | ✓ | ✗ | ✓ | ✓ | ✗ |
| Visual Hierarchy | ✓ | ✓ | ✗ | ✗ | ✓ |
| Fast Parsing | ✓ | ✓ | ✗ | ✓ | ✗ |
| No Indentation Rules | ✓ | ✓ | ✗ | ✓ | ✓ |
| Type Inference | ✓ | ✗ | ✓ | ✓ | ✗ |
| Comments | ✓ | ✗ | ✓ | ✓ | ✓ |
| Unambiguous | ✓ | ✓ | ✗ | ✓ | ✓ |
| Single Pass Parse | ✓ | ✓ | ✗ | ✓ | ✗ |
Choose VIBE when:
- Configuration files need to be human-readable and editable
- Fast parsing is important
- Visual structure clarity is valued
- Simple syntax is preferred
- Comments are needed
Choose JSON when:
- Web APIs and data interchange
- Strict typing is not needed
- Minimal parser complexity is required
- Maximum compatibility is needed
Choose YAML when:
- Complex data structures with references
- Multi-document files are needed
- Existing YAML ecosystem is required
Choose TOML when:
- Simple configuration files
- Strong typing is important
- INI-like format is preferred
JSON structures map directly to VIBE:
JSON:
{
"server": {
"host": "localhost",
"port": 8080,
"ssl": {
"enabled": true
}
},
"features": ["auth", "api"]
}VIBE:
server {
host localhost
port 8080
ssl {
enabled true
}
}
features [auth api]
YAML structures translate with some changes:
YAML:
server:
host: localhost
port: 8080
ssl:
enabled: true
features:
- auth
- apiVIBE:
server {
host localhost
port 8080
ssl {
enabled true
}
}
features [auth api]
TOML sections become VIBE objects:
TOML:
[server]
host = "localhost"
port = 8080
[server.ssl]
enabled = true
features = ["auth", "api"]VIBE:
server {
host localhost
port 8080
ssl {
enabled true
}
}
features [auth api]
Implementations should provide conversion utilities:
# Command-line converters
vibe-convert --from json --to vibe config.json config.vibe
vibe-convert --from yaml --to vibe config.yaml config.vibe
vibe-convert --from toml --to vibe config.toml config.vibe
# Validation
vibe-validate config.vibe
vibe-format config.vibe # Pretty-print formatterThe future is looking bright for VIBE! We're constantly vibing with new ideas while keeping the core philosophy intact.
description """
This is a multi-line string
that spans several lines
and preserves formatting.
"""
include "database.vibe"
include "logging.vibe"
env development
database_host ${env}.db.example.com
schema ConfigSchema {
server {
host: string
port: integer(1..65535)
}
}
A binary representation for faster parsing and smaller size:
- Magic number:
VIBE(0x56494245) - Version byte
- Length-prefixed strings
- Type markers for values
- Date/time literals:
2025-01-14T10:30:00Z - Duration literals:
30s,5m,2h - Size literals:
10MB,1GB
if environment == "production" {
debug false
log_level error
}
template DatabaseConfig {
host ${db_host}
port ${db_port}
name ${db_name}
}
primary_db: DatabaseConfig {
db_host prod-db.example.com
db_port 5432
db_name app_prod
}
Templates would let you copy that vibe across multiple configurations!
- JSON5 - JSON for humans
- HJSON - Human JSON
- CSON - CoffeeScript Object Notation
- SDLang - Simple Declarative Language
- Parsing Techniques - Grune & Jacobs
- Crafting Interpreters - Robert Nystrom
- ANTLR - Parser generator
VIBE Format Specification v1.0
Pass the vibe check ✓
Remember: Configuration doesn't have to be complicated. Sometimes the best solution is the one that just feels right.
Keep calm and VIBE on! 🌊
This specification is released under the MIT License (because sharing good vibes should be free).