Type an axiom, list your production rules, pick a depth. The page rewrites the string, counts what came out of every pass, walks the turtle, then hands you the curve as an SVG with one path in it. You decide which letters draw a line and which only carry structure, so a Hilbert curve and a Gosper curve both work without editing the code.
F = FF, F -> FF and F: FF all parse. A letter with no rule survives the pass unchanged.String length after each rewrite pass, with the factor against the pass before it.
| Pass | Symbols | Factor |
|---|
What the final string holds, sorted by the job each character does when the turtle reads it.
Every rewrite pass replaces all symbols at once. A rule whose body holds four copies of its own head multiplies the string by roughly four per pass, and the factor column in the ladder settles on that number after two or three passes. Once you read the factor, the next depth stops being a surprise. Depth 8 on a rule with factor 4 is 65,536 times the axiom.
The ladder is the reason this page shows the count before the picture. A grammar that looks harmless in the textarea reaches seven figures in nine passes, and a browser tab does not warn you first. Rewriting stops at 1.5 million symbols and the ladder marks the pass where the ceiling landed, so you lower the depth instead of waiting on a frozen tab.
Segments matter more than symbols. Turns and brackets cost nothing to draw. The Levy C curve at depth 12 carries 20,476 symbols but paints only 4,096 lines, while the fractal plant at depth 6 paints 6,048 from 25,159. Watch the line segment counter when the render slows down.
| Starter | Depth | Symbols | Segments | Growth |
|---|---|---|---|---|
| Koch snowflake | 4 | 1,792 | 768 | 4x |
| Sierpinski | 5 | 1,215 | 729 | 3x |
| Dragon curve | 11 | 8,190 | 2,048 | 2x |
| Hilbert curve | 5 | 3,411 | 1,023 | 4x |
| Gosper curve | 4 | 5,601 | 2,401 | 7x |
| Fractal plant | 6 | 25,159 | 6,048 | 4x |
| Binary tree | 7 | 1,084 | 576 | 2x |
| Levy C curve | 12 | 20,476 | 4,096 | 2x |
Gosper is the one to watch. Its ladder reads 1, 15, 113, 799, 5,601, 39,215, 274,513, and the next pass crosses the ceiling. Seven per pass is why the button loads depth 4 rather than something deeper.
Most L-system pages hard-code F as the forward stroke. That works until you type two of the classic curves side by side. Hilbert is written with A and B as scaffolding that never draws, and the actual strokes come from F. Gosper is written the other way around: A and B are the strokes and there is no F anywhere in the rules. A fixed alphabet gets one of them wrong, and the usual result is a Hilbert curve with a stray line through the middle of every cell.
Naming the drawing letters yourself settles the conflict. Load Hilbert and the field reads F. Load Gosper and it reads A B. Paste a grammar from a paper, read which letters the author called turtle commands, type those. Anything left over becomes rewrite-only and shows up in the amber row of the census, which is a quick way to spot a letter you meant to draw with.
Brackets are checked as the turtle walks. A closing bracket with nothing on the stack is skipped rather than guessed at, and both that count and the number left open at the end are reported above the stats. Unbalanced brackets are the usual cause of a plant that drifts off one side of the frame, because branches that never returned to the trunk keep extending from wherever they stopped.
The turtle always walks with a step length of one. Coordinates come out in abstract units, the bounding box gets measured, and only then does the drawing get scaled into the frame. Fit to frame divides the frame size by the bounding box, so a Koch snowflake at depth 2 and the same snowflake at depth 6 fill the same space. The step field is greyed out while fit is on because nothing it changes survives the rescale.
Turn fit off and the step field becomes pixels per forward move. Fixed step is what you want when comparing two depths at the same scale, since the curve then grows outward instead of tightening inward. The span readout tells you the bounding box in step units, so a span of 12 by 9 at a step of 20 needs a 240 by 180 pixel area to sit inside.
Start heading rotates the whole figure before the walk. Zero points right, 90 points up. Branching grammars read better at 90 because the trunk grows upward, so the plant and binary tree buttons set it for you. The other six start at zero.
Save SVG writes every segment into one <path> element. Runs of connected moves become a single subpath, so a Hilbert curve at depth 5 leaves as one continuous line rather than 1,023 separate shapes. That is the shape a pen plotter, a vinyl cutter or a laser wants to see, because each subpath is one uninterrupted tool movement. The viewBox is sized to the bounding box with a small margin, so the file scales to any output size without a resample.
PNG export copies the canvas at its current pixel size, which stays useful for a slide or a forum post. It carries the same limits any raster has: zoom in past the export size and the lines soften. Reach for SVG when the drawing is going anywhere near a physical machine or a print job, and PNG when it is going into a document.
Copy expanded string hands you the final string as plain text. Useful when you want to interpret the same grammar in Python, Processing or a shader, since the rewrite is the expensive part and the drawing after it is a short loop.
The grammar here is deterministic and context-free, which covers the classic curves and most of what a first course on Lindenmayer systems asks for. Three families sit outside it.
A < B > C that fire only when neighbours match. Signal propagation along a stem needs them.F(3.5), so segment length or angle varies per branch. This turtle uses one length and one angle for the whole string, which is why every branch of the binary tree has the same thickness and reach.Two more limits worth knowing. Drawing stops after 220,000 segments, and past that the string is still walked for the bounding box but the extra lines never get painted, which reads as a curve that looks complete yet thins out in one corner. Rule bodies are stripped of spaces before use, so a production cannot contain a literal space.
For a lighter path to the same shapes, the L-System Visualizer covers the same grammar with a fixed alphabet and no counting. If you want one curve with dedicated sliders rather than rules to write, the Koch Snowflake Generator, the Dragon Curve Generator and the Hilbert Curve Generator skip the grammar step. Ferns built from affine maps instead of strings belong in the Barnsley Fern Generator.
Answers tied to how this parser and turtle behave.
The expanded string holds no letter listed in the draw symbols field. Placeholder grammars start this way: an axiom of X with a rule that turns X into F sequences draws nothing at depth 0, because the first F only appears after a pass. Raise the depth, or add the letter your rules use for strokes to the draw field.
The string length after a pass divided by the length before it. It settles quickly on the dominant growth rate of your rules, so once two passes agree you can predict any deeper level by multiplying. A factor of 4 means each extra depth is four times the work.
Yes. Type them in the draw symbols field, separated by spaces or nothing at all. The Gosper starter uses A and B as strokes. Case matters, so A and a are treated as different symbols.
They pass through every rewrite unchanged. This is standard L-system behaviour and it is how turn and bracket characters survive to the end. A letter that is neither a draw symbol nor a turtle command shows up under rewrite-only in the census.
Fit to frame is on, and fit rescales the finished drawing to the frame regardless of step length. Uncheck it and the field turns on, at which point step becomes pixels per forward move and the drawing can extend past the frame edges.
One path element. Connected segments are written as continuous subpaths, so a curve drawn without lifting the pen stays a single subpath. Bracketed grammars produce one subpath per branch, since popping the stack moves the pen without drawing.
The depth control stops at 14, and rewriting stops earlier if the string passes 1.5 million symbols. Both are there so a mistyped rule cannot lock up the tab. The ladder names the pass where the ceiling was reached.
No. Rewriting, drawing and exporting all run in your browser. The grammar never leaves the page, and closing the tab discards it.