Support deprecated Gerber syntax via a refactored tokenizer - #25
Support deprecated Gerber syntax via a refactored tokenizer#25nicolube wants to merge 6 commits into
Conversation
Commands are delimited by `*`, not newlines (spec 4.1). The old line-based tokenizer merged single-line files into one block, causing a spurious CoordinateDataWithoutOperationCode error. Now splits on `*`, treats `%...%` spans (incl. macros) as one block, and ends a block at a newline outside such spans.
Parse errors carried only a (line, content) tuple. Replace it with an ErrorContext { line, offset, token } so callers can pinpoint which command failed, which matters when several are packed onto one line. Also funnel outer parse_line errors through the context path instead of dropping them.
ViewMate and other tools emit G1/G2/G3 instead of G01/G02/G03 (spec 8.3 style variation). These fell through to UnknownCommand, so the interpolate never registered and modal D01 never armed, cascading into spurious CoordinateDataWithoutOperationCode errors across every region. Accept the single-digit forms, disambiguating G3 from the G36/G37 region commands.
|
@hydra Pls review the PR carefully, this is a hevy one with breaking API changes. |
|
Finally got some time to try this, things have been somehwat busy recently and my focus has been elsewhere. anyway, this PR has the exact same problem as or #26 as per my message: #26 (comment)
|
|
@hydra Hey it seems like u have escapes within ur gcode wich the tokenizer currently not supports: G04 %MIB1*% *
G04 %IR180*% *
G04 %SFA1.5B3*% *
G04 %OFA60B60*% *
G04 %ASAYBX*% *I will have a look at it soon... |
|
@hydra After a quick look into gerber spec section 3.15 (G04) specifies that comment content must be acording to section 3.6.6 wich explicely forbits So technicly ur gerber is invalid.
|
|
Ahh, I got an old refrence, they have been allowed at a later date... |
|
Well it is still out of spec.... |
Gerber spec 3.4.3 requires \, *, and % to be backslash-escaped inside strings. The tokenizer treated every raw * and % as a delimiter, so an escaped one inside a comment or TF/TA/TO value truncated the block early.
8717e4f to
7d1822e
Compare
|
Ahh yes, this block from The previous new-line based approach was able handle them as it didn't care about the comment content. The documentation of the spec isn't particularly clear about escape sequences, but this is what I read today: Gerber Spec 2026.05, section 3.4.3 Strings
Note: There is no mention of a non-unicode (c-style) escape sequence. e.g. See also section 3.4.4
I think we need a round-trip test like the ones in |
|
Well also 3.4.3:
Then on next page same section:
Sound for me like I could escape them with Want me to keep the escaping (7d1822e) or drop it? |
|
from the changes, there's this snippet from one of the tests: This doesn't like right to me, given the spec. I don't see anything in the spec that suggests that escaping
and
We need a test for the fields, since there Or am I missing something in the spec? |
|
@hydra Shall we parse unicode escapes into unicode chars, or keep as is? |
This reverts commit 7d1822e. Gerber spec 3.4.3 defines only unicode escapes (\uXXXX, \UXXXXXXXX); there is no C-style `\*` form, and 3.4.4 excludes `*`/`%` from the field grammar outright. A conforming string therefore never contains a raw delimiter, so the tokenizer needs no escape awareness.
Gerber spec 3.4.3/3.4.4: reserved characters (`*`, `%`, `\`, and `,` in fields) are written as unicode escapes, so a conforming string cannot contain a block delimiter. Escapes are kept verbatim, making the gbr -> rust -> gbr round-trip byte-exact.


Some copper layers exported from ViewMate Pro failed to load — a flood of CoordinateDataWithoutOperationCode errors. Root cause was a mix of newline-based tokenizing and a couple of unsupported deprecated constructs from the Gerber spec. This PR
refactors the tokenizer and adds support for the missing syntax.
Refactored tokenizer (Gerber spec §4.1)
Per §4.1, commands are delimited by the end-of-block character *; newlines are insignificant whitespace. The old tokenizer split input line-by-line, so files that pack the whole stream onto one physical line were parsed as a single command and fell
apart.
Reworked it into a byte-level, */%-aware tokenizer:
Support deprecated single-digit G-codes (Gerber spec §8.3)
§8.3 lists G1/G2/G3 as a tolerated style variation of G01/G02/G03. ViewMate emits these, and we treated them as UnknownCommand — so the interpolation never registered, modal D01 never armed, and every coordinate line in every region errored. Now
supported, including the combined G1X…D1* form, with G3 disambiguated from the G36/G37 region commands.
Richer error context
Errors now carry a column offset and the failing token (Line 14:28: 'G1X1576795Y1969D1*'), not just a line number — which is what made the single-digit G-code issue obvious. Also fixed a path where some errors were silently dropped.
Breaking: GerberParserErrorWithContext.line: Option<(usize, String)> is replaced by context: Option ({ line, offset, token }).
Verification
ViewMate copper layers that previously threw ~597k errors now parse with zero. Regression tests added for each change; full suite, clippy, and fmt are green.