UP (Unified Properties)

A Human-Friendly Data Serialization Format

View the Project on GitHub uplang/spec

License: GPL v3 Website

Unified Properties

UP is a modern, human-friendly data serialization format designed to be simpler than YAML, more powerful than JSON, and more readable than TOML. It combines the best features of existing formats while introducing unique capabilities like dedenting and type annotations.

Quick Links:

Why UP?

Features

Type Annotations

# Single-word values (no quotes needed)
name Alice
age!int 30
active!bool true
url!uri https://example.com
created!ts 2025-10-05T12:00:00Z
timeout!dur 30s

# Multi-word values (two options)
title "Senior Engineer"     # Option 1: Use quotes
description: A modern data serialization format  # Option 2: Use colon suffix

Blocks (Nested Structures)

server {
  host localhost
  port!int 8080
  database {
    host db.example.com
    port!int 5432
  }
}

Lists

# Multiline lists
items [
apple
banana
cherry
]

# Inline lists
colors [red, green, blue]

Line-Oriented Values (Simple Multi-Word Values)

# Use `:` suffix to capture the entire line as a value
name: John Doe
title: Senior Software Engineer
message: Hello, World! This is a complete sentence.

# Works with type annotations
description!string: A modern, human-friendly data serialization format
count!int: 42
url!uri: https://example.com/path?query=value

# Traditional quoted syntax also works
name "John Doe"
title "Senior Software Engineer"

# Important: In line-oriented mode, surrounding quotes are stripped
title: "Senior Engineer"     # value is: Senior Engineer (quotes stripped)
title "Senior Engineer"       # value is: Senior Engineer (no quotes)
# Both produce the same result!

# To preserve literal quotes, use !quoted annotation
title!quoted: "Senior Engineer"  # value is: "Senior Engineer" (with quotes)
title!quoted: Engineer           # value is: "Engineer" (quotes added)

# Important: In line-oriented mode, # starts a comment
message: Hello World  # comment here
# Result: value is "Hello World" (comment not included)

# To include # in values, use quotes
tag "Use #hashtags"          # value is: Use #hashtags
tag: Use #hashtags           # value is: Use (# starts comment)

Multiline Strings with Language Hints

script!bash ```bash
#!/bin/bash
echo "Hello, World!"

config ```json { β€œkey”: β€œvalue”, β€œnumber”: 42 }

Dedenting (Unique Feature!)

# Remove 4 leading spaces from each line
code!4 ```python
    def hello():
        print("world")

Becomes:

def hello():

print(β€œworld”)


### Tables
```up
users!table {
  columns [id, name, email, age]
  rows {
    [1, Alice, alice@example.com, 30]
    [2, Bob, bob@example.com, 25]
    [3, Carol, carol@example.com, 35]
  }
}

Comments

# Comments start with # and go to end of line
name Alice  # Single-word values work inline
title: Senior Engineer  # Multi-word values use colon suffix or quotes

Templates & Composition (Revolutionary!)

# base.up - Common configuration
vars {
  app_name MyApp
  default_port!int 8080
}

app_name $vars.app_name
server {
  port $vars.default_port
}

# production.up - Environment-specific
config!base base.up

server!overlay {
  host production.example.com
  replicas!int 10
}

# Result: Base + Production overlay = Final config

No string templating hell! Just declarative composition using ! annotations.

Iterative variable resolution - Variables can reference each other regardless of order:

vars {
  environment production
  region us-west-2
  host $vars.environment.$vars.region.example.com  # Resolved iteratively
  url https://$vars.host:443
}

Dynamic namespaces - Generate content on-the-fly for testing and mocking:

!use [time, id, faker, random]

test_user {
  id $id.uuid
  name $faker.name
  email $faker.email
  created_at $time.now
  score!int $random.int(1, 100)
}

Declarative list generation - $list namespace with $self context:

!use [list, faker, id]

# Generate 10 test users with sequence context
users $list.generate(10, {
  id $id.uuid
  sequence!int $self.number
  name $faker.name
  email $faker.email
  is_first!bool $self.first
  label "User $self.number of $self.count"
})

Runtime schema validation - Types reference schemas for validation:

