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 }