Fix DSN tokenizer to accept KiCad net names like /*52

Specctra's SpecCharASCII includes / and *, and an Identifier may start with /,
so KiCad emits hierarchical net names such as /*52 and /53. The tokenizer
treated any /* as a block-comment start and raised 'unterminated comment' when
no */ followed — rejecting real KiCad DSN. Match FreeRouting's JFlex rule-order
resolution: /* is a comment only when a closing */ exists; otherwise it is an
ordinary name run. Validated against a KiCad 10.0.4 pcbnew-exported DSN (78 nets
incl. /*52, /53).
This commit is contained in:
2026-07-11 18:46:29 -06:00
parent 07a9433f19
commit c905032a39
2 changed files with 22 additions and 9 deletions
+12 -6
View File
@@ -126,13 +126,19 @@ def tokenize(text: str, quote_chars: str = _QUOTES) -> list[Token]:
eol = text.find("\n", i)
i = n if eol == -1 else eol
continue
if ch == "/" and i + 1 < n and text[i + 1] == "*": # block comment
# `/* ... */` is a block comment ONLY when a closing `*/` exists.
# SpecCharASCII includes `/` and `*`, and an Identifier may start with
# `/`, so KiCad emits net names like `/*52`. FreeRouting's JFlex scanner
# resolves the ambiguity by longest-match / rule-order: with no closing
# `*/`, the comment rule fails and the run is read as a name. Mirror
# that — an unclosed `/*` is an ordinary token, not an error.
if ch == "/" and i + 1 < n and text[i + 1] == "*":
end = text.find("*/", i + 2)
if end == -1:
raise DsnSyntaxError(f"unterminated /* */ comment at line {line}")
line += text.count("\n", i, end)
i = end + 2
continue
if end != -1:
line += text.count("\n", i, end)
i = end + 2
continue
# no closing `*/` — fall through and read `/*...` as a normal token
# Brackets -----------------------------------------------------------
if ch == "(":