# Schema validates structure and constraints
server!file://./schemas/server.up-schema {
  host localhost
  port!int 8080
  timeout!dur 30s
}

# Or use schema registry
server!https://schemas.uplang.org/server/1.0.0 {
  host example.com
  port!int 443
  tls_enabled!bool true
}

Multi-document files - Use comment separators (# ---) to define multiple configs in one file:

# base config
vars { port!int 8080 }

# ---

# dev config
config!base base.up
server!overlay { debug!bool true }

# ---

# prod config
config!base base.up
server!overlay { replicas!int 10 }

See TEMPLATING.md for full documentation.

Document Lint Directives

Enforce coding standards with document-level linting rules:

!lint {
  no-empty-values!level warning
  no-ambiguous-keys!level warning
  require-type-annotations!level error
}

server {
  host!string: localhost
  port!int: 8080
  enabled!bool: true
}

Available lint rules:

See SYNTAX-REFERENCE.md for complete documentation.

Quick Start

#β€”

Implementations

UP has official implementations in multiple languages:

Language Repository Package Status
Go uplang/go go get github.com/uplang/go βœ… Stable
JavaScript/TypeScript uplang/js npm install @uplang/parser βœ… Stable
Python uplang/py pip install uplang βœ… Stable
Rust uplang/rust cargo add uplang βœ… Stable
Java uplang/java Maven/Gradle 🚧 In Progress
C uplang/c make install βœ… Stable

β†’ See All Implementations


Tooling

Command-Line Tools

Tool Description Installation
up Main CLI for parsing, formatting, validation go install github.com/uplang/tools/up@latest
up-language-server LSP server for IDE integration go install github.com/uplang/tools/language-server@latest
up-repl Interactive REPL go install github.com/uplang/tools/repl@latest

Editor Support

Editor Extension Features
VS Code vscode-up Syntax highlighting, LSP, auto-completion
IntelliJ IDEA intellij-up Full IDE integration, refactoring
Vim/Neovim LSP via nvim-lspconfig Syntax highlighting, LSP support
Emacs LSP via lsp-mode Full LSP integration

Namespace Plugins

Extend UP with dynamic functions:

Namespace Description Example
string String manipulation string:uuid, string:upper
time Date/time functions time:now, time:format
env Environment variables env:get HOME
file File operations file:read config.txt
random Random data random:int 1 100
fake Test data generation fake:name, fake:email

β†’ See All Namespaces


Ecosystem

Documentation


Installation

# UP CLI tool
go install github.com/uplang/tools/up@latest

# Language Server
go install github.com/uplang/tools/language-server@latest

# Or use language-specific parser libraries
# See IMPLEMENTATIONS.md for all available implementations

Usage

# Parse a UP file and output as JSON
up parse -i config.up --pretty

# Validate UP syntax
up validate -i config.up

# Format a UP file
up format -i config.up -o formatted.up

# Process templates (NEW!)
up template process -i config/production.up -o output.up

# Validate templates
up template validate -i config/production.up

Example Document

# Application configuration
app_name MyApp
version 1.0.0
debug!bool false

# Server settings
server {
  host 0.0.0.0
  port!int 8080
  tls_enabled!bool true
}

# Database configuration
database {
  driver postgres
  host db.example.com
  port!int 5432
  max_connections!int 50
}

# Feature flags
features {
  new_ui!bool true
  beta_api!bool false
}

# API endpoints
endpoints [
/health
/api/v1/users
/api/v1/products
]

# Environment variables
environment ```bash
export DATABASE_URL="postgresql://localhost/mydb"
export REDIS_URL="redis://localhost:6379"
export API_KEY="secret-key-here"

Scheduled jobs

jobs!table { columns [name, schedule, command] rows { [backup, 0 2 * * *, /usr/local/bin/backup.sh] [cleanup, 0 3 * * *, /usr/local/bin/cleanup.sh] } }


## Templating System

UP includes a revolutionary **declarative templating system** that avoids traditional string-based templating hell.

### Key Features

- **`_vars`** - Define reusable structured variables
- **`_base`** - Inherit from base configurations
- **`_overlay`** - Merge configurations declaratively
- **`_include`** - Compose from multiple files
- **`_patch`** - Apply targeted modifications
- **`_merge`** - Configure merge strategies

### Why UP Templating?

❌ **Traditional templating** (Helm, Jinja2):
```yaml
replicas: 
  tls: 

Problems: String substitution, complex logic, type-unsafe, hard to debug

βœ… UP templating:

_base base.up
_overlay {
  server {
    replicas!int 10
    tls_enabled!bool true
  }
}

Benefits: Declarative, type-safe, composable, predictable

Example: Multi-Environment Setup

config/
β”œβ”€β”€ base.up              # Common config
β”œβ”€β”€ development.up       # Dev environment
β”œβ”€β”€ production.up        # Prod environment
└── features/
    β”œβ”€β”€ enable-beta.up
    └── high-availability.up

Compose them:

up template process -i config/production.up -o prod.up

See TEMPLATING.md and examples/templates/ for complete documentation.

Language Implementations

UP has official parser implementations in multiple languages. Each implementation is maintained in its own repository.

For complete details and installation instructions, see IMPLEMENTATIONS.md.

Go (Reference Implementation)

import "github.com/uplang/go"

p := up.NewParser()
doc, err := p.ParseDocument(reader)

Repository: github.com/uplang/go

JavaScript/TypeScript

const up = require('@uplang/js');
const doc = up.parse(upText);

Repository: github.com/uplang/js

Python

import uplang
doc = uplang.parse(up_text)

Repository: github.com/uplang/py

Rust

use uplang::parse;
let doc = parse(up_text)?;

Repository: github.com/uplang/rust

C

#include <up.h>
up_document_t *doc = up_parse_string(up_text);

Repository: github.com/uplang/c

Grammar Specifications

UP has formal grammar definitions in multiple parser generator formats:

These can be used to generate parsers in any language supported by these tools.

Examples

Comprehensive examples demonstrating all UP features:

See examples/README.md for detailed descriptions.

Comparison with Other Formats

Feature UP JSON YAML TOML HCL
Human-friendly βœ… ❌ βœ… βœ… βœ…
Type annotations βœ… ❌ ❌ βœ… βœ…
Multiline strings βœ… ❌ βœ… βœ… βœ…
Comments βœ… ❌ βœ… βœ… βœ…
Nested structures βœ… βœ… βœ… βœ… βœ…
Simple syntax βœ… βœ… ❌ βœ… βœ…
Dedenting βœ… ❌ ❌ ❌ ❌
Language hints βœ… ❌ ❌ ❌ ❌
Tables βœ… ❌ ❌ βœ… ❌
No indentation rules βœ… βœ… ❌ βœ… βœ…

Why Not JSON?

Why Not YAML?

Why Not TOML?

Why UP?

Language Design Principles

  1. Line-Oriented: Each statement is on its own line
  2. Explicit Structure: Delimiters ({, [, ` ``` `) are clear and unambiguous
  3. Optional Types: Everything is a string by default, types are annotations
  4. Minimal Syntax: Few special characters, no complex escaping rules
  5. Predictable: No surprising behavior or edge cases
  6. Extensible: Custom type annotations supported
  7. Developer-Friendly: Designed for configuration files and data exchange

Syntax Summary

# Comments
# Start with # and go to end of line

# Key-value pairs
key value
key!type value

# Blocks (nested structures)
key {
  nested_key value
}

# Lists
key [
item1
item2
]

# Inline lists
key [item1, item2, item3]

# Multiline strings
key ```
multiline content
preserved whitespace

Multiline with language hint

key!lang ```python def hello(): print(β€œworld”)


# Dedenting (removes N leading spaces)
key!4 ```
    indented content
    becomes dedented

Tables

key!table { columns [col1, col2, col3] rows { [val1, val2, val3] [val4, val5, val6] } }


## Type Annotations

UP supports arbitrary type annotations. **String is the default** - no annotation needed.

Common type annotations:

- **`!int`, `!integer`** - Integer numbers
- **`!float`, `!double`, `!number`** - Floating-point numbers
- **`!bool`, `!boolean`** - Boolean values
- **`!url`, `!uri`** - URLs and URIs
- **`!ts`, `!timestamp`** - Timestamps
- **`!dur`, `!duration`** - Durations
- **`!list`** - Lists
- **`!table`** - Tables
- **Custom types** - Any identifier can be a type

**Note:** String is the default type. Only specify `!string` if you need to explicitly document that something is a string, but it's usually redundant (e.g., `version 1.2.3` is already a string).

Types are metadata for consumers. The parser preserves type information but doesn't validate values.

## Use Cases

UP is ideal for:

- **Application configuration files**
- **Infrastructure as Code** (similar to HCL)
- **CI/CD pipelines** (simpler than YAML)
- **API specifications**
- **Data exchange** (alternative to JSON)
- **Documentation with embedded code**
- **Configuration management**
- **Test fixtures and mock data**

## Tools and Ecosystem

### Command-Line Tools
- `up parse` - Parse UP and output JSON
- `up validate` - Validate UP syntax
- `up format` - Format/prettify UP files

### Editor Support
- Tree-sitter grammar for syntax highlighting
- Language Server Protocol (LSP) implementation (planned)
- VS Code extension (planned)
- Vim/Neovim plugin (planned)

### Integrations
- Convert to/from JSON, YAML, TOML (planned)
- Schema validation (planned)
- Template support (planned)

## Repository Structure

This repository (`spec`) contains the **UP language specification** only:

spec/ β”œβ”€β”€ grammar/ # Grammar definitions β”‚ β”œβ”€β”€ up.y # Bison/Yacc grammar β”‚ β”œβ”€β”€ up.l # Flex lexer β”‚ β”œβ”€β”€ up.g4 # ANTLR4 grammar β”‚ β”œβ”€β”€ up.peg # PEG grammar β”‚ β”œβ”€β”€ grammar.js # Tree-sitter grammar β”‚ β”œβ”€β”€ GRAMMAR.md # EBNF specification β”‚ └── LEXER.md # Lexer specification β”œβ”€β”€ examples/ # Example UP files β”‚ β”œβ”€β”€ *.up # Feature demonstrations β”‚ β”œβ”€β”€ templates/ # Template examples β”‚ └── README.md # Example documentation β”œβ”€β”€ schemas/ # Schema examples β”œβ”€β”€ *.md # Documentation files └── README.md # This file


**Implementation repositories** (parsers and tools):
- **Go**: [`github.com/uplang/go`](https://github.com/uplang/go) - Reference parser + CLI
- **JavaScript**: [`github.com/uplang/js`](https://github.com/uplang/js)
- **Python**: [`github.com/uplang/py`](https://github.com/uplang/py)
- **Rust**: [`github.com/uplang/rust`](https://github.com/uplang/rust)
- **C**: [`github.com/uplang/c`](https://github.com/uplang/c)

**Namespace implementations**:
- **Namespaces**: [`github.com/uplang/ns`](https://github.com/uplang/ns) - Official namespaces

### Testing Examples

```bash
# Install the reference CLI
go install github.com/uplang/go/cmd/up@latest

# Validate all examples
for file in examples/*.up; do
  up validate -i "$file"
done

Contributing

Contributions are welcome! Areas where help is needed:

Please see CONTRIBUTING.md for guidelines.

Specification

The formal specification is available in grammar/GRAMMAR.md.

Key points:

FAQ

Is UP production-ready?

UP has a stable reference implementation in Go and parsers in multiple languages. All examples parse correctly and the grammar is well-defined.

How does UP handle Unicode?

Full UTF-8 support for identifiers, strings, and comments.

Can I use UP for large files?

Yes, UP parsers are designed to handle files of any size efficiently. The Go implementation uses streaming parsing.

How do I handle secrets/sensitive data?

Like other configuration formats, UP files can contain sensitive data. Use encryption, environment variable substitution, or secret management tools.

Can UP replace JSON/YAML/TOML?

UP can be used anywhere these formats are used. It’s especially good for configuration files and human-edited documents.

What about backward compatibility?

The UP specification is stable. Future versions will maintain backward compatibility with existing documents.

License

MIT License - see LICENSE for details.

Documentation

Language Specification

Namespaces

All namespace documentation is now in the ns repository:

Specification

Implementations

Ecosystem

Acknowledgments

UP draws inspiration from:


UP: Better than JSON. Simpler than YAML. More powerful than TOML.