M3LParser 0.1.3

There is a newer version of this package available.
See the version list below for details.
dotnet add package M3LParser --version 0.1.3
                    
NuGet\Install-Package M3LParser -Version 0.1.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="M3LParser" Version="0.1.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="M3LParser" Version="0.1.3" />
                    
Directory.Packages.props
<PackageReference Include="M3LParser" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add M3LParser --version 0.1.3
                    
#r "nuget: M3LParser, 0.1.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package M3LParser@0.1.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=M3LParser&version=0.1.3
                    
Install as a Cake Addin
#tool nuget:?package=M3LParser&version=0.1.3
                    
Install as a Cake Tool

M3LParser

M3L (Meta Model Markup Language) parser for .NET — parse .m3l.md files into a structured AST.

M3L is a Markdown-based data modeling language. You write data models in readable Markdown, and this parser converts them into a machine-processable AST with full validation.

Install

dotnet add package M3LParser

Supported runtimes: .NET 8.0, .NET 9.0, .NET 10.0

Quick Start

using M3L;

var parser = new M3LParser();

// Parse a file or directory
var ast = await parser.ParseAsync("./models");

// Parse a string
var ast2 = parser.ParseString("""
## User
- name: string(100) @not_null
- email: string(320)? @unique

## UserRole ::enum
- admin: "Administrator"
- user: "Regular User"
""");

Console.WriteLine(ast2.Models.Count);  // 1
Console.WriteLine(ast2.Enums.Count);   // 1

// Validate with diagnostics
var (validated, result) = await parser.ValidateAsync("./models");
foreach (var error in result.Errors)
    Console.WriteLine($"[{error.Code}] {error.Message}");

M3L Syntax

# Namespace: myapp

## Author
- name(Author Name): string(100) @not_null @searchable
- bio(Biography): text?
- birth_date: date?

### Rollup
- book_count: integer @rollup(BookAuthor.author_id, count)

> Stores information about book authors.

## BookStatus ::enum
- available: "Available"
- borrowed: "Borrowed"
- reserved: "Reserved"

## Book : BaseModel
- title: string(200) @not_null @searchable
- isbn: string(20) @unique
- status: enum = "available"
  - available: "Available"
  - borrowed: "Borrowed"
- publisher_id: identifier @fk(Publisher.id)

### Lookup
- publisher_name: string @lookup(publisher_id.name)

### Computed
- is_available: boolean @computed("status = 'available' AND quantity > 0")

## OverdueLoans ::view @materialized
> Currently overdue book loans.
### Source
- from: Loan
- where: "due_date < now() AND status = 'ongoing'"
- order_by: due_date asc
- borrower_name: string @lookup(member_id.name)

Key syntax elements:

Syntax Meaning
# Title Document title or namespace (# Namespace: domain.example)
## Name Model definition
## Name : Parent Model with inheritance
## Name ::enum Enum definition
## Name ::interface Interface definition
## Name ::view Derived view
- field: type Field definition
- field: type? Nullable field
- field: type[] Array field
- field: type?[] Array of nullable items
- field: type = val Field with default value
@attr / @attr(args) Attribute (constraint, index, etc.)
`[FrameworkAttr]` Custom framework attribute
### Lookup / ### Rollup / ### Computed Kind section for derived fields
### Section Named section (Indexes, Relations, Metadata, etc.)
> text Model/element description
"text" Inline description on field

AST Output

The parser produces an M3LAst object:

public class M3LAst
{
    public string ParserVersion { get; set; }   // Parser package version (semver)
    public string AstVersion { get; set; }      // AST schema version
    public ProjectInfo Project { get; set; }
    public List<string> Sources { get; set; }
    public List<ModelNode> Models { get; set; }
    public List<EnumNode> Enums { get; set; }
    public List<ModelNode> Interfaces { get; set; }
    public List<ModelNode> Views { get; set; }
    public List<Diagnostic> Errors { get; set; }
    public List<Diagnostic> Warnings { get; set; }
}

Key AST types

public class FieldNode
{
    public string Name { get; set; }
    public string? Type { get; set; }
    public List<string>? GenericParams { get; set; }  // map<K,V> → ["K", "V"]
    public bool Nullable { get; set; }
    public bool Array { get; set; }
    public bool ArrayItemNullable { get; set; }       // string?[] → true
    public FieldKind Kind { get; set; }               // Stored, Computed, Lookup, Rollup
    public List<FieldAttribute> Attributes { get; set; }
    public List<CustomAttribute>? FrameworkAttrs { get; set; }
    public LookupDef? Lookup { get; set; }
    public RollupDef? Rollup { get; set; }
    public ComputedDef? Computed { get; set; }
    public List<FieldNode>? Fields { get; set; }      // sub-fields for object type
    // ...
}

public class ModelNode
{
    public string Name { get; set; }
    public string NodeType { get; set; }              // "model", "interface", "view"
    public List<string> Inherits { get; set; }
    public List<FieldAttribute> Attributes { get; set; }  // model-level attrs
    public List<FieldNode> Fields { get; set; }
    public SectionData Sections { get; set; }
    // ...
}

Validation

The validator checks for semantic errors and style warnings:

Errors:

Code Description
M3L-E001 Rollup FK field missing @reference
M3L-E002 Lookup FK field missing @reference
M3L-E004 View references non-existent model
M3L-E005 Duplicate model/enum name
M3L-E006 Duplicate field name within model
M3L-E007 Unresolved parent in inheritance

Warnings (strict mode):

Code Description
M3L-W001 Field line exceeds 80 characters
M3L-W002 Object nesting exceeds 3 levels
M3L-W004 Lookup chain exceeds 3 hops

Multi-file Projects

Place .m3l.md files in a directory and parse the directory path. The resolver automatically merges all files, resolves inheritance, and detects cross-file references.

var parser = new M3LParser();
var ast = await parser.ParseAsync("./models");

// All models, enums, interfaces, views from all files are merged
Console.WriteLine($"Models: {ast.Models.Count}");
Console.WriteLine($"Errors: {ast.Errors.Count}");

API Reference

High-level API (M3LParser)

var parser = new M3LParser();

// Parse files from path (file or directory)
M3LAst ast = await parser.ParseAsync(inputPath);

// Parse content string
M3LAst ast = parser.ParseString(content, filename);

// Parse and validate
(M3LAst ast, ValidateResult result) = await parser.ValidateAsync(inputPath);
(M3LAst ast, ValidateResult result) = parser.ValidateString(content);

Lower-level API

using M3L;
using M3L.Models;

// Step-by-step parsing
List<Token> tokens = Lexer.Lex(content, "file.m3l.md");
ParsedFile parsed = Parser.ParseTokens(tokens, "file.m3l.md");
M3LAst ast = Resolver.Resolve(new[] { parsed });
ValidateResult result = Validator.Validate(ast, new ValidateOptions { Strict = true });

Version Info

string parserVersion = M3LParser.GetParserVersion(); // from VERSION file
string astVersion = M3LParser.GetAstVersion();       // "1.0"

Compatibility

This C# parser is a direct port of the TypeScript parser and produces an equivalent AST structure. Both parsers share the same conformance test suite.

TypeScript C#
Package @iyulab/m3l M3LParser
Runtime Node.js 20+ .NET 8.0+
AST Version 1.0 1.0

Version is managed centrally via the root VERSION file.

License

MIT

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.
  • net8.0

    • No dependencies.
  • net9.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.4 84 2/26/2026
0.1.3 93 2/25/2026