Skip to content

Make ANTLR parser run simulations end-to-end - #113

Merged
tmolteno merged 1 commit into
masterfrom
antlr-simulation-fixes
Jul 15, 2026
Merged

Make ANTLR parser run simulations end-to-end#113
tmolteno merged 1 commit into
masterfrom
antlr-simulation-fixes

Conversation

@tmolteno

Copy link
Copy Markdown
Owner

Summary

The ANTLR parser (antlr/nec_parse) already dispatched all 21 program cards into the necpp engine, and RP/XQ already called simulate(). Five bugs stopped those simulations from running correctly and visibly. This PR fixes them so the parser actually performs simulations and emits their results.

Changes

File Change Why
antlr/nec_visitor.h Added nec->calc_prepare() in visitGeCard Lifecycle: buffers simulate() indexes (current_vector) were sized after the walk, but RP/XQ fire simulate() during it. Mirrors the geometry-only visitor and production driver order.
antlr/nec_visitor.h Fixed dispatch_labeled to skip N leading tokens of rest_ints Field mapping: its comment claimed ANTLR removes labelled tokens from ctx->INT() — false; getTokens() returns all tokens including labels. The mode integer (EX/GN/LD/NT/RP type) was consumed twice, shifting tag/seg and corrupting every labelled card.
antlr/NECFull.g4 Made imaginary voltage optional for EX type 0/5 (fnum fnumfnum fnum?) Grammar: the type-0 voltage-source branch mandated both real and imaginary voltage, rejecting valid minimal inputs like EX 0 0 4 0 1. (trailing blanks default to 0 in NEC-2).
antlr/nec_test.cpp s_output.set_file(stdout) before set_output Output dropped: the sink was never connected, so set_output cached a null FILE* and all simulation output was silently discarded. Uses set_file (not set_stream) because nec_printf/integer/real_out short-circuit on null m_output_fp.
antlr/nec_test.cpp Removed post-walk calc_prepare(); added context.write_results(std::cout) calc_prepare now runs in visitGeCard; write_results emits the structured result tables (radiation patterns, impedances, near fields) accumulated by RP/XQ/NE.
antlr/Makefile Added end-to-end simulation smoke test (FR/EX/RP/EN) asserting radiation-pattern + power-budget tables present Previously test: only checked parsing/geometry, never a real simulation.
antlr/build_in_docker.sh Generates ../build/simple/config.h (NECPP_VERSION/NECPP_BUILD_DATE) So the antlr build does not depend on a prior top-level make.

No changes to src/ — the engine and the shared nec_card_parser.h dispatch table were already the correct integration surface.

Verification

  • example1.nec (EX + XQ + NE) simulates; near-E field values match production nec2++ numerically (e.g. INPUT POWER = 4.4773E-03 Watts, near-E field 5.5442E+01 -66.31 at 0.0179 m).
  • Full make test passes: geometry, all card types, and the new simulating case (6249 bytes output, both tables present).
  • The full-card-set case still prints one CHECK DATA error — confirmed it is NT 0 1 0 0 … with a placeholder second-port segment of 0, which production nec2++ rejects identically (invalid input data, not a parser defect). That test tolerates it via || true.

Out of scope

CLI flags (-i/-o/-s), NX multi-job looping, PL filename handling, full nec2++ drop-in parity.

The ANTLR parser (antlr/nec_parse) already dispatched all 21 program
cards into the necpp engine, and RP/XQ already called simulate(). Five
bugs stopped those simulations from running correctly and visibly:

1. Lifecycle (nec_visitor.h): calc_prepare() was called *after* the
   visitor walk, but RP/XQ trigger simulate() *during* the walk, and
   simulate() indexes current_vector which calc_prepare() allocates.
   Moved calc_prepare() into visitGeCard, mirroring the geometry-only
   visitor and the production driver's order.

2. Field mapping (nec_visitor.h): dispatch_labeled's comment claimed
   ANTLR removes labelled tokens from ctx->INT() -- false; getTokens()
   returns all tokens including labels. The mode integer (EX/GN/LD/NT/
   RP type) was consumed twice, shifting tag/seg and corrupting every
   labelled card. Skip N leading tokens of rest_ints equal to the label
   count.

3. Grammar (NECFull.g4): EX type-0/5 voltage-source branch mandated both
   real and imaginary voltage, rejecting valid minimal inputs like
   'EX 0 0 4 0 1.' where trailing blanks default to 0 in NEC-2. Made the
   imaginary voltage optional (fnum fnum -> fnum fnum?).

4. Output sink (nec_test.cpp): nec_output_file was never connected, so
   set_output cached a null FILE* and all simulation output was silently
   dropped. Added s_output.set_file(stdout) -- uses FILE* not a stream
   because nec_printf/integer/real_out short-circuit on null m_output_fp.

5. Results emission (nec_test.cpp): added context.write_results() after
   the walk so computed radiation patterns / impedances / near fields
   are emitted (nec_results::write clears each flag, so one call is
   idempotent). Removed the now-redundant post-walk calc_prepare().

Also: build_in_docker.sh now generates ../build/simple/config.h
(NECPP_VERSION/NECPP_BUILD_DATE) so the antlr build does not depend on a
prior top-level make. Added an end-to-end simulation smoke test
(FR/EX/RP/EN) to antlr/Makefile asserting radiation-pattern and
power-budget tables are present.

Verified: example1.nec simulates and its near-E field values match the
production nec2++ output numerically.
@tmolteno
tmolteno merged commit 06f46fa into master Jul 15, 2026
1 check passed
@tmolteno
tmolteno deleted the antlr-simulation-fixes branch July 15, 2026 22:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant