Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion antlr/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@ test: generate
@echo "=== all geometry card types ==="
@printf 'GW 1 5 0. 0. -1. 0. 0. 1. 0.\nGC 0 0 1.0 .001 .005\nGA 3 11 0.15 0 180 .001\nGH 4 20 0.5 1.0 0.1 0.2 0.1 0.2 .001\nGS 2.0\nGM 0 0 1. 0. 0. 1. 0. 0. 0.\nGE\nFR 0 1 0 0 1.\nEN\n' | ./run_in_docker.sh ./nec_parse
@echo "=== full card set (field counts per nec2prt3.pdf) ==="
@printf 'GW 1 7 0. 0. -.25 0. 0. .25 .001\nGE\nFR 0 1 0 0 100.\nLD 5 0 0 0 1.\nGN 1\nEX 0 0 5 0 1. 0.\nNT 0 1 0 0 0 0 0 0 0 0\nTL 0 1 0 0 50. 0. 0. 0. 0. 0.\nXQ 0\nGD 0. 0. 0. 0.\nRP 0 1 1 0 0. 0. 0. 0.\nNX\nPT 0 0 0 0\nKH 1.0\nNE 0 1 1 1 0. 0. 0. 0. 0. 0.\nNH 0 1 1 1 0. 0. 0. 0. 0. 0.\nPQ 0 0 0 0\nEK 0\nCP 0 0 0 0\nPL 0 0 0 0 0 0 0\nWG\nMP 0 0 0 0 0. 0. 0. 0. 0. 0.\nEN\n' | ./run_in_docker.sh ./nec_parse || true
@printf 'GW 1 7 0. 0. -.25 0. 0. .25 .001\nGE\nFR 0 1 0 0 100.\nLD 5 0 0 0 1.\nGN 1\nEX 0 0 5 0 1. 0.\nnt 0 1 0 0 0 0 0 0 0 0\nTL 0 1 0 0 50. 0. 0. 0. 0. 0.\nXQ 0\nGD 0. 0. 0. 0.\nRP 0 1 1 0 0. 0. 0. 0.\nNX\nPT 0 0 0 0\nKH 1.0\nNE 0 1 1 1 0. 0. 0. 0. 0. 0.\nNH 0 1 1 1 0. 0. 0. 0. 0. 0.\nPQ 0 0 0 0\nEK 0\nCP 0 0 0 0\nPL 0 0 0 0 0 0 0\nWG\nMP 0 0 0 0 0. 0. 0. 0. 0. 0.\nEN\n' | ./run_in_docker.sh ./nec_parse || true
@echo "=== end-to-end simulation (FR/EX/RP triggers simulate()) ==="
@printf 'CE dipole\nGW 0 7 0. 0. -.25 0. 0. .25 .001\nGE\nFR 0 1 0 0 300.\nEX 0 0 4 0 1.\nRP 0 1 1 0 0. 0. 0. 0.\nEN\n' | ./run_in_docker.sh ./nec_parse > /tmp/nec_sim.out
@echo " output bytes: $$(wc -c < /tmp/nec_sim.out)"
@grep -q 'RADIATION PATTERN' /tmp/nec_sim.out && echo " radiation-pattern table present"
@grep -q 'POWER BUDGET' /tmp/nec_sim.out && echo " power-budget present"
@echo "=== all tests passed ==="

clean:
Expand Down
6 changes: 3 additions & 3 deletions antlr/NECFull.g4
Original file line number Diff line number Diff line change
Expand Up @@ -106,16 +106,16 @@ gnCard
;

// EX — Excitation. Field layout depends on excitation type (I1).
// 0: voltage source (applied-E) tag seg flag v_r v_i [norm]
// 0: voltage source (applied-E) tag seg flag v_r [v_i] [norm]
// 1: linear plane wave nTH nPH flag th ph eta dth [dph] [pol]
// 2: right-hand circular wave nTH nPH flag th ph eta dth dph pol
// 3: left-hand circular wave nTH nPH flag th ph eta dth dph pol
// 4: elementary current source – – flag x y z alpha beta moment
// 5: voltage source (slope disc.) tag seg flag v_r v_i [norm]
// 5: voltage source (slope disc.) tag seg flag v_r [v_i] [norm]
exCard
: EX i=INT
( {std::stoi($i.text) == 0 || std::stoi($i.text) == 5}?
INT INT INT fnum fnum fnum?
INT INT INT fnum fnum? fnum?
| {std::stoi($i.text) == 1}?
INT INT INT fnum fnum fnum fnum fnum? fnum?
| {std::stoi($i.text) >= 2 && std::stoi($i.text) <= 4}?
Expand Down
17 changes: 17 additions & 0 deletions antlr/build_in_docker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,23 @@ echo "=== Generating ANTLR 4 parser (full NEC) ==="
docker run $DOCKER_OPTS "$IMAGE" \
antlr4 -Dlanguage=Cpp -o generated -visitor NECFull.g4

# Generate the build config header that common.h / nec2cpp.cpp require.
# The main Makefile owns the canonical NECPP_VERSION; read it from there so
# the two builds cannot drift apart. build/simple/config.h is included via
# -I ../build/simple, and must define NECPP_VERSION and NECPP_BUILD_DATE
# (the strings that common.h stitches into the nec_version literal).
NECPP_VERSION=$(grep -E '^NECPP_VERSION[[:space:]]*=' ../Makefile | head -1 | sed -E 's/.*=[[:space:]]*//')
NECPP_BUILD_DATE=$(date +"%Y-%m-%d")
mkdir -p ../build/simple
{
echo '#ifndef CONFIG_H'
echo '#define CONFIG_H'
echo "#define NECPP_VERSION \"${NECPP_VERSION}\""
echo "#define NECPP_BUILD_DATE \"${NECPP_BUILD_DATE}\""
echo '#endif'
} > ../build/simple/config.h
echo " config.h: NECPP_VERSION=${NECPP_VERSION} NECPP_BUILD_DATE=${NECPP_BUILD_DATE}"

echo "=== Compiling full NEC parser ==="
# Compile nec2cpp.cpp separately with main() renamed
mkdir -p build
Expand Down
15 changes: 14 additions & 1 deletion antlr/nec_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ int main(int argc, char* argv[]) {
nec_context context;
nec_output_file s_output;
nec_output_flags s_output_flags;
// Connect the output sink. Must use set_file (a FILE*) rather than
// set_stream: nec_context::set_output caches m_output_fp via get_fp(),
// and the internal fast-print routines (nec_printf/integer/real_out)
// short-circuit when m_output_fp == NULL, dropping printf-style output.
// Without this, all simulation output (freq header, currents, radiation
// tables) is silently discarded.
s_output.set_file(stdout);
context.set_output(s_output, s_output_flags);

c_geometry* geo = context.get_geometry();
Expand All @@ -87,7 +94,13 @@ int main(int argc, char* argv[]) {
visitor.geo = geo;
tree->accept(&visitor);

context.calc_prepare();
// calc_prepare() ran inside visitGeCard (see nec_visitor.h), so the
// interaction buffers are sized before any program card was dispatched.
// Emit the accumulated structured results (radiation patterns, antenna
// input/impedance, near fields, currents) computed by RP/XQ/NE/NH/PT.
// nec_results::write() clears each result's write_file flag as it goes,
// so a single call here is correct and idempotent.
context.write_results(std::cout);

std::cout << "Parsed successfully. Wires: " << visitor.nwire
<< ", Segments: " << geo->n_segments << std::endl;
Expand Down
21 changes: 17 additions & 4 deletions antlr/nec_visitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,21 +100,27 @@ class NecBuildVisitor : public NECFullBaseVisitor {
dispatch(mn, v, {});
}
// Dispatch a card whose grammar labels one or more leading INT fields
// (e.g. EX i=INT, NT i1=INT i2=INT). In ANTLR 4 a labelled token is
// removed from ctx->INT(), so ctx->INT() returns the *remaining* integers;
// the labelled tokens are passed in `leading` to fill i[0], i[1], ...
// (e.g. EX i=INT, NT i1=INT i2=INT). The labelled tokens are passed in
// `leading` to fill i[0], i[1], ... and are also present at the front of
// `rest_ints`, because ANTLR 4's rule-context getter (getTokens) returns
// *all* tokens of a type — including labelled ones. So we skip as many
// leading elements of rest_ints as there are labels to avoid consuming
// the mode integer twice (which would shift tag/seg and corrupt the card).
void dispatch_labeled(const std::string& mn,
std::initializer_list<antlr4::Token*> leading,
const std::vector<antlr4::tree::TerminalNode*>& rest_ints,
const std::vector<NECFullParser::FnumContext*>& fv) {
nec_card card;
card.mnemonic = mn;
size_t n_labels = 0;
size_t idx = 0;
for (auto* tok : leading) {
if (tok) { card.i[idx] = (int)std::stod(tok->getText()); card.parameter_count++; }
n_labels++;
idx++;
}
for (size_t n = 0; idx < 4 && n < rest_ints.size(); n++, idx++) {
// Skip the labelled tokens that also appear at the front of rest_ints.
for (size_t n = n_labels; idx < 4 && n < rest_ints.size(); n++, idx++) {
card.i[idx] = (int)std::stod(rest_ints[n]->getText()); card.parameter_count++;
}
for (size_t n = 0; n < 6 && n < fv.size(); n++) {
Expand Down Expand Up @@ -177,6 +183,13 @@ class NecBuildVisitor : public NECFullBaseVisitor {
antlrcpp::Any visitGeCard(NECFullParser::GeCardContext* ctx) override {
auto v = ctx->INT();
geo->geometry_complete(nec, v.empty() ? 0 : (int)std::stod(v[0]->getText()));
// Size the interaction buffers now, before any program card runs.
// RP/XQ dispatch below trigger simulate() during the walk, and
// simulate() indexes current_vector — which calc_prepare() allocates
// (nec_context.cpp). Mirrors the geometry-only visitor
// (geometry_visitor.h) and the production driver flow
// (nec2cpp.cpp: parse_geometry -> calc_prepare -> cards).
nec->calc_prepare();
return nullptr;
}
antlrcpp::Any visitGmCard(NECFullParser::GmCardContext* ctx) override {
Expand Down
Loading