--- doc: five-syntax title: Five language syntax reference keywords: [syntax, grammar, FUNCTION, LOCAL, IF, FOR, DO WHILE, DO CASE, code block, string literal, array, hash, operators, IIF, BEGIN SEQUENCE] summary: Core Five/xBase syntax an LLM needs to write correct code — declarations, literals, operators, control flow, code blocks. Confirmed against the lexer/parser and real solmade usage. --- # Five syntax reference Case-insensitive for keywords AND identifiers (`LOCAL`/`local`, `x`/`X` are the same). Arrays/strings are **1-based**. Strings do **not** process C escapes (see gotchas). ## Program structure ```five FUNCTION Main() LOCAL nTotal := CalcSum( 10, 20 ) ? "Result:", nTotal RETURN nTotal FUNCTION CalcSum( nA, nB ) RETURN nA + nB PROCEDURE ShowMessage() // PROCEDURE returns NIL implicitly ? "Hello" RETURN STATIC FUNCTION Helper( x ) // STATIC = file-local visibility RETURN x * 2 ``` ## Variable declaration Declarations come **first**, before executable statements. ```five LOCAL x := 10 // init with := LOCAL a, b, c := 20 // only c is initialized; a,b are NIL STATIC s_count := 0 // persists across calls (file-level or in-func) PUBLIC nGlobal := 100 // runtime memvar, global PRIVATE nScoped := 50 // runtime memvar, dynamic scope ``` Pass-by-reference uses `@` at the call site: ```five FUNCTION Inc( x ) x := x + 1 RETURN NIL // ... LOCAL n := 10 Inc( @n ) // n is now 11 ``` ## Literals ```five LOCAL n := 42 // number LOCAL f := 3.14 LOCAL c1 := "double quotes" // string LOCAL c2 := 'single quotes' // string (equivalent; NO escape processing in either) LOCAL c3 := [bracket string] // string; supports nested [ ] LOCAL lT := .T. // logical true (.t. ok) LOCAL lF := .F. // logical false LOCAL x := NIL // null/undefined LOCAL a := { 1, 2, 3 } // array literal, 1-based LOCAL h := { "k" => "v" } // hash literal LOCAL e := {=>} // empty hash LOCAL b := {| p1, p2 | p1 + p2 } // code block (closure); no-arg form: {|| expr} ``` Access: `a[1]` (first element), `h["k"]`, `h["new"] := 1` (add/update). ## Operators ```five := += -= *= /= %= **= // assignment / compound assignment == = // equality (= also assigns in some contexts; prefer == for compare) != <> # // not equal (three spellings) < > <= >= $ // substring containment: "ell" $ "hello" => .T. + - * / % ** ^ // arithmetic (** and ^ = power); + also concatenates strings .AND. .OR. .NOT. // logical (short-circuit); aliases: && || ! ++ -- // increment / decrement ``` ## Control flow ```five IF cond // ... ELSEIF cond2 // ... ELSE // ... ENDIF DO WHILE cond // ... IF skip ; LOOP ; ENDIF // LOOP = continue IF stop ; EXIT ; ENDIF // EXIT = break ENDDO FOR i := 1 TO 10 // optional STEP: FOR i := 10 TO 1 STEP -1 ? i NEXT FOR EACH item IN aArray ? item NEXT DO CASE CASE x == 1 // ... CASE x == 2 // ... OTHERWISE // ... ENDCASE BEGIN SEQUENCE // structured error handling risky() RECOVER ? "error caught" END SEQUENCE ``` Inline conditional (expression, not statement): ```five cResult := IIF( x > 10, "big", "small" ) // Iif() also works ``` ## Statement continuation & comments ```five LOCAL s := "a" + ; // trailing ';' continues the statement on the next line "b" + ; "c" // single-line comment /* multi-line comment */ ``` ## Advanced features (verify against parser before relying on these) The compiler/parser also supports OOP (`CLASS ... ENDCLASS`, `METHOD ... CLASS X`, `::member`, `INHERIT FROM`), and Go-inspired concurrency (`GO {|| ...}`, channels `<-`, `WATCH`/`ENDWATCH` select, `DEFER`). These appear in the grammar but are uncommon in the solmade app; if you need them, confirm exact syntax in `compiler/parser` and `examples/` first rather than assuming Harbour-standard behavior.