flatlang

package module
v0.0.0-...-93c90eb Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 22, 2020 License: MIT Imports: 8 Imported by: 0

README

flatlang

MIT License go.dev reference Discord Chat

flatlang is an embeddable configuration language that is made for configuring large-scale codegen tools, automation tools, code bases, and applications offline/in realtime.

flatlang is heavily inspired on being scriptable and embeddable by Google Starlark, and being suited for code generation and data validation by CUE.

** This project is still a heavy WIP! Ping me on Discord if you'd like to contribute or know more.

Goals

  1. Be human-friendly. Flatlang discourages having to type the same variable names and method names over and over again while laying out your configuration. This is done by having flatlang represent configuration code as chains of method calls linked together using pipe syntax ('>'). This forces configuration in flatlang to naturally be imperative, such that it naturally reads/can be written from top to bottom.

  2. Be easy to type. Defining a variable, calling a method with a set of parameters, editing some constants, and refactoring out some code should only require a few key strokes. The goal is to make flatlang a language that is convenient and fun to write in irrespective of your coding environment (terminal, text editor, IDE, etc.). There are zero keywords you have to remember in flatlang.

  3. No recursion. Recursion burdens the reader into having to follow and pick up base conditions and recursive statements; something which obfuscates configuration code and dilutes readability.

  4. No recursive structures. Maps and lists in flatlang are only allowed to be composed of literals. Most likely whenever you see the need to recursively compose a map or list, you'd be better off implementing new builtin methods into flatlang to handle your use case, or reconsider the parameters of methods you implement into flatlang.

  5. Types are values. Options and values may be constrained using sum types, which may very easily be used to configure and represent complicated constraints on values for your programs.

Design

Both the lexer and parser are generated using Ragel and Yacc.

You can manually test the lexer/parser for flatlang by running either one of the following commands below. The command below assumes you have Go installed:

Lexer
$ cat testdata/test.fbs | go run github.com/lithdew/flatlang/cmd/lexer
Parser
$ go run github.com/lithdew/flatlang/cmd/parser

Example

// Database URL.

db = 'sqlite://:memory:';

// SQL query handlers.

all_posts = sql db 'select * from posts limit :limit offset :offset' 'posts';
find_post = sql db 'select * from posts where id = :id' 'post';
new_post  = sql db 'insert into posts (author, content) values (:author, :content) returning id' 'id';

// An example expanded-form of a SQL query.

expanded_form = sql {db: db, query: 'select * from posts limit :limit offset :offset', set: 'posts'};

// Pagination helper.

paginate
    = default {offset: 0, limit: 1024}
    > require {offset: >=0, limit: >=0 & <=1024}
    > set ['limit', 'offset'];

// GET "/posts" returns at most 1024 posts.

get "/posts"
	> paginate
	> find_post
	> encode;

// GET "/posts/:id" returns a post with a specific id = ":id".

get "/posts/:id"
    > find_post
    > encode;

// POST "/posts" creates a new post. Author and content must be provided.

post {path: "/posts", max_body_size: 128}
	> decode
	> new_post
	> encode;

// A simple health check endpoint that returns {status: "ok"}.

get "/health" > set {status: "ok"} > encode;

Documentation

Index

Constants

This section is empty.

Variables

View Source
var NodeString = [...]string{
	ProgramNode: "program",
	VarNode:     "var",
	ValNode:     "val",
	ExprNode:    "expr",
	InterpNode:  "interp",
	IdentNode:   "ident",
	BoolNode:    "bool",
	IntNode:     "int",
	FloatNode:   "float",
	StringNode:  "string",
	TextNode:    "text",
	ListNode:    "list",
	MapNode:     "map",

	OpNode + negate: "-",
	OpNode + '+':    "+",
	OpNode + '-':    "-",
	OpNode + '*':    "*",
	OpNode + '/':    "/",
	OpNode + '>':    ">",
	OpNode + '<':    "<",
	OpNode + gte:    ">=",
	OpNode + lte:    "<=",
	OpNode + '!':    "!",
	OpNode + '&':    "&",
	OpNode + '|':    "|",
}

Functions

func Eval

func Eval(lx *Lexer, n *Node) (interface{}, error)

func Repr

func Repr(sym int) string

func Unquote

func Unquote(s string) (string, error)

Types

type Evaluator

type Evaluator struct {
	// contains filtered or unexported fields
}

func NewEval

func NewEval(lx *Lexer) *Evaluator

func (*Evaluator) Eval

func (e *Evaluator) Eval(n *Node) (interface{}, error)

func (*Evaluator) RegisterBuiltin

func (e *Evaluator) RegisterBuiltin(name string, fn interface{}) error

type Lexer

type Lexer struct {
	Data     []byte
	Tokens   []Token
	Comments []Token
	// contains filtered or unexported fields
}

func Lex

func Lex(data []byte, path string) (*Lexer, error)

func LexFile

func LexFile(path string) (r *Lexer, err error)

func (*Lexer) At

func (r *Lexer) At(offset int) string

func (*Lexer) Errorf

func (r *Lexer) Errorf(format string, a ...interface{}) error

func (*Lexer) Last

func (r *Lexer) Last() string

type Node

type Node struct {
	Type   NodeType
	Tokens []int
	Nodes  []*Node
}

func NewNode

func NewNode(t NodeType, tokens ...int) *Node

func NewOpNode

func NewOpNode(t NodeType, tokens ...int) *Node

func (Node) Format

func (n Node) Format(lx *Lexer) string

func (*Node) N

func (n *Node) N(nodes ...*Node) *Node

func (*Node) N1

func (n *Node) N1(n0 *Node) *Node

func (*Node) N2

func (n *Node) N2(n0, n1 *Node) *Node

func (*Node) N3

func (n *Node) N3(n0, n1, n2 *Node) *Node

func (*Node) T

func (n *Node) T(tokens ...int) *Node

func (*Node) T1

func (n *Node) T1(t0 int) *Node

func (*Node) T2

func (n *Node) T2(t0, t1 int) *Node

func (*Node) T3

func (n *Node) T3(t0, t1, t2 int) *Node

func (Node) Val

func (n Node) Val(lx *Lexer) string

type NodeType

type NodeType int
const (
	ProgramNode NodeType = iota
	VarNode
	ValNode
	ExprNode
	InterpNode
	IdentNode
	BoolNode
	IntNode
	FloatNode
	StringNode
	TextNode
	ListNode
	MapNode

	OpNode
)

func (NodeType) String

func (t NodeType) String() string

type Parser

type Parser struct {
	Result *Node
	// contains filtered or unexported fields
}

func Parse

func Parse(lx *Lexer) (*Parser, error)

func (*Parser) Error

func (p *Parser) Error(s string)

func (Parser) Format

func (p Parser) Format() string

func (*Parser) Lex

func (p *Parser) Lex(val *yySymType) int

type Stack

type Stack [][2]int

func (*Stack) Pop

func (s *Stack) Pop() (int, int)

func (*Stack) Push

func (s *Stack) Push(a, b int)

type Token

type Token struct{ Sym, Pos, End, Prev int }

func (Token) String

func (t Token) String() string

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL