PHPackages                             maml/maml - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Parsing &amp; Serialization](/categories/parsing)
4. /
5. maml/maml

ActiveLibrary[Parsing &amp; Serialization](/categories/parsing)

maml/maml
=========

MAML Parser

v2.0.1(1mo ago)03MITPHPPHP &gt;=8.2CI passing

Since Mar 23Pushed 1mo agoCompare

[ Source](https://github.com/maml-dev/maml-php)[ Packagist](https://packagist.org/packages/maml/maml)[ Docs](https://maml.dev)[ RSS](/packages/maml-maml/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (4)Dependencies (3)Versions (4)Used By (0)

maml-php
========

[](#maml-php)

[MAML](https://maml.dev) parser for PHP. Includes a full AST with source positions, comment preservation, and pretty printing.

- Spec-accurate parser and serializer
- Full AST with source positions (offset, line, column) on every node
- Comments preserved and attached to nearest nodes
- Schema validation with detailed error reporting
- `printAst()` reconstructs source from AST, including comments
- `errorSnippet()` for user-friendly error messages pointing at source locations
- Zero dependencies
- 100% test coverage

Installation
------------

[](#installation)

```
composer require maml/maml

```

Requires PHP 8.2+ with `mbstring`.

Quick Start
-----------

[](#quick-start)

```
use Maml\Maml;

// Parse to plain PHP values
$data = Maml::parse('{name: "MAML", version: 1}');
$data['name']; // "MAML"

// Serialize back to MAML
Maml::stringify(['name' => 'MAML', 'version' => 1]);
// {
//   name: "MAML"
//   version: 1
// }
```

AST
---

[](#ast)

```
$source = '{
  # Database config
  host: "localhost"
  port: 5432
}';

$doc = Maml::parseAst($source);
```

Every node has a `type` string and a `span` with start/end positions:

```
$doc->value->type; // "Object"
$doc->value->span->start->line; // 1
$doc->value->properties[0]->key->value; // "host"
```

### Printing

[](#printing)

`printAst()` reconstructs MAML source from an AST, preserving comments and blank lines:

```
Maml::printAst($doc);
// {
//   # Database config
//   host: "localhost"
//   port: 5432
// }
```

### Converting to plain values

[](#converting-to-plain-values)

`toValue()` strips AST metadata and returns plain PHP values:

```
Maml::toValue($doc); // ["host" => "localhost", "port" => 5432]
```

### Error snippets

[](#error-snippets)

Point at any AST node in source for user-friendly error messages. Accepts `Position` (single `^`) or `Span` (underline `^^^^`):

```
$node = $doc->value->properties[1]->value;
Maml::errorSnippet($source, $node->span, 'Port out of range');
// Port out of range on line 4.
//
//       port: 5432
//             ^^^^
```

Show context lines and Rust-style gutter with line numbers:

```
Maml::errorSnippet($source, $node->span, 'Port out of range', context: 2, gutter: true);
// Port out of range on line 4.
//
//     2 |   host: "localhost"
//     3 |   port: 5432
//     4 |   timeout: -1
//       |            ^^
```

Options: `context` (lines above), `indent` (default `'    '`), `gutter` (line numbers).

Schema Validation
-----------------

[](#schema-validation)

Define expected shapes with the `S` builder, validate against a parsed AST:

```
use Maml\Schema\S;

$schema = S::object([
    'host' => S::string(),
    'port' => S::integer(min: 1, max: 65535),
    'tags' => S::arrayOf(S::string(), minItems: 1),
    'ssl' => S::optional(S::boolean()),
    'mode' => S::enum('fast', 'safe', 'auto'),
    'version' => S::optional(S::string(pattern: '/^\d+\.\d+\.\d+$/')),
]);

$doc = Maml::parseAst($source);
$errors = Maml::validate($doc, $schema);

foreach ($errors as $error) {
    // $error->message  "Expected integer, got string"
    // $error->path     "$.port"
    // $error->span     Span(start: Position(line: 3, ...), end: ...)
    echo Maml::errorSnippet($source, $error->span, $error->message);
}
```

### Available schema types

[](#available-schema-types)

BuilderMatches`S::string()`String or raw string`S::string(pattern: '/.../')`String matching regex`S::integer()`Integer`S::integer(min: 0, max: 100)`Integer within range`S::float()`Float`S::float(min: 0.0, max: 1.0)`Float within range`S::number()`Integer or float`S::number(min: 0)`Number with minimum`S::boolean()`Boolean`S::null()`Null`S::any()`Anything`S::literal('x')`Exact value`S::enum('a', 'b')`One of the listed values`S::object([...])`Object with typed properties, rejects unknown keys`S::object([...], S::any())`Same, but allows extra keys`S::object([...], S::string())`Same, extra keys must match schema`S::orderedObject([...])`Object with properties in order`S::map(schema)`Object with any keys, typed values`S::optional(schema)`Property may be absent`S::arrayOf(schema)`Array of uniform type`S::arrayOf(schema, minItems: 1)`Array with minimum length`S::arrayOf(schema, maxItems: 10)`Array with maximum length`S::tuple([s1, s2])`Fixed-length array`S::union(s1, s2)`One of several schemasLicense
-------

[](#license)

[MIT](LICENSE)

###  Health Score

39

—

LowBetter than 86% of packages

Maintenance91

Actively maintained with recent releases

Popularity4

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~6 days

Total

3

Last Release

45d ago

Major Versions

v1.0.0 → v2.0.02026-04-03

### Community

Maintainers

![](https://www.gravatar.com/avatar/f4d823f67218bb68e89dca47d04551e8a929c3bfca85513df67a2700544b5338?d=identicon)[medv](/maintainers/medv)

---

Top Contributors

[![antonmedv](https://avatars.githubusercontent.com/u/141232?v=4)](https://github.com/antonmedv "antonmedv (33 commits)")

---

Tags

configurationconfigparserserializermaml

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/maml-maml/health.svg)

```
[![Health](https://phpackages.com/badges/maml-maml/health.svg)](https://phpackages.com/packages/maml-maml)
```

###  Alternatives

[masterminds/html5

An HTML5 parser and serializer.

1.8k242.8M229](/packages/masterminds-html5)[hassankhan/config

Lightweight configuration file loader that supports PHP, INI, XML, JSON, and YAML files

97513.5M170](/packages/hassankhan-config)[laktak/hjson

JSON for Humans. A configuration file format with relaxed syntax, fewer mistakes and more comments.

86233.7k12](/packages/laktak-hjson)[romanpitak/nginx-config-processor

Nginx configuration files processor.

7235.3k1](/packages/romanpitak-nginx-config-processor)[m1/vars

Vars is a simple to use and easily extendable configuration loader with in built loaders for ini, json, PHP, toml, XML and yaml/yml file types. It also comes with in built support for Silex and more frameworks to come soon.

69124.2k1](/packages/m1-vars)[metroplex-systems/edifact

Parser and Serializer for UN/EDIFACT messages

36404.6k](/packages/metroplex-systems-edifact)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
