Ryan Malloy 3bf4f6bed2 Implement Specctra DSN parser with typed board model
Ports the read path of FreeRouting's io/specctra/parser package to a
Java-free Python implementation:

- tokenizer: S-expression lexer mirroring SpecctraFileDescription.flex
  (comments, quoted strings, the string_quote IGNORE_QUOTE directive,
  case-insensitive keywords, and hash-prefixed names)
- sexp: nested S-expression tree builder
- shapes: rect/circle/polygon/path plus area-with-holes scopes
- model: typed dataclasses for layers, padstacks, images, placements,
  nets, net classes, rules, keepouts
- reader: recursive-descent scope readers producing a DsnBoard, one
  _read_* function per FreeRouting read_scope method

46 pytest cases cover the tokenizer, tree, shapes, and end-to-end
parsing against hand-crafted fixtures modeled on FreeRouting's own
test DSN files. Parses 90 of 91 upstream fixtures (the one failure is
a binary OLE file, not text DSN).
2026-07-11 15:21:18 -06:00

1.1 KiB

DSN test fixtures

Hand-crafted minimal Specctra DSN files, written to exercise the parser. They are modeled on the real fixtures shipped in the upstream FreeRouting repo (fixtures/empty_board.dsn and fixtures/SMD-routing-issue-demo.dsn) so the grammar and formatting match what kicad-cli pcb export specctra-dsn and FreeRouting itself produce, but they were typed fresh here (no upstream file is copied into this tree).

  • empty_board.dsn — the smallest valid board: parser, resolution, unit, and a structure with two signal layers and a pcb boundary path. Modeled on FreeRouting fixtures/empty_board.dsn.
  • smd_demo.dsn — a fuller board exercising every scope the parser handles: quoted board/padstack/image names, via, default rule (width + clearance with a (type smd_smd) pair), a keepout, padstacks (rect and circle pads), images with pins, placement with front/rotation, nets with Comp-Pin references, and a class with circuit/use_via and a rule. Modeled on FreeRouting fixtures/SMD-routing-issue-demo.dsn.