Syntax - nchauhan890/leaf-language GitHub Wiki
Syntax
This section describes the syntax rules for Leaf
Numbers
The syntax for numbers only accepts integers, and numbers with a deciaml point. Possible number forms:
>>> 123
123
>>> 12.3
12.3
>>> 123.
123
>>> 123.0
123.0
Strings
Strings are enclosed in single quotes (''
) and single quotes may not be escaped, however,
newline characters may be used with \n
. A newline character can be escaped by using a
double backslash \\n
. Strings implicitly continue on newlines, however the newline character
is ignored
Examples of strings:
>>> 'Hello world!'
Hello world!
>>> 'First line\nSecond line'
First line
Second line
>>> 'First line\\nStill on the first line'
First line\nStill on the first line
>>> 'First line
Also the first line'
First lineAlso the first line
Lists
Lists are denoted by square brackets, which may contain a number of expressions which are separated by commas:
>>> [1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
>>> [String, 1 + 1, true]
[<type String from built-ins>, 2, true]
Assignments
Assignments use the assignment operator <<
and support multiple assignments:
str << 'hello world'
str, decimal, int << 'leaf', 4.53, 86
In a multiple assignment, there must be the same number of target names as objects (Note that this isn't always true - i.e. when using iterable unpacking).
Function calls
Function calls use the function name followed by an opening square bracket, function arguments, modifiers/flags and a closing square bracket.
Modifiers begin with a tilde (~
), the modifier name, an assignment operator and
an expression. Flags begin with a tilde also, but only have the flag name afterwards.
Possible function calls:
>>> show[1, 2, 3 ~end << '' ~comma_sep]
1, 2, 3>>>
>>> show[]
>>>
>>> show[1]
1
>>> show[~no_newline]
>>>
>>> show[~end << 'END']
>>>
Booleans
Leaf support the boolean values true
and false
. They have a respective value of 1
and 0
and function
similarly to these numbers in arithmetic since they derive Number
. They must be written in lowercase only
in code and display with their corresponding name.
Indentation
Indentation is denoted by the pipe character (|
). It is used in conditionals, loops and function definitions
Each new level of indentation must have the appropriate number of indentation characters. Indentation characters
do not need to be written next to each other; they can be written spaced out to ease readability like the following:
if[a <= 10],then
| show[a, 'is less than or equal to 10;' ~ end << ' ']
| if [a = 5], then
| | show[a, 'is equal to 5;' ~ end << ' ']
| | if [a > 0], then
| | | show[a, 'is more than 0;' ~ end << ' ']
| | endif
| endif
endif
Each level of indentation usually ends with a keyword like endif
to denote the end of the current
indentation level.
If statements
If statements use the if
, then
, else
and endif
keywords. The expression, denoted by expr
is evalutated to its boolean value and the body under each section of the if statement must be indented. Possible if statement forms:
if [expr], then
| ...
endif
if [expr], then
| ...
else, if [expr], then
| ...
endif
if [expr], then
| ...
else
| ...
endif
if [expr], then
| ...
else, if [expr], then
| ...
else
| ...
endif
If statements can contain a variable number of else, if
clauses in them. Nested if statements must be indented
the appropriate number of indentation characters.
While/Until loops
While and until loops use the while
, until
, loop
and endloop
. They continously loop until the condition
specified at the top is either true or false: while
loops repeat until false
and until
loops repeat until true
. The syntax for while and untils loops are as follows:
while [expr_is_true], loop
| ...
endloop
until [expr_is_false], loop
| ...
endloop
For loops
For loops use the for
, in
, loop
and endloop
keywords. They iterate over any iterable and set the value
of the variable(s) specified to the next value in the iterable on each iteration. This is the syntax for for
loops:
for [item] in [iterable], loop
| ... (use 'item' here)
endloop
Loop Control
There are 2 ways that loops can be controlled: the break
and next
statements. The break
statement ends the loop
from inside it - this may occur when it is triggered by an if statement. The next
statement starts the next
repetition of the loop - in a for loop, it causes the for loop's variables to obtain their next values.
They are used as stand-alone statements and cannot appear within expressions. Note that an error will be raised if either are used outside of a loop context
Iterable unpacking
Iterable unpacking is a way to obtain each item in an iterable in a List
. The syntax used is a colon (:
).
This can be useful in the following situations:
For loops:
In a for loop, if you need to split each item into separate variables, iterable unpacking can be used in the for loop's definition. Consider the following:
grid = ['A1', 'A2', 'B1', 'B2']
for [row, col] in [:grid], loop
| show['row:', row, 'col:', col]
endloop
This outputs:
row: A col: 2
row: B col: 1
row: B col: 2
This can only be obtained using iterable unpacking - however, a problem here is that there must be a constant number of items to unpack in each cycle returned by the iterable otherwise an error will be raised
Function calls:
When calling functions, iterables can be used as separate arguments like so:
>>> values << [1, 2, 3]
>>> show['hey', :values]
hey 1 2 3
Multiple assignments:
This can be used to get around the limitation of same-number unpacking in for loops. Unpacking can occur on either the left or right side of the assignment and each variation performs a different function:
>>> a, b, c << :[1, 2], 3
>>> show[a, b, c]
1 2 3
>>> first, :last << :[1, 2], 3, [4, 5]
>>> first
1
>>> last
[2, 3, 4, 5]