Get started#

SciLex is three things over one engine: a header-only C++20 library, an abi3 Python extension, and a command-line lexer. All three depend on REAL’s headers and nothing else.

C++#

The library is header-only; add REAL’s include/ and SciLex’s to the include path, or use CMake:

include(FetchContent)
FetchContent_Declare(scilex GIT_REPOSITORY https://github.com/RECHE23/scilex GIT_TAG v2026.9.1)
set(SCILEX_FETCH_DEPS ON)   # fetch REAL alongside
FetchContent_MakeAvailable(scilex)
target_link_libraries(app PRIVATE scilex::scilex)

With REAL and SciLex installed under one prefix, find_package(scilex CONFIG REQUIRED) pulls REAL in transitively.

#include <cstdio>
#include <scilex/scilex.hpp>

int main()
{
  std::vector<scilex::rule> rules {
    {.kind = 0, .pattern = real::regex(R"(\s+)"), .skip = true}, // whitespace, skipped
    {.kind = 1, .pattern = real::regex("if")},                   // keyword: before the identifier
    {.kind = 2, .pattern = real::regex("[a-z_][a-z0-9_]*")},     // identifier
    {.kind = 3, .pattern = real::regex("[0-9]+")},               // number
    {.kind = 4, .pattern = real::regex(R"([-+*/=])")},           // operator
  };
  const scilex::lexer lexer {std::move(rules)};
  for (const scilex::token& tok : lexer.scan("if x + 42")) {
    std::printf("%d %.*s\n", tok.kind, static_cast<int>(tok.lexeme.size()), tok.lexeme.data());
  }
}

if is listed before the identifier rule: both match two bytes of if, and on a tie the earlier rule wins. scan yields one token per step; tokenize returns them all in a vector.

Python#

pip install scilex

The wheel is cp311-abi3 (CPython 3.11 and later). A rule is (kind, pattern), optionally followed by skip, the modes it is active in, and a mode action:

import scilex

lx = scilex.Lexer([(0, r"\s+", True), (1, r"[0-9]+"), (2, r"[a-z]+")])
for tok in lx.scan("abc 42"):
    print(tok.kind, tok.lexeme, tok.position)

scilex.get_include() returns the installed headers’ directory, for compiling C++ against the same version.

The command line#

make cli builds build/bin/scilex. It lexes with a built-in grammar or with yours:

$ scilex --list                       # the built-in example grammars
$ scilex --example json file.json     # lex a file with one
$ echo 'x = 41 + 1' | scilex my.lex   # or with a .lex grammar of your own
IDENT	x	1:1
OP	=	1:3
NUMBER	41	1:5
OP	+	1:8
NUMBER	1	1:10

--layout adds the indentation tokens, --errors=token recovers from unlexable bytes instead of stopping, and --columns=codepoints or --columns=utf16 counts columns in those units. The grammar format is described in The .lex grammar format.