Skip to content

80LK/modlike

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

125 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

go-modlike

Language: [ EN | RU ]

go-modlike is a Go library for parsing, building, and serializing configuration files in the Modlike format.

Modlike is inspired by the go.mod syntax: data is written as key value lines, while nested structures are represented with parenthesized blocks.

Features

  • parsing from []byte, string, and io.Reader;
  • document serialization to []byte, string, or io.Writer;
  • ordered data model: key order and list item order are preserved;
  • support for lists, maps, and string values;
  • string literals with escape sequences;
  • line and block comments at the lexical analysis stage;
  • strict per-key typing: once a key is first created as a list, it cannot later become a map.

Installation

go get github.com/80lk/modlike

The minimum Go version is specified in go.mod.

Format Example

project (
	name project_name
	version 1.0.0
)

project author 80LK

meta my_data "string value"

tags (
	tag1
	tag2
	tag3
	tag4
)

The root document is a map. Root key values can be:

  • a list, when the value is written as a single string or as a block without keys;
  • a map, when a nested key follows the root key or when a block contains key value pairs.

When a key appears more than once, values of the same type are merged: lists are appended, and maps are merged recursively.

Quick Start

package main

import (
	"fmt"
	"log"

	"github.com/80lk/modlike"
)

func main() {
	doc, err := modlike.ParseString(`
project (
	name project_name
	version 1.0.0
)

tags (
	tag1
	tag2
)
`)
	if err != nil {
		log.Fatal(err)
	}

	project, err := doc.GetMap("project")
	if err != nil {
		log.Fatal(err)
	}

	nameList, err := project.GetList("name")
	if err != nil {
		log.Fatal(err)
	}

	name, err := nameList.GetStringFirst()
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(name)

	out, err := modlike.SerializeString(doc)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(out)
}

Building a Document

func buildDocument() (modlike.Document, error) {
	doc := modlike.New()

	require, err := doc.CreateMap("require")
	if err != nil {
		return nil, err
	}

	module, err := require.CreateList("github.com/example/module")
	if err != nil {
		return nil, err
	}
	module.AppendString("v1.0.0")

	replace, err := doc.CreateMap("replace")
	if err != nil {
		return nil, err
	}

	oldModule, err := replace.CreateList("github.com/old/module")
	if err != nil {
		return nil, err
	}
	oldModule.AppendString("github.com/new/module")

	return doc, nil
}

Public API

Main package functions:

  • modlike.New() Document - creates an empty document;
  • modlike.Parse(data []byte) (Document, error) - parses a document from bytes;
  • modlike.ParseString(src string) (Document, error) - parses a document from a string;
  • modlike.ParseReader(r io.Reader) (Document, error) - parses a document from a stream;
  • modlike.Serialize(doc Document) ([]byte, error) - serializes a document;
  • modlike.SerializeString(doc Document) (string, error) - serializes a document to a string;
  • modlike.WriteTo(w io.Writer, doc Document) error - writes a serialized document to a stream.

Marshal and Unmarshal are declared, but currently return modlike: not implemented.

Data Model

Document is the root map with the following methods:

  • Has(key string) bool;
  • GetKind(key string) Kind;
  • Keys() []string;
  • Get(key string) Value;
  • GetList(key string) (*List, error);
  • CreateList(key string) (*List, error);
  • GetMap(key string) (*Map, error);
  • CreateMap(key string) (*Map, error);
  • Delete(key string);
  • All(func(string, Value) bool).

Map stores values by string keys and supports the same operations for nested lists and maps.

List stores an ordered sequence of values. Strings, maps, and nested lists can be added to a list:

  • AppendString, PrependString, InsertString;
  • AppendNewMap, PrependNewMap, InsertNewMap;
  • AppendNewList, PrependNewList, InsertNewList;
  • GetString, GetStringFirst, GetStringLast;
  • GetMap, GetMapFirst, GetMapLast;
  • GetList, GetListFirst, GetListLast;
  • Delete, DeleteFirst, DeleteLast;
  • All(func(int, Value) bool).

Value kind can be checked with Kind:

  • modlike.K_NONE;
  • modlike.K_LIST;
  • modlike.K_MAP;
  • modlike.K_STRING.

Syntax Brief

  • identifiers are used as unquoted keys and values;
  • strings with spaces are written in double quotes;
  • supported escape sequences are \n, \r, \t, \", \\;
  • a block starts with ( and ends with );
  • // starts a line comment;
  • /* ... */ defines a block comment;
  • empty lines are allowed.

Detailed grammar and format description are available in docs/spec.en.md, docs/modlike.ebnf, and docs/modlike.g4.

Tests

go test ./...

Status

The project is under active development. The parser, model transformer, and serializer are covered by tests, but the Marshal/Unmarshal API is not implemented yet.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages