Phase 3 PR 63 -- S7AddressParser (DB/M/I/Q/T/C grammar) #62

Merged
dohertj2 merged 1 commits from phase-3-pr63-s7-address-parser into v2 2026-04-19 00:08:28 -04:00
Owner

Summary

Adds S7AddressParser + S7ParsedAddress record struct + S7Area / S7Size enums to the Driver.S7 project. Accepts the Siemens TIA Portal / STEP 7 Classic address syntax documented in driver-specs.md §5:

  • DB{n}.DB{X|B|W|D}{offset}[.bit]DB1.DBX0.0, DB1.DBW0, DB1.DBD4
  • MB{n}, MW{n}, MD{n}, M{n}.{bit} — Merkers
  • I…, Q… — same patterns, inputs and outputs
  • T{n}, C{n} — timers and counters

Case-insensitive, whitespace-tolerant. Strict rejection of 16 garbage variants (bit without .bit, bit 8+, DB 0, unknown area letters, etc.) so bad tag configs fail at driver-init time rather than surfacing as BadInternalError on every read.

TryParse returns bool for Admin UI live validation callers that can't throw.

Validation

  • 50/50 unit tests pass (S7AddressParserTests)
  • dotnet build: 0 errors

Scope

No driver wiring yet — PR 64 consumes S7ParsedAddress from IReadable/IWritable.

Test plan

  • DB bit/byte/word/dword
  • M/I/Q bit + size variants
  • T/C numeric
  • Case-insensitive + whitespace
  • 16 garbage-reject theory
  • TryParse round-trip
## Summary Adds `S7AddressParser` + `S7ParsedAddress` record struct + `S7Area` / `S7Size` enums to the Driver.S7 project. Accepts the Siemens TIA Portal / STEP 7 Classic address syntax documented in `driver-specs.md` §5: - `DB{n}.DB{X|B|W|D}{offset}[.bit]` — `DB1.DBX0.0`, `DB1.DBW0`, `DB1.DBD4` - `MB{n}`, `MW{n}`, `MD{n}`, `M{n}.{bit}` — Merkers - `I…`, `Q…` — same patterns, inputs and outputs - `T{n}`, `C{n}` — timers and counters Case-insensitive, whitespace-tolerant. Strict rejection of 16 garbage variants (bit without `.bit`, bit 8+, DB 0, unknown area letters, etc.) so bad tag configs fail at driver-init time rather than surfacing as `BadInternalError` on every read. `TryParse` returns bool for Admin UI live validation callers that can't throw. ## Validation - 50/50 unit tests pass (S7AddressParserTests) - `dotnet build`: 0 errors ## Scope No driver wiring yet — PR 64 consumes `S7ParsedAddress` from `IReadable`/`IWritable`. ## Test plan - [x] DB bit/byte/word/dword - [x] M/I/Q bit + size variants - [x] T/C numeric - [x] Case-insensitive + whitespace - [x] 16 garbage-reject theory - [x] TryParse round-trip
dohertj2 added 1 commit 2026-04-19 00:08:25 -04:00
Phase 3 PR 63 -- S7AddressParser for DB/M/I/Q/T/C address strings. Adds S7AddressParser + S7ParsedAddress + S7Area + S7Size to the Driver.S7 project. Grammar follows driver-specs.md \u00A75 + Siemens TIA Portal / STEP 7 Classic convention: (1) Data blocks: DB{n}.DB{X|B|W|D}{offset}[.bit] where X=bit (requires .bit suffix 0-7), B=byte, W=word (16-bit), D=dword (32-bit). (2) Merkers: MB{n}, MW{n}, MD{n}, or M{n}.{bit} for bit access. (3) Inputs + Outputs: same {B|W|D} prefix or {n}.{bit} pattern as M. (4) Timers: T{n}. (5) Counters: C{n}. Output is an immutable S7ParsedAddress record struct with Area (DataBlock / Memory / Input / Output / Timer / Counter), DbNumber (only meaningful for DataBlock), Size (Bit / Byte / Word / DWord), ByteOffset (also timer/counter number when Area is Timer/Counter), BitOffset (0-7 for Size=Bit; 0 otherwise). Case-insensitive via ToUpperInvariant, whitespace trimmed on entry. Parse throws FormatException with the offending input echoed in the message; TryParse returns bool for config-validation callers that can't afford exceptions (e.g. Admin UI tag-editor live validation). Strict rejection policy -- 16 garbage cases covered in the theory test: empty/whitespace input, unknown area letter (Z0), DB without number/tail, DB bit size without .bit suffix, bit offset 8+, word/dword with .bit suffix, DB number 0 (must be >=1), non-numeric DB number, unknown size letter (Q), M without offset, M bit access without .bit, bit 8, negative offset, non-digit offset, non-numeric timer. Strict rejection surfaces config errors at driver-init time rather than as BadInternalError on every Read against the bad tag. No driver code wires through yet -- PR 64 is where IReadable/IWritable consume S7ParsedAddress and translate into S7netplus Plc.ReadAsync calls (the S7.Net address grammar is a strict subset of what we accept, and the parser's S7ParsedAddress is the bridge). Unit tests (S7AddressParserTests, 50 facts): parse-valid theories for DB/M/I/Q/T/C covering all size variants + edge bit offsets 0 and 7; case-insensitive + whitespace-trim theory; reject-invalid theory with 16 garbage cases; TryParse round-trip for valid and invalid inputs. 50/50 pass, dotnet build clean. d5034c40f7
dohertj2 merged commit 0eab1271be into v2 2026-04-19 00:08:28 -04:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dohertj2/lmxopcua#62