Skip to content
LexerLangv0.1.0

Syntax

File layout, naming rules, blocks, switch and operators.

Every file follows the same order:

LexerLang
package <name>        # required, first line
use <module>, ...     # immediately after package
<body>
LexerLang
package hello

use http_server, html_document

$app = new http_server

Extensions: .lexer for an entry file, .lx for a page or library file.

Naming#

A name must be either all lowercase or all uppercase:

LexerLang
http_request   form_data   a1        # valid — ordinary names
POST   GET   MAX_SIZE                # valid — constants
Person   HttpClient                  # valid — class names
LexerLang
myVar   formData   $Ad               # invalid — mixed case

Starting with a capital is valid only for class names. A name that starts lowercase and contains a capital is invalid everywhere.

Digits and _ are allowed in both forms. Keywords are lowercase only; writing IF is an error.

Blocks#

Every construct that opens a block closes with end <keyword>. There are no braces, and indentation is significant.

LexerLang
if $a == 10 then
    out("10")
else
    out("other")
end if

for $lang in $languages
    out($lang)
end for

while $i > 0
    $i = $i - 1
end while

func add($a, $b) as int32
    return $a + $b
end func

with $app
    .document.add($doc)
end with

Inside a with block, lines beginning with a dot apply to the block's subject: .document.add($doc) means $app.document.add($doc).

On one line#

: is the statement separator for single-line forms:

LexerLang
if $a == 10 then: out("10"): end if
func double($x): return $x * 2: end func

switch#

Tests one value against several possibilities:

LexerLang
switch $req.path
    case "/login", "/register"
        $app.layout($auth_layout)
    case in $admin_paths
        $app.layout($admin_layout)
    default
        $app.layout($shop_layout)
end switch
FormMeaning
case "a", "b"if any of the values match
case in $arrayif the subject is in the array
defaultif nothing matched; must be the last branch

The subject is evaluated once: a call with side effects running again in every branch would be a surprise.

The first matching branch runs and the switch ends — there is no fall-through. C's behaviour quietly ran the wrong branch too whenever someone forgot a break.

If nothing matches and there is no default, nothing happens. No free statements are allowed between branches: only case and default.

Operators#

&& and || may be written instead of and and or; they are the same operators, and the choice is a matter of style. Negation is not only.

LexerLang
if $stock > 0 && $product.active then: out("sellable"): end if
if $role == "admin" || $role == "editor" then: out("authorised"): end if
if not $cart then: out("cart is empty"): end if

A single & or | does not exist. The language has no bitwise operations, so someone writing a single character has almost always forgotten the second one; quietly giving it another meaning would be wrong.

Anonymous functions#

func can also be written as an expression. It sees the variables where it was defined:

LexerLang
$factor = 3
$times = func($x) as int32
    return $x * $factor
end func

out($times(5))             # 15

Route tables and session.with_lock use this.

Commas in objects#

Commas are not required in an object literal; a new field is recognised from the name: form. This is so that tables whose values are blocks do not need a comma after every end func:

LexerLang
{
    "/": func($req, $res) as void
        $res.send("a")
    end func

    "/b": func($req, $res) as void
        $res.send("b")
    end func
}

Comments#

LexerLang
# one line

###
Several
lines.
###

Next#

Types and variables.