nec2++
2.1.1
src
nec_card_parser.h
1
#pragma once
2
3
/*
4
Clean NEC card parser — replaces the FORTRAN-style readmn() with
5
std::string-based parsing and table-driven dispatch.
6
7
Copyright (C) 2025 Timothy C.A. Molteno
8
9
This program is free software; you can redistribute it and/or modify
10
it under the terms of the GNU General Public License as published by
11
the Free Software Foundation; either version 2 of the License, or
12
(at your option) any later version.
13
*/
14
15
#include <string>
16
#include <vector>
17
#include <sstream>
18
#include <cstring>
19
#include <cstdlib>
20
21
#include "common.h"
22
23
/*-----------------------------------------------------------------------*/
24
/* Parsed NEC card */
25
26
struct
nec_card
{
27
std::string mnemonic;
28
int
i[4] = {0,0,0,0};
29
double
f[7] = {0.,0.,0.,0.,0.,0.,0.};
30
int
parameter_count = 0;
31
32
bool
is(
const
char
* m)
const
{
return
mnemonic == m; }
33
};
34
35
/*-----------------------------------------------------------------------*/
36
/* Parse a single NEC card line into a nec_card struct. */
37
/* Handles: comma or space separators, negative numbers, E-notation, */
38
/* inline ' comments, leading # comment lines. */
39
40
inline
nec_card
parse_nec_card(
const
std::string& line) {
41
nec_card
card;
42
if
(line.size() < 2)
43
return
card;
44
45
/* Check for # comment lines */
46
if
(line[0] ==
'#'
)
47
return
card;
48
49
/* Extract mnemonic */
50
card.mnemonic = line.substr(0, 2);
51
52
/* Find the ' comment delimiter and truncate */
53
std::string rest = line.substr(2);
54
size_t
comment_pos = rest.find(
'\''
);
55
if
(comment_pos != std::string::npos)
56
rest = rest.substr(0, comment_pos);
57
58
/* Parse remaining fields: replace commas with spaces for uniform parsing */
59
for
(
auto
& ch : rest)
60
if (ch ==
','
) ch =
' '
;
61
62
std::stringstream ss(rest);
63
std::string token;
64
65
/* First 4 fields are integers */
66
for
(
int
n = 0; n < 4; n++) {
67
if
(!(ss >> token))
break
;
68
card.i[n] = std::atoi(token.c_str());
69
card.parameter_count++;
70
}
71
72
/* Next 6 fields are floats */
73
for
(
int
n = 0; n < 6; n++) {
74
if
(!(ss >> token))
break
;
75
card.f[n] = std::atof(token.c_str());
76
card.parameter_count++;
77
}
78
79
return
card;
80
}
81
82
/*-----------------------------------------------------------------------*/
83
/* Table-driven card dispatch (replaces atst[] + giant switch) */
84
85
class
nec_context
;
// forward decl
86
87
struct
card_handler
{
88
const
char
* name;
89
void (*dispatch)(
nec_context
& ctx,
const
nec_card
& card);
90
};
91
92
/* Dispatch helpers — one per card type */
93
void
handle_fr(
nec_context
& ctx,
const
nec_card
& c);
94
void
handle_ld(
nec_context
& ctx,
const
nec_card
& c);
95
void
handle_gn(
nec_context
& ctx,
const
nec_card
& c);
96
void
handle_ex(
nec_context
& ctx,
const
nec_card
& c);
97
void
handle_nt(
nec_context
& ctx,
const
nec_card
& c);
98
void
handle_tl(
nec_context
& ctx,
const
nec_card
& c);
99
void
handle_xq(
nec_context
& ctx,
const
nec_card
& c);
100
void
handle_gd(
nec_context
& ctx,
const
nec_card
& c);
101
void
handle_rp(
nec_context
& ctx,
const
nec_card
& c);
102
void
handle_nx(
nec_context
& ctx,
const
nec_card
& c);
103
void
handle_pt(
nec_context
& ctx,
const
nec_card
& c);
104
void
handle_kh(
nec_context
& ctx,
const
nec_card
& c);
105
void
handle_ne(
nec_context
& ctx,
const
nec_card
& c);
106
void
handle_nh(
nec_context
& ctx,
const
nec_card
& c);
107
void
handle_pq(
nec_context
& ctx,
const
nec_card
& c);
108
void
handle_ek(
nec_context
& ctx,
const
nec_card
& c);
109
void
handle_cp(
nec_context
& ctx,
const
nec_card
& c);
110
void
handle_pl(
nec_context
& ctx,
const
nec_card
& c);
111
void
handle_en(
nec_context
& ctx,
const
nec_card
& c);
112
void
handle_wg(
nec_context
& ctx,
const
nec_card
& c);
113
void
handle_mp(
nec_context
& ctx,
const
nec_card
& c);
114
115
/* The handler table — all 21 NEC card types in one place */
116
static
const
card_handler
card_handlers[] = {
117
{
"FR"
, handle_fr}, {
"LD"
, handle_ld}, {
"GN"
, handle_gn},
118
{
"EX"
, handle_ex}, {
"NT"
, handle_nt}, {
"TL"
, handle_tl},
119
{
"XQ"
, handle_xq}, {
"GD"
, handle_gd}, {
"RP"
, handle_rp},
120
{
"NX"
, handle_nx}, {
"PT"
, handle_pt}, {
"KH"
, handle_kh},
121
{
"NE"
, handle_ne}, {
"NH"
, handle_nh}, {
"PQ"
, handle_pq},
122
{
"EK"
, handle_ek}, {
"CP"
, handle_cp}, {
"PL"
, handle_pl},
123
{
"EN"
, handle_en}, {
"WG"
, handle_wg}, {
"MP"
, handle_mp},
124
};
125
126
inline
const
card_handler
* find_handler(
const
std::string& mnemonic) {
127
for
(
const
auto
& h : card_handlers)
128
if (h.name[0] == mnemonic[0] && h.name[1] == mnemonic[1])
129
return &h;
130
return
nullptr
;
131
}
nec_context
Container for an nec2++ simulation.
Definition
nec_context.h:80
card_handler
Definition
nec_card_parser.h:87
nec_card
Definition
nec_card_parser.h:26
Generated by
1.9.8