or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

command-line.mdcore-parsing.mdindex.mdnamelist-objects.mdparser-configuration.mdutility-functions.md

parser-configuration.mddocs/

0

# Advanced Parser Configuration

1

2

Configurable parsing engine for handling Fortran syntax variations, custom comment tokens, and complex array indexing. The Parser class provides fine-grained control over how namelist files are interpreted and processed.

3

4

## Capabilities

5

6

### Parser Class

7

8

Advanced parser with configurable options for handling diverse Fortran namelist dialects and edge cases.

9

10

```python { .api }

11

class Parser:

12

"""

13

Fortran namelist parser with extensive configuration options.

14

15

Provides control over parsing behavior, indexing conventions,

16

comment handling, and data structure organization.

17

"""

18

19

def __init__(self):

20

"""Create parser object with default configuration."""

21

```

22

23

**Usage Examples:**

24

25

```python

26

# Create parser with custom configuration

27

parser = f90nml.Parser()

28

29

# Configure parser options

30

parser.comment_tokens = '!#' # Support both ! and # comments

31

parser.default_start_index = 0 # Use 0-based indexing

32

parser.strict_logical = False # Relaxed logical parsing

33

34

# Use parser

35

nml = parser.read('config.nml')

36

```

37

38

### Parsing Methods

39

40

Core methods for processing namelist data from files and strings.

41

42

```python { .api }

43

def read(self, nml_fname, nml_patch_in=None, patch_fname=None):

44

"""

45

Parse a Fortran namelist file and store the contents.

46

47

Args:

48

nml_fname: str or file-like object - Input file path or file object

49

nml_patch_in: dict, optional - Patch data to apply during parsing

50

patch_fname: str, optional - Output file for patch results

51

52

Returns:

53

Namelist: Parsed namelist data

54

55

Raises:

56

ValueError: If namelist syntax is invalid

57

IOError: If file cannot be read

58

"""

59

60

def reads(self, nml_string):

61

"""

62

Parse a namelist string and return equivalent Namelist object.

63

64

Args:

65

nml_string: str - String containing Fortran namelist data

66

67

Returns:

68

Namelist: Parsed namelist data

69

70

Raises:

71

ValueError: If namelist syntax is invalid

72

"""

73

```

74

75

**Usage Examples:**

76

77

```python

78

parser = f90nml.Parser()

79

80

# Basic parsing

81

nml = parser.read('input.nml')

82

83

# Parse with simultaneous patching

84

patch_data = {'config': {'modified_param': 100}}

85

nml = parser.read('input.nml', patch_data, 'patched_output.nml')

86

87

# Parse string

88

nml_str = '&data x=1, y=2 /'

89

nml = parser.reads(nml_str)

90

```

91

92

### Comment Token Configuration

93

94

Customize which characters are treated as comment delimiters.

95

96

```python { .api }

97

comment_tokens: str

98

"""

99

String of single-character comment tokens (default: '!').

100

101

Fortran standard uses '!' but some programs support additional

102

tokens like '#' for preprocessing compatibility.

103

"""

104

```

105

106

**Usage Examples:**

107

108

```python

109

parser = f90nml.Parser()

110

111

# Support multiple comment types

112

parser.comment_tokens = '!#'

113

114

# Parse file with mixed comments

115

nml_content = '''

116

&config

117

! Standard Fortran comment

118

param1 = 10

119

# Preprocessor-style comment

120

param2 = 20

121

/

122

'''

123

nml = parser.reads(nml_content)

124

125

# Add custom comment token

126

parser.comment_tokens += '%' # Now supports !, #, and %

127

```

128

129

### Array Indexing Configuration

130

131

Control how array indices are interpreted and handled.

132

133

```python { .api }

134

default_start_index: int

135

"""

136

Assumed starting index for vectors without explicit indexing (default: 1).

137

138

Fortran allows arbitrary start indices. When not specified,

139

this value determines the assumed starting position.

140

"""

141

142

global_start_index: int

143

"""

144

Explicit start index for all vectors (default: None).

145

146

When set, forces all arrays to use this starting index,

147

overriding any explicit indices in the namelist.

148

"""

149

```

150

151

**Usage Examples:**

152

153

```python

154

parser = f90nml.Parser()

155

156

# Use 0-based indexing (Python-style)

157

parser.default_start_index = 0

158

159

# Parse namelist with ambiguous indexing

160

nml_content = '''

161

&data

162

array1(3:5) = 10, 20, 30 ! Explicit indices

163

array2 = 1, 2, 3 ! Uses default_start_index

164

/

165

'''

166

nml = parser.reads(nml_content)

167

print(nml['data']['array2']) # [1, 2, 3] starting at index 0

168

169

# Force global indexing

170

parser.global_start_index = 1

171

nml = parser.reads(nml_content)

172

# Now array2 will be treated as starting at index 1

173

```

174

175

### Data Structure Configuration

176

177

Control how multidimensional arrays and sparse data are organized.

178

179

