Switching between them happens when the parser encounters the special
characters { and }. The parser is
recursive—if, for example, it is in Lisp mode and the { is
encountered, it does not terminate the current Lisp
expression—instead it just reads a chunk of raw text that will be inserted
in the current place of the lisp expression as a string. Therefore you
can write for example:

At that point it starts reading one Lisp expression, after which it
expects the closing bracket.

If, while reading Lisp tokens, it encounters the open bracket, it
switches to raw text mode and reads until the closing bracket is
encountered.

These parser modes are recursive—that is, if in raw text mode we
encounter an open bracket, we enter Lisp mode to read one expression,
then we return to the text mode; similarly, if in Lisp mode we encounter
the open bracket we enter raw mode, and a strcat
expression will be returned in the AST.

A “raw text” could simply be a string, but more generally it'll
contain multiple chunks (strings mixed with Lisp expressions), therefore
the parser passes all those chunks to “strcat”.

“strcat” joins all non-NIL arguments that it receives and returns a
string. The arguments are forced to string, if needed, via Common
Lisp's "~A" format argument (except lists, which are simply
joined).

Whitespace is kept faithfully; usually in HTML it won't be a problem,
but there are various tricks you can use to control whitespace.

By default the result of each Lisp expression is inserted into the
output, unless it's NIL. Syntactic sugar is provided to
call functions without including the result (using [square brackets]
instead of regular parens).

Executing a template is a matter of executing this big “strcat”
expression.

By default the result of Lisp expressions is inserted literally, rather
than escaped. I've experimented a lot with both default ways (also with
trying to make the parser read my mind, which I failed)—in short, my
conclusion is that auto-escaping by default is more of an annoyance than a
benefit. Note, therefore, that the last example includes a backslash
before expressions that I wanted to escape, like {\name}—that's just syntactic sugar equivalent
to {(esc name)}.