Another way is to use leex and yecc…
If you put this in src folder… into string_lexer.xrl.
Definitions.
WHITESPACE = [\s\t]
TERMINATOR = \n|\r\n|\r
Rules.
\( : {token, {'(', TokenLine}}.
\) : {token, {')', TokenLine}}.
or : {token, {union, TokenLine, atom(TokenChars)}}.
and : {token, {intersection, TokenLine, atom(TokenChars)}}.
true : {token, {true, TokenLine, atom(TokenChars)}}.
false : {token, {false, TokenLine, atom(TokenChars)}}.
{WHITESPACE} : skip_token.
{TERMINATOR} : skip_token.
Erlang code.
atom(TokenChars) -> list_to_atom(TokenChars).
Then You could
iex> {:ok, tokens, _} = :string_lexer.string "(false and (true or true) or (true and (false or false)))" |> to_charlist()
{:ok,
[
{:"(", 1},
{false, 1, false},
{:intersection, 1, :and},
{:"(", 1},
{true, 1, true},
{:union, 1, :or},
{true, 1, true},
{:")", 1},
{:union, 1, :or},
{:"(", 1},
{true, 1, true},
{:intersection, 1, :and},
{:"(", 1},
{false, 1, false},
{:union, 1, :or},
{false, 1, false},
{:")", 1},
{:")", 1},
{:")", 1}
], 1}
And You could parse those tokens with yecc, You just need a grammar file 