Skip to content

Commit d43efca

Browse files
authored
Merge pull request #8 from PyNumLab/improve_parser
improve parser
2 parents 99d49e6 + 3f2b218 commit d43efca

9 files changed

Lines changed: 1682 additions & 1877 deletions

File tree

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,14 @@ The parser exposes stable file/project entrypoints:
453453
- `parse_fortran_project(...)` for many sources returning `FortranProject`.
454454
- `assess_wrap_readiness(...)` for wrappability diagnostics.
455455

456+
Internally, `FortranParser.visit_file` uses a recursive source-unit parser:
457+
the file is sliced into direct modules/submodules/programs/procedures/block
458+
data/interfaces/types, then each unit visitor parses only its own substring and
459+
recurses into direct children. Shared declaration helpers parse variables,
460+
procedure arguments/results, and type fields, then push them into the active
461+
scope. Procedure execution bodies and internal subprograms are ignored for
462+
wrapper metadata; procedure-local interfaces are retained for callback typing.
463+
456464
The semantics layer consumes `FortranFile`/`FortranModule` objects and projects them into language-independent semantic IR (`SemanticModule`, `SemanticFunction`, `SemanticClass`, `SemanticType`). This keeps the semantic API model independent from parser internals, matching the project goal that parser output is a helper and the semantic interface/IR is the source of truth.
457465

458466
For Fortran `use` imports, the parser stores each explicit imported symbol as a

fortran_parser.md

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,16 +88,25 @@ sections so maintainers can navigate the file by concern instead of by history:
8888
- `FortranParser` internals grouped by domain:
8989
- visitor-style API entrypoints (`visit_file`, `visit_project`,
9090
`visit_wrap_readiness`)
91-
- signature/declaration parsing
92-
- module-variable parsing
93-
- file/project orchestration
94-
- program-unit parsers (types, modules, interfaces, submodules, programs,
95-
block-data)
96-
- `_helper_*` methods for scoped parsing, expression resolution, and shared
91+
- source-unit visitors for files, modules, submodules, programs,
92+
procedures, interfaces, derived types, and block data
93+
- recursive source-unit slicing (`header`, specification part, execution
94+
part, `contains`) with original line numbers preserved on each slice
95+
- shared declaration parsing for module variables, program/block-data
96+
variables, procedure arguments/results, and derived-type fields
97+
- `_helper_*` methods for scoped parsing, expression resolution,
98+
preprocessor branch selection, same-level duplicate checks, and shared
9799
specification-part collection
98100
- Thin module-level convenience wrappers that delegate to a shared parser
99101
instance
100102

103+
`visit_file` is the central orchestration path. It first slices the source into
104+
direct file-level units, then each unit visitor parses only its own substring
105+
and recursively slices direct children. Procedure execution parts are ignored
106+
for wrapper metadata, and procedure-internal subprograms are not exported as
107+
file/module procedures. Procedure-local interface blocks are still visited
108+
enough to type callback dummy arguments and to preserve interface metadata.
109+
101110
Most parser organization changes are structural, but behavior, model-schema,
102111
coverage, or fixture changes should be reflected in this reference.
103112

fortran_parser/parser.py

Lines changed: 1459 additions & 1016 deletions
Large diffs are not rendered by default.

parser_implementation_reference.md

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -329,15 +329,22 @@ If you want another agent to reproduce the same architecture for a new language,
329329
ask it to implement each of these layers explicitly:
330330

331331
1. Preprocessor/lexer layer for source forms, comments, continuations.
332-
2. Procedure signature parser (headers, args, attributes, result handling).
333-
3. Declaration parser for types/intent/shape/flags.
334-
4. Module/package parser with import/use tracking.
335-
5. Composite type parser (fields, inheritance, bound methods/generics).
336-
6. Interface/contract block parser.
337-
7. Symbol resolver for local and cross-file compile-time constants.
338-
8. Project namespace parser with dependency ordering.
339-
9. Readiness validator with unsupported-pattern rules + unknown type checks.
340-
10. CLI with tree output + JSON output + file emission.
332+
2. Source-unit slicer that preserves original line numbers and returns direct
333+
children for each scope.
334+
3. Grammar-region splitter for `header`, specification part, execution part,
335+
and `contains`.
336+
4. Unit visitors for modules, submodules, programs, procedures, derived types,
337+
interfaces, and block data.
338+
5. Shared declaration parser for variables, procedure arguments/results, and
339+
derived-type fields, with scope-specific storage handled separately.
340+
6. Procedure signature parser (headers, args, attributes, result handling).
341+
7. Module/package parser with import/use tracking.
342+
8. Composite type parser (fields, inheritance, bound methods/generics).
343+
9. Interface/contract block parser.
344+
10. Symbol resolver for local and cross-file compile-time constants.
345+
11. Project namespace parser with dependency ordering.
346+
12. Readiness validator with unsupported-pattern rules + unknown type checks.
347+
13. CLI with tree output + JSON output + file emission.
341348
11. Unit tests per feature + fixture/golden regression suite + golden
342349
regeneration script.
343350

