Ruby lexer tooling for parser authors

Write lexers in Ruby. See why each token wins.

flexr lets you write a lexer specification as ordinary Ruby, run it while developing, inspect its matching behavior, and generate deterministic Ruby for deployment.

lexer.flexr.rb
class Lexer < Flexr::Lexer
  rule(/==/) { emit :EQ }
  rule(/=/)  { emit :ASSIGN }
  rule(/if/) { emit :IF }
  rule(/[a-z_][a-z0-9_]*/) { emit :IDENT }
end
input: if == totalstep 02
/==/ → EQlongest match · 2 chars
/=/ → ASSIGNshorter match · 1 char
Why flexr

One specification, two useful ways to run it.

Keep the feedback loop in Ruby. When the lexer is ready to ship, compile the same rules into a predictable artifact and keep the behavior easy to reason about.

01 / RUBY-NATIVE

Ordinary Ruby specifications

Use classes, constants, interpolation, and familiar Ruby actions without learning a separate lexer language.

02 / DECISIONS

Matching you can explain

Longest match wins. If matches have the same length, the rule defined first wins. The contract stays visible.

03 / PARITY

Runtime and generated parity

Develop with the runtime interpreter, then compare its token stream with generated Ruby before deployment.

04 / DIAGNOSTICS

Actionable checks

Find unsupported regexp constructs, unreachable rules, undeclared tokens, and other problems before they reach a parser.

A practical workflow

Write. Inspect. Generate. Integrate.

01

Write

Define rules and actions in a Ruby class that looks like the code around it.

02

Inspect

Check the specification and make a matching decision visible when rules compete.

03

Generate

Produce deterministic Ruby for environments where startup and deployment shape matter.

04

Integrate

Return tokens to Racc, Lrama, or your own parser protocol with explicit locations.

Choose your mode

Fast feedback first. Reproducible output when it matters.

Both modes consume the same lexer design. The choice is about the deployment boundary, not a second language.

Runtime mode

Load the specification directly with the flexr runtime. It is a strong fit for iteration, tests, and applications that value a compact source of truth.

Generated mode

Compile the specification to Ruby and commit or build the generated artifact. Use standalone output when the deployed process should not load the gem at runtime.

Make the boundary explicit

Useful power, clear constraints.

flexr is designed to be inspectable. Know what runs at build time, what remains Ruby code, and what the regexp compiler accepts.

SECURITY

Actions are Ruby code

Only run specifications and generated artifacts you trust. Static checks do not make arbitrary actions safe.

COMPATIBILITY

Regexp support is documented

Check the compatibility matrix before porting lookarounds, backreferences, or open-ended repetition.

EXPERIMENTAL

Experimental features say so

firstmatch is experimental because it changes the usual longest-match contract and needs an explicit option.

OPEN SOURCE

Read the implementation

Inspect examples, diagnostics, generated output, and the benchmark log in the repository.