From 292dcef81760237265f675f104717c2a18187184 Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Tue, 2 Jul 2024 13:32:09 -0500 Subject: [PATCH 01/27] Made test case to replicate #396. --- tests/test_source.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 tests/test_source.py diff --git a/tests/test_source.py b/tests/test_source.py new file mode 100644 index 00000000..babf3495 --- /dev/null +++ b/tests/test_source.py @@ -0,0 +1,15 @@ +import montepy +from montepy.data_inputs.data_parser import parse_data +from montepy.input_parser.block_type import BlockType +from montepy.input_parser.mcnp_input import Input + +import pytest + + +@pytest.mark.parametrize( + "line", ["sdef cel=d1 erg=d2 pos=fcel d3 ext=fcel d4 axs=0 0 1 rad=d5"] +) +def test_source_parse_and_parrot(line): + input = Input([line], BlockType.DATA) + data = parse_data(input) + assert data._tree.format() == line From 928562d69f6b50fc53152fe5775c82964153dae0 Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Tue, 2 Jul 2024 16:26:26 -0500 Subject: [PATCH 02/27] Made simpler mechanism to swap parsers without making blank classes. --- montepy/data_inputs/data_input.py | 32 +++++++++++++++++++++++++++++- montepy/data_inputs/data_parser.py | 8 +------- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/montepy/data_inputs/data_input.py b/montepy/data_inputs/data_input.py index 732e193e..1c40ff1d 100644 --- a/montepy/data_inputs/data_input.py +++ b/montepy/data_inputs/data_input.py @@ -4,7 +4,11 @@ import montepy from montepy.errors import * -from montepy.input_parser.data_parser import ClassifierParser, DataParser +from montepy.input_parser.data_parser import ( + ClassifierParser, + DataParser, + ParamOnlyDataParser, +) from montepy.input_parser.mcnp_input import Input from montepy.particle import Particle from montepy.mcnp_object import MCNP_Object @@ -322,8 +326,17 @@ class DataInput(DataInputAbstract): :param input: the Input object representing this data input :type input: Input + :param fast_parse: Whether or not to only parse the first word for the type of data. + :type fast_parse: bool + :param prefix: The input prefix found during parsing (internal use only) + :type prefix: str """ + def __init__(self, input=None, fast_parse=False, prefix=None): + if prefix: + self._load_correct_parser(prefix) + super().__init__(input, fast_parse) + @property def _class_prefix(self): return None @@ -335,3 +348,20 @@ def _has_number(self): # pragma: no cover @property def _has_classifier(self): # pragma: no cover return None + + def _load_correct_parser(self, prefix): + """ + Decides if a specialized parser needs to be loaded for barebone + special cases. + + .. versionadded:: 0.2.11 + """ + PARAM_PARSER = ParamOnlyDataParser + PARSER_PREFIX_MAP = { + "f": montepy.input_parser.tally_parser.TallyParser, + "fm": 1, + "fs": montepy.input_parser.tally_seg_parser.TallySegmentParser, + "sdef": PARAM_PARSER, + } + if prefix.lower() in PARSER_PREFIX_MAP: + self._parser = PARSER_PREFIX_MAP[prefix.lower()]() diff --git a/montepy/data_inputs/data_parser.py b/montepy/data_inputs/data_parser.py index 5e8b9b1b..89eb7ce3 100644 --- a/montepy/data_inputs/data_parser.py +++ b/montepy/data_inputs/data_parser.py @@ -6,8 +6,6 @@ lattice_input, material, mode, - tally, - tally_segment, tally_multiplier, thermal_scattering, universe_input, @@ -22,9 +20,6 @@ lattice_input.LatticeInput, material.Material, mode.Mode, - tally.Tally, - tally_multiplier.TallyMultiplier, - tally_segment.TallySegment, thermal_scattering.ThermalScatteringLaw, transform.Transform, volume.Volume, @@ -47,8 +42,7 @@ def parse_data(input): base_input = data_input.DataInput(input, fast_parse=True) prefix = base_input.prefix - for data_class in PREFIX_MATCHES: if prefix == data_class._class_prefix(): return data_class(input) - return data_input.DataInput(input) + return data_input.DataInput(input, prefix=prefix) From 44092c64c2fa2e5c20f6008ea0135afd8fe4f5ec Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Tue, 2 Jul 2024 16:33:38 -0500 Subject: [PATCH 03/27] Started an sdef style parser. --- montepy/input_parser/__init__.py | 1 + montepy/input_parser/data_parser.py | 53 +++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/montepy/input_parser/__init__.py b/montepy/input_parser/__init__.py index a80864bb..843bcd07 100644 --- a/montepy/input_parser/__init__.py +++ b/montepy/input_parser/__init__.py @@ -10,4 +10,5 @@ from . import read_parser from . import shortcuts from . import surface_parser +from . import tally_seg_parser from . import tokens diff --git a/montepy/input_parser/data_parser.py b/montepy/input_parser/data_parser.py index f54b178f..0c213814 100644 --- a/montepy/input_parser/data_parser.py +++ b/montepy/input_parser/data_parser.py @@ -166,3 +166,56 @@ def data_classifier(self, p): return syntax_node.SyntaxNode( "data input classifier", {"start_pad": padding, "classifier": p.classifier} ) + + +class ParamOnlyDataParser(DataParser): + """ + A parser for parsing parameter (key-value pair) only data inputs. + + .e.g., SDEF + + .. versionadded:: 0.2.11 + + :returns: a syntax tree for the data input. + :rtype: SyntaxNode + """ + + @_( + "param_introduction parameters", + ) + def param_data_input(self, p): + ret = {} + for key, node in p.introduction.nodes.items(): + ret[key] = node + if hasattr(p, "data"): + ret["data"] = p.data + else: + ret["data"] = syntax_node.ListNode("empty data") + if hasattr(p, "parameters"): + ret["parameters"] = p.parameters + return syntax_node.SyntaxNode("data", ret) + + @_( + "classifier_phrase", + "padding classifier_phrase", + ) + def param_introduction(self, p): + ret = {} + if isinstance(p[0], syntax_node.PaddingNode): + ret["start_pad"] = p[0] + else: + ret["start_pad"] = syntax_node.PaddingNode() + ret["classifier"] = p.classifier_phrase + ret["keyword"] = syntax_node.ValueNode(None, str, padding=None) + return syntax_node.SyntaxNode("data intro", ret) + + @_("classifier param_seperator data") + def parameter(self, p): + return syntax_node.SyntaxNode( + p.classifier.prefix.value, + { + "classifier": p.classifier, + "seperator": p.param_seperator, + "data": p.data, + }, + ) From 235edf4583865f1ddbade4c96db2e504df1420d4 Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Tue, 2 Jul 2024 16:34:19 -0500 Subject: [PATCH 04/27] Made a useful debug tool. --- montepy/input_parser/parser_base.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/montepy/input_parser/parser_base.py b/montepy/input_parser/parser_base.py index dcd844ce..5250aa82 100644 --- a/montepy/input_parser/parser_base.py +++ b/montepy/input_parser/parser_base.py @@ -503,6 +503,7 @@ def error(self, token): :param token: the token that broke the parsing rules. :type token: Token """ + self._debug_parsing_error(token) if token: lineno = getattr(token, "lineno", 0) if self._input and self._input.lexer: @@ -523,3 +524,18 @@ def error(self, token): ) else: self.log.parse_error("sly: Parse error in input. EOF\n") + + def _debug_parsing_error(self, token): # pragma: no cover + """ + A function that should be called from error when debugging a parsing error. + + Call this from the method error. Also you will need the relevant debugfile to be set and saving the parser + tables to file. e.g., + + debugfile = 'parser.out' + """ + print("********* New Parsing Error ************ ") + print(f"Token: {token}") + print(f"State: {self.state}, statestack: {self.statestack}") + print(f"Symstack: {self.symstack}") + print() From 3e11f99f062624eac32a3d92eca54e87055eb2f3 Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Tue, 2 Jul 2024 16:35:00 -0500 Subject: [PATCH 05/27] Made parser more reliable and forbid partial success. --- montepy/input_parser/parser_base.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/montepy/input_parser/parser_base.py b/montepy/input_parser/parser_base.py index 5250aa82..80bfabda 100644 --- a/montepy/input_parser/parser_base.py +++ b/montepy/input_parser/parser_base.py @@ -105,6 +105,9 @@ def clear_queue(self): self._parse_fail_queue = [] return ret + def __len__(self): + return len(self._parse_fail_queue) + class MCNP_Parser(Parser, metaclass=MetaBuilder): """ @@ -142,7 +145,11 @@ def parse(self, token_generator, input=None): :rtype: SyntaxNode """ self._input = input - return super().parse(token_generator) + tree = super().parse(token_generator) + # treat any previous errors as being fatal even if it recovered. + if len(self.log) > 0: + return None + return tree precedence = (("left", SPACE), ("left", TEXT)) From 8e04d25d8b18c8b37bf7ac30115fd318d9b0905c Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Tue, 2 Jul 2024 16:35:22 -0500 Subject: [PATCH 06/27] Added doc strings. --- montepy/input_parser/tally_parser.py | 9 ++++++++- montepy/input_parser/tally_seg_parser.py | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/montepy/input_parser/tally_parser.py b/montepy/input_parser/tally_parser.py index 50a8c917..a5468863 100644 --- a/montepy/input_parser/tally_parser.py +++ b/montepy/input_parser/tally_parser.py @@ -4,7 +4,14 @@ class TallyParser(DataParser): - """ """ + """ + A barebone parser for parsing tallies before they are fully implemented. + + .. versionadded:: 0.2.0 + + :returns: a syntax tree for the data input. + :rtype: SyntaxNode + """ debugfile = None diff --git a/montepy/input_parser/tally_seg_parser.py b/montepy/input_parser/tally_seg_parser.py index 25ae0856..bef8e01c 100644 --- a/montepy/input_parser/tally_seg_parser.py +++ b/montepy/input_parser/tally_seg_parser.py @@ -4,7 +4,14 @@ class TallySegmentParser(DataParser): - """ """ + """ + A barebone parser for parsing tally segment inputs before they are fully implemented. + + .. versionadded:: 0.2.10 + + :returns: a syntax tree for the data input. + :rtype: SyntaxNode + """ debugfile = None From caf435621c368c8a1e4e3d50632d97749f16aa62 Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Tue, 2 Jul 2024 16:35:41 -0500 Subject: [PATCH 07/27] Added sdef keywords. --- montepy/input_parser/tokens.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/montepy/input_parser/tokens.py b/montepy/input_parser/tokens.py index 136e7c6b..a62856c2 100644 --- a/montepy/input_parser/tokens.py +++ b/montepy/input_parser/tokens.py @@ -94,6 +94,31 @@ class MCNP_Lexer(Lexer): "refs", # volume "no", + # sdef + "cel", + "sur", + "erg", + "tme", + "dir", + "vec", + "nrm", + "pos", + "rad", + "ext", + "axs", + "x", + "y", + "z", + "ccc", + "ara", + "wgt", + "tr", + "eff", + "par", + "dat", + "loc", + "bem", + "bap", } """ Defines allowed keywords in MCNP. From 8f17a7bdc83037116dec42a75525037ce1259a56 Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Tue, 2 Jul 2024 16:59:15 -0500 Subject: [PATCH 08/27] Removed tally special classes thanks to machinery. --- montepy/data_inputs/data_input.py | 5 +++-- montepy/data_inputs/tally.py | 22 ---------------------- montepy/data_inputs/tally_multiplier.py | 19 ------------------- montepy/data_inputs/tally_segment.py | 22 ---------------------- 4 files changed, 3 insertions(+), 65 deletions(-) delete mode 100644 montepy/data_inputs/tally.py delete mode 100644 montepy/data_inputs/tally_multiplier.py delete mode 100644 montepy/data_inputs/tally_segment.py diff --git a/montepy/data_inputs/data_input.py b/montepy/data_inputs/data_input.py index 1c40ff1d..cffe0355 100644 --- a/montepy/data_inputs/data_input.py +++ b/montepy/data_inputs/data_input.py @@ -357,9 +357,10 @@ def _load_correct_parser(self, prefix): .. versionadded:: 0.2.11 """ PARAM_PARSER = ParamOnlyDataParser + TALLY_PARSER = montepy.input_parser.tally_parser.TallyParser, PARSER_PREFIX_MAP = { - "f": montepy.input_parser.tally_parser.TallyParser, - "fm": 1, + "f": TALLY_PARSER, + "fm": TALLY_PARSER, "fs": montepy.input_parser.tally_seg_parser.TallySegmentParser, "sdef": PARAM_PARSER, } diff --git a/montepy/data_inputs/tally.py b/montepy/data_inputs/tally.py deleted file mode 100644 index ecfc6429..00000000 --- a/montepy/data_inputs/tally.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2024, Battelle Energy Alliance, LLC All Rights Reserved. -import montepy -from montepy.data_inputs.data_input import DataInputAbstract -from montepy.input_parser.tally_parser import TallyParser - - -class Tally(DataInputAbstract): - """ """ - - _parser = TallyParser() - - @staticmethod - def _class_prefix(): - return "f" - - @staticmethod - def _has_number(): - return True - - @staticmethod - def _has_classifier(): - return 1 diff --git a/montepy/data_inputs/tally_multiplier.py b/montepy/data_inputs/tally_multiplier.py deleted file mode 100644 index 3c954a6f..00000000 --- a/montepy/data_inputs/tally_multiplier.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2024, Battelle Energy Alliance, LLC All Rights Reserved. -from montepy.data_inputs.data_input import DataInputAbstract -from montepy.input_parser.tally_parser import TallyParser - - -class TallyMultiplier(DataInputAbstract): - _parser = TallyParser() - - @staticmethod - def _class_prefix(): - return "fm" - - @staticmethod - def _has_number(): - return True - - @staticmethod - def _has_classifier(): - return 0 diff --git a/montepy/data_inputs/tally_segment.py b/montepy/data_inputs/tally_segment.py deleted file mode 100644 index 9a78cea2..00000000 --- a/montepy/data_inputs/tally_segment.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2024, Battelle Energy Alliance, LLC All Rights Reserved. -import montepy -from montepy.data_inputs.data_input import DataInputAbstract -from montepy.input_parser.tally_seg_parser import TallySegmentParser - - -class TallySegment(DataInputAbstract): - """ """ - - _parser = TallySegmentParser() - - @staticmethod - def _class_prefix(): - return "fs" - - @staticmethod - def _has_number(): - return True - - @staticmethod - def _has_classifier(): - return 0 From 1bd79b9813045d2cbd87523c8e96733a5d61402d Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Tue, 2 Jul 2024 17:02:15 -0500 Subject: [PATCH 09/27] Cleaned up a few issues. --- montepy/data_inputs/data_input.py | 2 +- montepy/data_inputs/data_parser.py | 1 - montepy/input_parser/__init__.py | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/montepy/data_inputs/data_input.py b/montepy/data_inputs/data_input.py index cffe0355..38c602ed 100644 --- a/montepy/data_inputs/data_input.py +++ b/montepy/data_inputs/data_input.py @@ -357,7 +357,7 @@ def _load_correct_parser(self, prefix): .. versionadded:: 0.2.11 """ PARAM_PARSER = ParamOnlyDataParser - TALLY_PARSER = montepy.input_parser.tally_parser.TallyParser, + TALLY_PARSER = montepy.input_parser.tally_parser.TallyParser PARSER_PREFIX_MAP = { "f": TALLY_PARSER, "fm": TALLY_PARSER, diff --git a/montepy/data_inputs/data_parser.py b/montepy/data_inputs/data_parser.py index 89eb7ce3..7d0ca9a2 100644 --- a/montepy/data_inputs/data_parser.py +++ b/montepy/data_inputs/data_parser.py @@ -6,7 +6,6 @@ lattice_input, material, mode, - tally_multiplier, thermal_scattering, universe_input, volume, diff --git a/montepy/input_parser/__init__.py b/montepy/input_parser/__init__.py index 843bcd07..e6a83a8f 100644 --- a/montepy/input_parser/__init__.py +++ b/montepy/input_parser/__init__.py @@ -10,5 +10,6 @@ from . import read_parser from . import shortcuts from . import surface_parser +from . import tally_parser from . import tally_seg_parser from . import tokens From 2c3c3cbf1eece309649069453749b75e604a1cac Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Tue, 2 Jul 2024 17:03:23 -0500 Subject: [PATCH 10/27] Made progress on making an sdef parser. --- montepy/input_parser/data_parser.py | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/montepy/input_parser/data_parser.py b/montepy/input_parser/data_parser.py index 0c213814..09555bff 100644 --- a/montepy/input_parser/data_parser.py +++ b/montepy/input_parser/data_parser.py @@ -16,7 +16,7 @@ class DataParser(MCNP_Parser): :rtype: SyntaxNode """ - debugfile = None + debugfile = "parser.out" @_( "introduction", @@ -181,7 +181,7 @@ class ParamOnlyDataParser(DataParser): """ @_( - "param_introduction parameters", + "param_introduction spec_parameters", ) def param_data_input(self, p): ret = {} @@ -209,8 +209,26 @@ def param_introduction(self, p): ret["keyword"] = syntax_node.ValueNode(None, str, padding=None) return syntax_node.SyntaxNode("data intro", ret) + @_("spec_parameter", "spec_parameters spec_parameter") + def spec_parameters(self, p): + """ + A list of the parameters (key, value pairs) for this input. + + :returns: all parameters + :rtype: ParametersNode + """ + print(list(p)) + if len(p) == 1: + params = syntax_node.ParametersNode() + param = p[0] + else: + params = p[0] + param = p[1] + params.append(param) + return params + @_("classifier param_seperator data") - def parameter(self, p): + def spec_parameter(self, p): return syntax_node.SyntaxNode( p.classifier.prefix.value, { From b6b417ecd12e39926a553f3bea8dc01118c0e825 Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Tue, 2 Jul 2024 17:05:51 -0500 Subject: [PATCH 11/27] Added sdef bug to changelog. --- doc/source/changelog.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/source/changelog.rst b/doc/source/changelog.rst index 206d3fab..40e9d9dd 100644 --- a/doc/source/changelog.rst +++ b/doc/source/changelog.rst @@ -1,6 +1,13 @@ MontePy Changelog ================= +#Next Version# +------------------- + +**Bug fixes** + +* Fixed bug with ``SDEF`` input, and made parser more robust (:issue:`396`). + 0.2.10 ---------------------- From 6963bb2d398c2c69c4bd2e83d8ac4de4e7345e8e Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Mon, 8 Jul 2024 13:04:52 -0500 Subject: [PATCH 12/27] Switched to montepy.org email. --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 3b62cd62..f9d79c43 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,10 +7,10 @@ description = "A library for reading, editing, and writing MCNP input files" readme = "README.md" requires-python = ">=3.8" maintainers = [ - {name = "Micah Gale", email = "micah.gale@inl.gov"} + {name = "Micah Gale", email = "mgale@montepy.org"} ] authors = [ - {name = "Micah Gale", email = "micah.gale@inl.gov"}, + {name = "Micah Gale", email = "mgale@montepy.org"} {name = "Travis Labossiere-Hickman", email = "Travis.LabossiereHickman@inl.gov"}, {name = "Brenna Carbno", email="brenna.carbno@inl.gov"} ] From 2b0b20c47a9388ec864ed4171734b4a37653c066 Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Mon, 8 Jul 2024 13:08:15 -0500 Subject: [PATCH 13/27] Fixed syntax error. --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index f9d79c43..0d868937 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ maintainers = [ {name = "Micah Gale", email = "mgale@montepy.org"} ] authors = [ - {name = "Micah Gale", email = "mgale@montepy.org"} + {name = "Micah Gale", email = "mgale@montepy.org"}, {name = "Travis Labossiere-Hickman", email = "Travis.LabossiereHickman@inl.gov"}, {name = "Brenna Carbno", email="brenna.carbno@inl.gov"} ] From 3356e9b16a0d93c95a0f656e772e4555473a58b4 Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Mon, 8 Jul 2024 13:14:53 -0500 Subject: [PATCH 14/27] Removed tallies from documentation site. --- doc/source/api/montepy.data_inputs.rst | 2 -- doc/source/api/montepy.data_inputs.tally.rst | 8 -------- doc/source/api/montepy.data_inputs.tally_multiplier.rst | 8 -------- 3 files changed, 18 deletions(-) delete mode 100644 doc/source/api/montepy.data_inputs.tally.rst delete mode 100644 doc/source/api/montepy.data_inputs.tally_multiplier.rst diff --git a/doc/source/api/montepy.data_inputs.rst b/doc/source/api/montepy.data_inputs.rst index 3471a48c..bce4790c 100644 --- a/doc/source/api/montepy.data_inputs.rst +++ b/doc/source/api/montepy.data_inputs.rst @@ -24,8 +24,6 @@ montepy.data\_inputs package montepy.data_inputs.material_component montepy.data_inputs.mode montepy.data_inputs.thermal_scattering - montepy.data_inputs.tally - montepy.data_inputs.tally_multiplier montepy.data_inputs.transform montepy.data_inputs.universe_input montepy.data_inputs.volume diff --git a/doc/source/api/montepy.data_inputs.tally.rst b/doc/source/api/montepy.data_inputs.tally.rst deleted file mode 100644 index dc16f381..00000000 --- a/doc/source/api/montepy.data_inputs.tally.rst +++ /dev/null @@ -1,8 +0,0 @@ -montepy.data\_inputs.tally module -================================= - - -.. automodule:: montepy.data_inputs.tally - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/source/api/montepy.data_inputs.tally_multiplier.rst b/doc/source/api/montepy.data_inputs.tally_multiplier.rst deleted file mode 100644 index f38e1552..00000000 --- a/doc/source/api/montepy.data_inputs.tally_multiplier.rst +++ /dev/null @@ -1,8 +0,0 @@ -montepy.data\_inputs.tally_multiplier module -============================================ - - -.. automodule:: montepy.data_inputs.tally_multiplier - :members: - :undoc-members: - :show-inheritance: From 355a8d78d14a9b150840db5ec049686e40476763 Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Mon, 8 Jul 2024 16:30:14 -0500 Subject: [PATCH 15/27] Fixed sdef parser by making it its mostly own thing. --- montepy/input_parser/data_parser.py | 57 +++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/montepy/input_parser/data_parser.py b/montepy/input_parser/data_parser.py index 09555bff..6f65f7a4 100644 --- a/montepy/input_parser/data_parser.py +++ b/montepy/input_parser/data_parser.py @@ -16,7 +16,7 @@ class DataParser(MCNP_Parser): :rtype: SyntaxNode """ - debugfile = "parser.out" + debugfile = None @_( "introduction", @@ -180,19 +180,17 @@ class ParamOnlyDataParser(DataParser): :rtype: SyntaxNode """ + debugfile = None + @_( "param_introduction spec_parameters", ) def param_data_input(self, p): ret = {} - for key, node in p.introduction.nodes.items(): + for key, node in p.param_introduction.nodes.items(): ret[key] = node - if hasattr(p, "data"): - ret["data"] = p.data - else: - ret["data"] = syntax_node.ListNode("empty data") - if hasattr(p, "parameters"): - ret["parameters"] = p.parameters + if hasattr(p, "spec_parameters"): + ret["parameters"] = p.spec_parameters return syntax_node.SyntaxNode("data", ret) @_( @@ -217,7 +215,6 @@ def spec_parameters(self, p): :returns: all parameters :rtype: ParametersNode """ - print(list(p)) if len(p) == 1: params = syntax_node.ParametersNode() param = p[0] @@ -227,13 +224,49 @@ def spec_parameters(self, p): params.append(param) return params - @_("classifier param_seperator data") + @_("spec_classifier param_seperator data") def spec_parameter(self, p): return syntax_node.SyntaxNode( - p.classifier.prefix.value, + p.spec_classifier.prefix.value, { - "classifier": p.classifier, + "classifier": p.spec_classifier, "seperator": p.param_seperator, "data": p.data, }, ) + + @_( + "KEYWORD", + ) + def spec_data_prefix(self, p): + return syntax_node.ValueNode(p[0], str) + + @_( + "modifier spec_data_prefix", + "spec_data_prefix", + "spec_classifier NUMBER", + "spec_classifier particle_type", + ) + def spec_classifier(self, p): + """ + The classifier of a data input. + + This represents the first word of the data input. + E.g.: ``M4``, `IMP:N`, ``F104:p`` + + :rtype: ClassifierNode + """ + if hasattr(p, "spec_classifier"): + classifier = p.spec_classifier + else: + classifier = syntax_node.ClassifierNode() + + if hasattr(p, "modifier"): + classifier.modifier = syntax_node.ValueNode(p.modifier, str) + if hasattr(p, "spec_data_prefix"): + classifier.prefix = p.spec_data_prefix + if hasattr(p, "NUMBER"): + classifier.number = syntax_node.ValueNode(p.NUMBER, int) + if hasattr(p, "particle_type"): + classifier.particles = p.particle_type + return classifier From 1c7c19f99b78c40c7c2d4dfdb71ec04183a226df Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Mon, 8 Jul 2024 16:30:35 -0500 Subject: [PATCH 16/27] Made state by state bebugger. --- montepy/input_parser/parser_base.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/montepy/input_parser/parser_base.py b/montepy/input_parser/parser_base.py index 80bfabda..3204cc1f 100644 --- a/montepy/input_parser/parser_base.py +++ b/montepy/input_parser/parser_base.py @@ -145,6 +145,15 @@ def parse(self, token_generator, input=None): :rtype: SyntaxNode """ self._input = input + + # debug every time a token is taken + def gen_wrapper(): + while True: + token = next(token_generator, None) + self._debug_parsing_error(token) + yield token + + # change to using `gen_wrapper()` to debug tree = super().parse(token_generator) # treat any previous errors as being fatal even if it recovered. if len(self.log) > 0: @@ -510,7 +519,6 @@ def error(self, token): :param token: the token that broke the parsing rules. :type token: Token """ - self._debug_parsing_error(token) if token: lineno = getattr(token, "lineno", 0) if self._input and self._input.lexer: From 873456e29b1eb3a633d9be5d01e91e0b0829bf8f Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Mon, 8 Jul 2024 17:26:51 -0500 Subject: [PATCH 17/27] Tried to make ListNode update no padding if values are rammed together. --- montepy/input_parser/syntax_node.py | 29 +++++++++++++++++++++++++++++ tests/test_source.py | 1 + 2 files changed, 30 insertions(+) diff --git a/montepy/input_parser/syntax_node.py b/montepy/input_parser/syntax_node.py index 496a7280..c0aca535 100644 --- a/montepy/input_parser/syntax_node.py +++ b/montepy/input_parser/syntax_node.py @@ -375,6 +375,15 @@ def is_space(self, i): return False return len(val.strip()) == 0 and val != "\n" + def has_space(self): + """ + Determines if there is syntactically significant space anywhere in this node. + + :returns: True if there is syntactically significant (not in a comment) space. + :rtype: bool + """ + return any([self.is_space(i) for i in range(len(self))]) + def append(self, val, is_comment=False): """ Append the node to this node. @@ -1031,6 +1040,20 @@ def value(self): """ return self._value + @property + def never_pad(self): + """ + Whether or not this value node will not have extra spaces added. + + :returns: true if extra padding is not adding at the end if missing. + :rtype: bool + """ + return self._never_pad + + @never_pad.setter + def never_pad(self, never_pad): + self._never_pad = never_pad + @value.setter def value(self, value): if self.is_negative is not None and value is not None: @@ -1335,6 +1358,12 @@ def append(self, val): """ if isinstance(val, ShortcutNode): self._shortcuts.append(val) + if len(self) > 0: + last = self[-1] + if isinstance(last, ValueNode) and ( + (last.padding and not last.padding.has_space) or last.padding is None + ): + self[-1].never_pad = True super().append(val) @property diff --git a/tests/test_source.py b/tests/test_source.py index babf3495..ef50f009 100644 --- a/tests/test_source.py +++ b/tests/test_source.py @@ -12,4 +12,5 @@ def test_source_parse_and_parrot(line): input = Input([line], BlockType.DATA) data = parse_data(input) + print(repr(data._tree)) assert data._tree.format() == line From 33098e1af1be38877f92dafa9d1d2bd2fce9585e Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Tue, 9 Jul 2024 07:38:15 -0500 Subject: [PATCH 18/27] Add never_pad test to list_node format. --- montepy/input_parser/syntax_node.py | 1 + 1 file changed, 1 insertion(+) diff --git a/montepy/input_parser/syntax_node.py b/montepy/input_parser/syntax_node.py index c0aca535..bea412d0 100644 --- a/montepy/input_parser/syntax_node.py +++ b/montepy/input_parser/syntax_node.py @@ -1382,6 +1382,7 @@ def format(self): and node.padding is None and i < length - 1 and not isinstance(self.nodes[i + 1], PaddingNode) + and not node.never_pad ): node.padding = PaddingNode(" ") if isinstance(last_node, ShortcutNode) and isinstance(node, ShortcutNode): From cf56a485454fb765634d4cc85d744f7f2a441fea Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Tue, 9 Jul 2024 08:05:30 -0500 Subject: [PATCH 19/27] Documented final step of deploy process. --- doc/source/developing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/developing.rst b/doc/source/developing.rst index 459738b9..217a032c 100644 --- a/doc/source/developing.rst +++ b/doc/source/developing.rst @@ -126,7 +126,7 @@ For a deployment you need to: #. Run the deploy script : ``.github/scripts/deploy.sh`` #. Manually merge onto main without creating a new commit. This is necessary because there's no way to do a github PR that will not create a new commit, which will break setuptools_scm. - +#. Update the release notes on the draft release, and finalize it on GitHub. Package Structure ----------------- From 8d35edb759e419d3661c19a21d2466ac44da4d30 Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Tue, 9 Jul 2024 08:06:41 -0500 Subject: [PATCH 20/27] Created system to only flag never_pad during parsing. --- montepy/input_parser/data_parser.py | 10 +++++----- montepy/input_parser/syntax_node.py | 6 ++++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/montepy/input_parser/data_parser.py b/montepy/input_parser/data_parser.py index 6f65f7a4..e3245ca8 100644 --- a/montepy/input_parser/data_parser.py +++ b/montepy/input_parser/data_parser.py @@ -86,10 +86,10 @@ def zaid_phrase(self, p): def particle_sequence(self, p): if len(p) == 1: sequence = syntax_node.ListNode("particle sequence") - sequence.append(p[0]) + sequence.append(p[0], True) else: sequence = p[0] - sequence.append(p[1]) + sequence.append(p[1], True) return sequence @_("PARTICLE", "SURFACE_TYPE", "PARTICLE_SPECIAL") @@ -114,10 +114,10 @@ def text_phrase(self, p): def text_sequence(self, p): if len(p) == 1: sequence = syntax_node.ListNode("text sequence") - sequence.append(p[0]) + sequence.append(p[0], True) else: sequence = p[0] - sequence.append(p[1]) + sequence.append(p[1], True) return sequence @_("kitchen_junk", "kitchen_sink kitchen_junk") @@ -125,7 +125,7 @@ def kitchen_sink(self, p): sequence = p[0] if len(p) != 1: for node in p[1].nodes: - sequence.append(node) + sequence.append(node, True) return sequence @_("number_sequence", "text_sequence", "particle_sequence") diff --git a/montepy/input_parser/syntax_node.py b/montepy/input_parser/syntax_node.py index bea412d0..acc31efc 100644 --- a/montepy/input_parser/syntax_node.py +++ b/montepy/input_parser/syntax_node.py @@ -1349,16 +1349,18 @@ def check_for_orphan_jump(value): else: check_for_orphan_jump(new_vals[i]) - def append(self, val): + def append(self, val, from_parsing=False): """ Append the node to this node. :param node: node :type node: ValueNode, ShortcutNode + :param from_parsing: If this is being append from the parsers, and not elsewhere. + :type from_parsing: bool """ if isinstance(val, ShortcutNode): self._shortcuts.append(val) - if len(self) > 0: + if len(self) > 0 and from_parsing: last = self[-1] if isinstance(last, ValueNode) and ( (last.padding and not last.padding.has_space) or last.padding is None From b6d3598c44fc261d3b77c411b3ec5fd5be2d4144 Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Tue, 9 Jul 2024 17:02:11 -0500 Subject: [PATCH 21/27] Tried new logic for clearing never_pad. Failed. --- montepy/data_inputs/cell_modifier.py | 8 ++++---- montepy/input_parser/syntax_node.py | 5 ++++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/montepy/data_inputs/cell_modifier.py b/montepy/data_inputs/cell_modifier.py index 87330e02..e95a1935 100644 --- a/montepy/data_inputs/cell_modifier.py +++ b/montepy/data_inputs/cell_modifier.py @@ -255,10 +255,10 @@ def format_for_mcnp_input(self, mcnp_version): C = is_worth_pring Logic: - A!BC + !ABC - C *(A!B + !AB) - C * (A xor B) - C * (A != B) + 1. A!BC + !ABC + 2. C *(A!B + !AB) + 3. C * (A xor B) + 4. C * (A != B) """ # print in either block if (self.in_cell_block != print_in_data_block) and self._is_worth_printing: diff --git a/montepy/input_parser/syntax_node.py b/montepy/input_parser/syntax_node.py index acc31efc..0bc3f74b 100644 --- a/montepy/input_parser/syntax_node.py +++ b/montepy/input_parser/syntax_node.py @@ -1062,7 +1062,10 @@ def value(self, value): self._value = value def _check_if_needs_end_padding(self, value): - if value is None or self.value is not None or self._never_pad: + # disable never pad for former jump + if value is not None and self.value is None: + self.never_pad = False + if value is None or self.value is None or self._never_pad: return # if not followed by a trailing space if self.padding is None: From 64052aefdee2ab2aebd0763ab632468e2b743bd6 Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Wed, 10 Jul 2024 08:24:45 -0500 Subject: [PATCH 22/27] Revert "Tried new logic for clearing never_pad. Failed." This reverts commit b6d3598c44fc261d3b77c411b3ec5fd5be2d4144. --- montepy/input_parser/syntax_node.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/montepy/input_parser/syntax_node.py b/montepy/input_parser/syntax_node.py index 0bc3f74b..acc31efc 100644 --- a/montepy/input_parser/syntax_node.py +++ b/montepy/input_parser/syntax_node.py @@ -1062,10 +1062,7 @@ def value(self, value): self._value = value def _check_if_needs_end_padding(self, value): - # disable never pad for former jump - if value is not None and self.value is None: - self.never_pad = False - if value is None or self.value is None or self._never_pad: + if value is None or self.value is not None or self._never_pad: return # if not followed by a trailing space if self.padding is None: From dfc762e1f3879d514ba4754831c6ad13c552f39d Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Wed, 10 Jul 2024 08:51:35 -0500 Subject: [PATCH 23/27] Don't label jump as never pad as the logic is handled elsewhere. --- montepy/input_parser/syntax_node.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/montepy/input_parser/syntax_node.py b/montepy/input_parser/syntax_node.py index acc31efc..437b065a 100644 --- a/montepy/input_parser/syntax_node.py +++ b/montepy/input_parser/syntax_node.py @@ -1654,9 +1654,7 @@ def _expand_jump(self, p): jump_num = 1 self._num_node = ValueNode(None, int, never_pad=True) for i in range(jump_num): - self._nodes.append( - ValueNode(input_parser.mcnp_input.Jump(), float, never_pad=True) - ) + self._nodes.append(ValueNode(input_parser.mcnp_input.Jump(), float)) def _expand_interpolate(self, p): if self._type == Shortcuts.LOG_INTERPOLATE: From 3ae1bfa9ba15ec986b65b56bf31006d81e814b95 Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Wed, 10 Jul 2024 08:51:51 -0500 Subject: [PATCH 24/27] relaxed tests with trailing spaces. --- tests/test_integration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_integration.py b/tests/test_integration.py index c4ba5afb..52454505 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -783,7 +783,7 @@ def test_universe_data_formatter(self): with self.assertWarns(LineExpansionWarning): output = problem.cells._universe.format_for_mcnp_input((6, 2, 0)) print(output) - self.assertIn("u 350 2J -1 J 350", output) + self.assertIn("u 350 2J -1 J 350 ", output) def test_universe_number_collision(self): problem = montepy.read_input( From ce11882e87edc64f26d73a7dfff3da978bae6b04 Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Wed, 10 Jul 2024 09:01:47 -0500 Subject: [PATCH 25/27] Removed crufty infinite recursion line. --- montepy/input_parser/parser_base.py | 1 - 1 file changed, 1 deletion(-) diff --git a/montepy/input_parser/parser_base.py b/montepy/input_parser/parser_base.py index 3204cc1f..75846269 100644 --- a/montepy/input_parser/parser_base.py +++ b/montepy/input_parser/parser_base.py @@ -52,7 +52,6 @@ def _flatten_rules(classname, basis, attributes): for par_basis in parent: if par_basis != Parser: return - MetaBuilder._flatten_rules(classname, par_basis, attributes) class SLY_Supressor: From 20089977218ff5d0f507ff0d6ca986d3498d7bc4 Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Wed, 10 Jul 2024 09:12:59 -0500 Subject: [PATCH 26/27] Added test for has space. --- tests/test_syntax_parsing.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/test_syntax_parsing.py b/tests/test_syntax_parsing.py index a59a4e05..9bd42fe1 100644 --- a/tests/test_syntax_parsing.py +++ b/tests/test_syntax_parsing.py @@ -1,6 +1,7 @@ # Copyright 2024, Battelle Energy Alliance, LLC All Rights Reserved. import copy from io import StringIO +import pytest from unittest import TestCase import montepy @@ -567,6 +568,22 @@ def test_blank_dollar_comment(self): self.assertEqual(len(comment.contents), 0) +@pytest.mark.parametrize( + "padding,expect", + [ + (["$ hi"], False), + ([" c style comment"], False), + ([" "], True), + (["$ hi", " ", "c hi"], True), + ], +) +def test_padding_has_space(padding, expect): + node = syntax_node.PaddingNode(padding[0]) + for pad in padding[1:]: + node.append(pad) + assert node.has_space() == expect + + class TestParticlesNode(TestCase): def test_particle_init(self): parts = syntax_node.ParticleNode("test", ":n,p,e") From 0d27e03e736330556e04d719632c83236b1214f4 Mon Sep 17 00:00:00 2001 From: "Micah D. Gale" Date: Wed, 17 Jul 2024 16:58:15 -0500 Subject: [PATCH 27/27] correct next version release number. --- montepy/data_inputs/data_input.py | 2 +- montepy/input_parser/data_parser.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/montepy/data_inputs/data_input.py b/montepy/data_inputs/data_input.py index 38c602ed..80b0fd59 100644 --- a/montepy/data_inputs/data_input.py +++ b/montepy/data_inputs/data_input.py @@ -354,7 +354,7 @@ def _load_correct_parser(self, prefix): Decides if a specialized parser needs to be loaded for barebone special cases. - .. versionadded:: 0.2.11 + .. versionadded:: 0.3.0 """ PARAM_PARSER = ParamOnlyDataParser TALLY_PARSER = montepy.input_parser.tally_parser.TallyParser diff --git a/montepy/input_parser/data_parser.py b/montepy/input_parser/data_parser.py index e3245ca8..57635454 100644 --- a/montepy/input_parser/data_parser.py +++ b/montepy/input_parser/data_parser.py @@ -174,7 +174,7 @@ class ParamOnlyDataParser(DataParser): .e.g., SDEF - .. versionadded:: 0.2.11 + .. versionadded:: 0.3.0 :returns: a syntax tree for the data input. :rtype: SyntaxNode