Files
masonry/lang/lang.go
2025-08-15 01:51:43 -06:00

182 lines
5.2 KiB
Go

package lang
import (
"github.com/alecthomas/participle/v2"
)
// Root AST node containing all definitions
type AST struct {
Definitions []Definition `parser:"@@*"`
}
// Union type for top-level definitions
type Definition struct {
Server *Server `parser:"@@"`
Entity *Entity `parser:"| @@"`
Endpoint *Endpoint `parser:"| @@"`
Page *Page `parser:"| @@"`
}
// Clean server syntax
type Server struct {
Name string `parser:"'server' @Ident"`
Settings []ServerSetting `parser:"@@*"`
}
type ServerSetting struct {
Host *string `parser:"('host' @String)"`
Port *int `parser:"| ('port' @Int)"`
}
// Clean entity syntax with better readability
type Entity struct {
Name string `parser:"'entity' @Ident"`
Description *string `parser:"('desc' @String)?"`
Fields []Field `parser:"@@*"`
}
// Much cleaner field syntax
type Field struct {
Name string `parser:"@Ident ':'"`
Type string `parser:"@Ident"`
Required bool `parser:"@'required'?"`
Unique bool `parser:"@'unique'?"`
Index bool `parser:"@'indexed'?"`
Default *string `parser:"('default' @String)?"`
Validations []Validation `parser:"@@*"`
Relationship *Relationship `parser:"@@?"`
}
// Simple validation syntax
type Validation struct {
Type string `parser:"'validate' @Ident"`
Value *string `parser:"@String?"`
}
// Clear relationship syntax
type Relationship struct {
Type string `parser:"'relates' 'to' @Ident"`
Cardinality string `parser:"'as' @('one' | 'many')"`
ForeignKey *string `parser:"('via' @String)?"`
Through *string `parser:"('through' @String)?"`
}
// Endpoint definitions with clean, readable syntax
type Endpoint struct {
Method string `parser:"'endpoint' @('GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH')"`
Path string `parser:"@String"`
Entity *string `parser:"('for' @Ident)?"`
Description *string `parser:"('desc' @String)?"`
Auth bool `parser:"@'auth'?"`
Params []EndpointParam `parser:"@@*"`
Response *ResponseSpec `parser:"@@?"`
CustomLogic *string `parser:"('custom' @String)?"`
}
// Clean parameter syntax
type EndpointParam struct {
Name string `parser:"'param' @Ident ':'"`
Type string `parser:"@Ident"`
Required bool `parser:"@'required'?"`
Source string `parser:"'from' @('path' | 'query' | 'body')"`
}
// Response specification
type ResponseSpec struct {
Type string `parser:"'returns' @Ident"`
Format *string `parser:"('as' @String)?"`
Fields []string `parser:"('fields' '[' @Ident (',' @Ident)* ']')?"`
}
// Page definitions for frontend with clean syntax
type Page struct {
Name string `parser:"'page' @Ident"`
Path string `parser:"'at' @String"`
Layout string `parser:"'layout' @Ident"`
Title *string `parser:"('title' @String)?"`
Description *string `parser:"('desc' @String)?"`
Auth bool `parser:"@'auth'?"`
Meta []MetaTag `parser:"@@*"`
Components []Component `parser:"@@*"`
}
// Meta tags for SEO
type MetaTag struct {
Name string `parser:"'meta' @Ident"`
Content string `parser:"@String"`
}
// Component definitions with endpoint references
type Component struct {
Type string `parser:"'component' @Ident"`
Entity *string `parser:"('for' @Ident)?"`
Config []ComponentAttr `parser:"@@*"`
}
// Component attributes and configurations
type ComponentAttr struct {
Fields *ComponentFields `parser:"@@"`
Actions *ComponentActions `parser:"| @@"`
DataSource *ComponentDataSource `parser:"| @@"`
Style *ComponentStyle `parser:"| @@"`
Pagination *ComponentPagination `parser:"| @@"`
Filters *ComponentFilters `parser:"| @@"`
Validation bool `parser:"| @'validate'"`
}
// Component field specification
type ComponentFields struct {
Fields []string `parser:"'fields' '[' @Ident (',' @Ident)* ']'"`
}
// Component actions (can reference endpoints)
type ComponentActions struct {
Actions []ComponentAction `parser:"'actions' '[' @@ (',' @@)* ']'"`
}
type ComponentAction struct {
Name string `parser:"@Ident"`
Endpoint *string `parser:"('via' @String)?"`
}
// Data source configuration (can reference endpoints)
type ComponentDataSource struct {
Endpoint string `parser:"'data' 'from' @String"`
}
// Component styling
type ComponentStyle struct {
Theme *string `parser:"'style' @Ident"`
Classes []string `parser:"('classes' '[' @String (',' @String)* ']')?"`
}
// Pagination configuration
type ComponentPagination struct {
PageSize *int `parser:"'pagination' ('size' @Int)?"`
}
// Filter specifications
type ComponentFilters struct {
Filters []ComponentFilter `parser:"'filters' '[' @@ (',' @@)* ']'"`
}
type ComponentFilter struct {
Field string `parser:"@Ident"`
Type string `parser:"'as' @('text' | 'select' | 'date' | 'number')"`
Label *string `parser:"('label' @String)?"`
}
func ParseInput(input string) (AST, error) {
parser, err := participle.Build[AST](
participle.Unquote("String"),
)
if err != nil {
return AST{}, err
}
ast, err := parser.ParseString("", input)
if err != nil {
return AST{}, err
}
return *ast, nil
}