# EFTL language reference This is a compact index derived from the documents currently under `docs/`. Re-check the PDFs when exact wording, diagrams, or edge behavior matters. ## Documentation map - `elixForms_Doc_EFTL.pdf`: EFTL specification through the documented 3.1.0 changes, language behavior, attributes, control flow, and examples. - `elixForms_EFTLParser_syntax_rels.pdf`: generated lexer/parser relationship diagrams. - `elixForms_TAG_Sintassi.pdf`: positional syntax for the ElixForms `SCHEMAID` and `GETVALUEBYTAG` plugins. ## Common lexical and structural rules - EFTL uses square-bracket tags and requires properly nested, non-overlapping elements. - A bodyless element ends with `/]`; a block has matching opening and closing tags. - Attribute values are quoted. Attribute order is not semantically significant. - The main specification says uppercase and lowercase tag spellings are interpreted equally and recommends lowercase style. The current implementation is largely uppercase-only. - Text outside `[EFTL]...[/EFTL]` is not processed. Text inside an EFTL root but outside an executable tag is emitted as user text where the grammar permits it. - Comments use `[!-- ... --]` and may span lines. - The generated relationships include user text, ignored whitespace, CDATA, headers, comments, statements, code blocks, and output blocks. Consult the diagram PDF before enforcing a new parent/child restriction. ## Root, directives, and context | Construct | Form | Key rules | | --- | --- | --- | | EFTL | `[EFTL] ... [/EFTL]` | Root block; no documented attributes; a document needs at least one root to be processed. | | HEADER | `[HEADER name="..." value="..." type="..." /]` | Declares a directive. The documented directive is `trimDocument`, with boolean `true` or `false`. | | LOG | `[LOG] ... [/LOG]` | Writes evaluated content to the server log; no documented attributes. | Predefined execution-context names include `currentDateTime`, `defaultLocale`, `currentLocale`, and `requestId`. Other values may be supplied by the calling service. ## Variables and value functions | Construct | Form | Key rules | | --- | --- | --- | | VAR | `[VAR name="..." type="..." unique="..." ] ... [/VAR]` | `name` identifies a context variable. Documented types: `string`, `boolean`, `number`, `date`, `object`, `iterable`. `unique` defaults to `false` and is meaningful only for `iterable`. | | VALUE_OF | `[VALUE_OF varname="..." index="..." /]` | Emits a variable value. `index` identifies the position for an iterable and may name another variable. | | SIZE_OF | `[SIZE_OF varname="..." /]` | Returns iterable size, otherwise `0`. | | IS_EMPTY | `[IS_EMPTY varname="..." /]` | Tests missing, null, blank string, empty iterable, or empty map according to the documented rules. | | IS_NOT_EMPTY | `[IS_NOT_EMPTY varname="..." /]` | Logical negative of `IS_EMPTY`. | | CONTAINS | `[CONTAINS varname="..." value="..." /]` or `[CONTAINS varname="..."] ... [/CONTAINS]` | Supports string or iterable input. Attribute `value` and body are alternatives; `value` has priority when both exist. | Do not require `type` merely because current examples commonly include it: some examples omit it. Resolve requiredness from the parser relations or runtime contract before emitting an error. ## Transformations | Construct | Form | Key rules | | --- | --- | --- | | FORMAT | `[FORMAT varname="..." type="..." /]` or `[FORMAT type="..." pattern="..."] ... [/FORMAT]` | `varname` takes precedence over the body. Documented formatting covers number and date families; number modes include currency, integer, double, percent, and generic. | | SPLIT | `[SPLIT regex="..." emptyIfBlank="true|false"] ... [/SPLIT]` | Applies a valid regular expression to a string result. `emptyIfBlank` defaults to `false`. An invalid regex is a runtime parsing error and can be checked statically only for a literal. | | TRIM | `[TRIM varname="..." /]` or `[TRIM] ... [/TRIM]` | Trims a named variable or evaluated body. A found variable takes precedence; otherwise the body is evaluated. | ## Control structures - IF shape: `[IF] [CONDITION] ... [/CONDITION] [THEN] ... [/THEN] { [ELSE IF] ... [/ELSE IF] } [ELSE] ... [/ELSE] [/IF]`. - `CONDITION` must evaluate to boolean. There may be multiple `ELSE IF` blocks and at most one final `ELSE`; both are optional. - WHILE shape: `[WHILE ...] [CONDITION] ... [/CONDITION] [DO] ... [/DO] [/WHILE]`. - The WHILE section documents an optional `threshold` with default and maximum `32766`, but also contains a sentence saying the tag has no attributes. Treat this as an explicit documentation inconsistency. - FOR shape: `[FOR varName="item" iterable="items"] ... [/FOR]`. The loop variable exists during the loop and is removed afterward. - The FOR prose depends on both `varName` and `iterable`, but the generated relationship only shows a generic attribute node. Treat formal requiredness, attribute-name casing, duplicate/unknown attributes, null or non-iterable input, and shadowing as unresolved until confirmed against the runtime grammar. ## Code blocks | Kind | Form | Meaning | | --- | --- | --- | | Assignment | `[% target = expression; ... %]` | Mutates variables; documented statements end with `;`. | | Evaluation | `[% expression %]` | Evaluates and returns a result, often boolean in `CONDITION`. | | Output | `[%= variable %]` | Writes a context variable; a missing variable is a runtime error. | The expression language examples use assignment, equality/comparison, arithmetic, boolean operators, strings, numbers, booleans, and `null`. The PDFs do not provide a complete operator-precedence grammar; avoid inventing one without a runtime grammar source. ## ElixForms TAG payloads `SCHEMAID` is positional: - position 0: plugin name `SCHEMAID`; - position 1: schema ID; - position 2: column reference; - position 3: `IUQOID`; - position 4: line terminator, with a space selecting the default; - position 5: column separator; - position 6: default value; - position 7: date/time formatter; - position 8: language (documented as currently unused). Positions 0 through 4 must be present. Preserve commas for omitted intermediate optional positions. `GETVALUEBYTAG` is positional: - position 0: plugin name `GETVALUEBYTAG`; - position 1: tag name; - position 2: lookup type: `REQUEST`, `MODULE`, or `USER_PROFILE`; - position 3: `IUQOID`; - position 4: weight/order option; - position 5: column separator; - position 6: format string. The weight list in the prose and the final syntax example differ in spelling and membership (`UPDATED_FIST`/`UPDATED_FIRST`, `UPDATE_LAST`/`UPDATED_LAST`, and `CONCAT`). Treat exact validation as ambiguous until confirmed against the TAG runtime. ## Known implementation delta at skill creation The current TypeScript tokenizer/parser does not yet model all documented constructs. Notably absent or incomplete are `LOG`, `FOR`, `IS_EMPTY`, `IS_NOT_EMPTY`, case-insensitive spellings, structural ordering inside IF/WHILE, attribute validation beyond VAR type, and full expression parsing. Re-check source before relying on this list because it is expected to shrink as the linter evolves.