@@ -407,6 +414,13 @@ A condensed history of important parser capabilities added over time (from
407414
- Added parser public API coverage for less common module/import forms and
408415
preserved `use` rename source/target mappings through JSON, semantic IR, and
409416
`.pyi` import aliases.
417+
- Refactored `FortranParser.visit_file` onto recursive source-unit slicing:
418+
file parsing now dispatches direct units to small `visit_*_unit` methods,
419+
each unit works on its own source substring, and shared declaration helpers
420+
push parsed symbols into the active scope.
421+
- Refreshed parser goldens for the grammar-style parser. Procedure-internal
422+
subprograms are no longer exported as file/module procedures; local
423+
interfaces remain available for callback typing and interface metadata.
410424

411425
## 9) Pull-request maintenance policy for this reference
412426

@@ -491,12 +505,15 @@ When updating parser behavior, keep this fail-fast contract aligned with tests:
491505
diagnostics where appropriate; unknown datatype syntax should crash early.
492506
- **Preprocessor-conditional duplicate procedures (guarded allowance):**
493507
- The parser does **not** run a full C preprocessor stage before parsing.
494-
- While scanning signatures, simple directive structure is tracked for `#ifdef`, `#ifndef`, `#elif`, `#else`, and `#endif` to model mutually-exclusive branches.
495-
- `visit_file(..., macro_defines=...)` can provide macro decisions; inactive conditional branches are skipped during signature extraction so the active code path is selected. The module-level `parse_fortran_file(...)` convenience function delegates to this visitor.
508+
- While slicing source units, simple directive structure is tracked for
509+
`#ifdef`, `#ifndef`, `#elif`, `#else`, and `#endif` to model
510+
mutually-exclusive branches.
511+
- `visit_file(..., macro_defines=...)` can provide macro decisions; inactive conditional branches are skipped before unit parsing so the active code path is selected. The module-level `parse_fortran_file(...)` convenience function delegates to this visitor.
496512
- accepted forms: `set[str]` or `dict[str, int|bool|str]`
497513
- dictionary values are truthy/falsey (`0`, `False`, `"0"`, `"false"` treated as undefined/disabled)
498514
- Basic `#if` expressions are supported for branch selection (`defined(X)`, `!`, `&&`, `||`, parentheses, `0`/`1`).
499-
- Duplicate procedure-name checks in a module/global scope are evaluated against this branch context:
515+
- Duplicate procedure-name checks in a module/global scope are evaluated
516+
against same-level sliced units and this branch context:
500517
- if two same-name procedure headers are reachable in an overlapping branch context, raise `FortranParseError` (duplicate procedure name).
501518
- if they are only present in mutually-exclusive branches of the same conditional group, allow both signatures.
502519
- This is a structural exclusivity model (branch groups), not semantic evaluation of macro expressions. In other words, branch mutual exclusivity is honored without requiring expression truth evaluation.

tests/parser/fortran/fixtures/scifortran/SF_SPARSE_ARRAY_CSC.json

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4578,7 +4578,22 @@
45784578
}
45794579
],
45804580
"default_visibility": "private",
4581-
"public_symbols": [],
4581+
"public_symbols": [
4582+
"sparse_dmatrix_csc",
4583+
"sparse_zmatrix_csc",
4584+
"as_sparse",
4585+
"sparse",
4586+
"assignment(=)",
4587+
"operator(+)",
4588+
"operator(-)",
4589+
"operator(*)",
4590+
"operator(/)",
4591+
"operator(.x.)",
4592+
"sp_kron",
4593+
"transpose",
4594+
"hconjg",
4595+
"matmul"
4596+
],
45824597
"private_symbols": []
45834598
}
45844599
],
@@ -9166,7 +9181,22 @@
91669181
}
91679182
],
91689183
"default_visibility": "private",
9169-
"public_symbols": [],
9184+
"public_symbols": [
9185+
"sparse_dmatrix_csc",
9186+
"sparse_zmatrix_csc",
9187+
"as_sparse",
9188+
"sparse",
9189+
"assignment(=)",
9190+
"operator(+)",
9191+
"operator(-)",
9192+
"operator(*)",
9193+
"operator(/)",
9194+
"operator(.x.)",
9195+
"sp_kron",
9196+
"transpose",
9197+
"hconjg",
9198+
"matmul"
9199+
],
91709200
"private_symbols": []
91719201
}
91729202
}

tests/parser/fortran/fixtures/scifortran/SF_SPARSE_ARRAY_CSR.json

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4578,7 +4578,22 @@
45784578
}
45794579
],
45804580
"default_visibility": "private",
4581-
"public_symbols": [],
4581+
"public_symbols": [
4582+
"sparse_dmatrix_csr",
4583+
"sparse_zmatrix_csr",
4584+
"as_sparse",
4585+
"sparse",
4586+
"assignment(=)",
4587+
"operator(+)",
4588+
"operator(-)",
4589+
"operator(*)",
4590+
"operator(/)",
4591+
"operator(.x.)",
4592+
"kron",
4593+
"transpose",
4594+
"hconjg",
4595+
"matmul"
4596+
],
45824597
"private_symbols": []
45834598
}
45844599
],
@@ -9166,7 +9181,22 @@
91669181
}
91679182
],
91689183
"default_visibility": "private",
9169-
"public_symbols": [],
9184+
"public_symbols": [
9185+
"sparse_dmatrix_csr",
9186+
"sparse_zmatrix_csr",
9187+
"as_sparse",
9188+
"sparse",
9189+
"assignment(=)",
9190+
"operator(+)",
9191+
"operator(-)",
9192+
"operator(*)",
9193+
"operator(/)",
9194+
"operator(.x.)",
9195+
"kron",
9196+
"transpose",
9197+
"hconjg",
9198+
"matmul"
9199+
],
91709200
"private_symbols": []
91719201
}
91729202
}

tests/parser/fortran/fixtures/scifortran/SF_SPARSE_COMMON.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,9 @@
577577
}
578578
],
579579
"default_visibility": "public",
580-
"public_symbols": [],
580+
"public_symbols": [
581+
"shape"
582+
],
581583
"private_symbols": []
582584
}
583585
],
@@ -1164,7 +1166,9 @@
11641166
}
11651167
],
11661168
"default_visibility": "public",
1167-
"public_symbols": [],
1169+
"public_symbols": [
1170+
"shape"
1171+
],
11681172
"private_symbols": []
11691173
}
11701174
}

0 commit comments

Comments
 (0)