Logic Block

A logic block tests values rather than text. It reads no input and moves no cursor: it succeeds or it fails, and consumes nothing either way. That is what lets a grammar decide something instead of merely matching it.

It is written between curly braces.

A = {5 * 5 == 20};
B = (char => numvar x) . (char => numvar y) . {y = 15; x * y == 65};

A fails, because 5 * 5 == 20 is false. In B two characters are captured, y is set to 15, and the block succeeds only if x * y == 65.

What a block answers

A logic block answers true or false, and true is the default.

Statements are separated by ;, and the last one’s value is the block’s answer. A statement that produced no value — an assignment, a cleared set — is a deed rather than an answer, and a deed is no reason to fail. So a block whose last statement is an assignment holds.

{x == "cat"}          # answers the comparison
{y = 15; x * y == 65} # a deed, then an answer
{y = 15}              # only a deed -- holds

The final block

{{ ... }} is a final block. It runs for what it does, and its result is not checked — it always holds.

B := "a" . {{9 => n}};

Use it when the point is the effect rather than the verdict: setting a variable, clearing a set, counting something. Nothing may follow a final block in the grammar, because there is no outcome for the rest to depend on.

The difference in one line: an ordinary block can fail the action it sits in, a final block cannot.

Operators

Precedence follows C, tightest binding first: NOT, then * /, then + -, then < <= > >=, then == !=, then AND, then OR. Brackets override it.

NOT a
a * b   a / b    # division by zero is 0
a + b   a - b    # a - b clamps at 0 rather than wrapping
a < b   a <= b   a > b   a >= b
a == b  a != b
a AND b
a OR b
TRUE  FALSE      # one and zero

AND and OR short-circuit, the way C’s && and || do: the right side is not evaluated when the left has already settled the answer.

Text compares by bytes, and == and != are the only operators it has — arithmetic over text is refused when the grammar is validated, not at run time.

Asking about a semvar

set::is(t)     # is t a member?
set::not(t)    # is it not?
set::clear     # empty the set -- a deed, so it holds

See also

A logic block is also the condition of an IF statement, and it reads values put into Variables with =>. To stop the parse outright rather than fail a match, see System Functions.