```python { .api }

180

row_major: bool

181

"""

182

Read multidimensional arrays in row-major format (default: False).

183

184

By default, preserves Fortran column-major ordering.

185

When True, converts to row-major (C-style) ordering.

186

"""

187

188

sparse_arrays: bool

189

"""

190

Store unset rows of multidimensional arrays as empty lists (default: False).

191

192

Provides more compact representation for sparse data structures.

193

"""

194

```

195

196

**Usage Examples:**

197

198

```python

199

parser = f90nml.Parser()

200

201

# Configure for row-major arrays

202

parser.row_major = True

203

204

# Parse multidimensional data

205

nml_content = '''

206

&matrix

207

data(1:2, 1:3) = 1, 2, 3, 4, 5, 6

208

/

209

'''

210

nml = parser.reads(nml_content)

211

# Array will be organized in row-major order

212

213

# Enable sparse array handling

214

parser.sparse_arrays = True

215

sparse_content = '''

216

&sparse

217

matrix(1, 1) = 10

218

matrix(5, 5) = 20

219

/

220

'''

221

nml = parser.reads(sparse_content)

222

# Unset rows will be empty lists instead of None-filled

223

```

224

225

### Logical Value Parsing

226

227

Control how logical (boolean) values are interpreted.

228

229

```python { .api }

230

strict_logical: bool

231

"""

232

Use strict rules for logical value parsing (default: True).

233

234

When True: Only standard forms (.true., .t., true, t, .false., .f., false, f)

235

When False: Any string starting with 't' or 'f' is interpreted as boolean

236

"""

237

```

238

239

**Usage Examples:**

240

241

```python

242

parser = f90nml.Parser()

243

244

# Strict logical parsing (default)

245

parser.strict_logical = True

246

try:

247

nml = parser.reads('&data flag = totally_true /')

248

except ValueError:

249

print("Invalid logical value in strict mode")

250

251

# Relaxed logical parsing

252

parser.strict_logical = False

253

nml = parser.reads('&data flag = totally_true /') # Interprets as True

254

print(nml['data']['flag']) # True

255

256

# Standard logical values work in both modes

257

standard_content = '''

258

&flags

259

flag1 = .true.

260

flag2 = .false.

261

flag3 = T

262

flag4 = F

263

/

264

'''

265

nml = parser.reads(standard_content)

266

```

267

268

### Advanced Parsing Features

269

270

Handle complex Fortran namelist features and edge cases.

271

272

**Derived Types:**

273

```python

274

# Parse Fortran derived types

275

derived_content = '''

276

&particles

277

particle(1)%x = 1.0

278

particle(1)%y = 2.0

279

particle(2)%x = 3.0

280

particle(2)%y = 4.0

281

/

282

'''

283

parser = f90nml.Parser()

284

nml = parser.reads(derived_content)

285

print(nml['particles']['particle'][0]['x']) # 1.0

286

```

287

288

**Complex Numbers:**

289

```python

290

# Parse complex number literals

291

complex_content = '''

292

&physics

293

impedance = (1.0, 2.0)

294

frequency_response = (3.14, -1.57), (2.71, 0.0)

295

/

296

'''

297

nml = parser.reads(complex_content)

298

print(nml['physics']['impedance']) # (1.0+2.0j)

299

```

300

301

**Vector Indexing:**

302

```python

303

# Handle explicit vector indices

304

indexed_content = '''

305

&arrays

306

pressure(0:2) = 1013.25, 850.0, 700.0

307

temperature(5:7) = 273.15, 283.15, 293.15

308

/

309

'''

310

parser = f90nml.Parser()

311

parser.default_start_index = 0

312

nml = parser.reads(indexed_content)

313

314

# Access start index information

315

print(nml['arrays'].start_index) # {'pressure': [0], 'temperature': [5]}

316

```

317

318

## Error Handling and Diagnostics

319

320

```python

321

parser = f90nml.Parser()

322

323

# Handle invalid syntax

324

try:

325

nml = parser.reads('&invalid syntax without end')

326

except ValueError as e:

327

print(f"Parse error: {e}")

328

329

# Handle file access errors

330

try:

331

nml = parser.read('/nonexistent/file.nml')

332

except IOError as e:

333

print(f"File error: {e}")

334

335

# Validate configuration

336

try:

337

parser.default_start_index = "invalid"

338

except TypeError as e:

339

print(f"Configuration error: {e}")

340

```

341

342

## Integration with Core Functions

343

344

Parser objects can be used instead of the module-level functions for full control:

345

346

```python

347

# Module-level functions (use default parser)

348

nml = f90nml.read('input.nml')

349

350

# Equivalent using custom parser

351

parser = f90nml.Parser()

352

parser.comment_tokens = '!#'

353

parser.default_start_index = 0

354

nml = parser.read('input.nml')

355

356

# Parser configuration persists across multiple files

357

nml1 = parser.read('file1.nml')

358

nml2 = parser.read('file2.nml') # Uses same configuration

359

```