Skip to content

Parsers API

AbstractParser

Base class for all parsers.

gmshparser.abstract_parser.AbstractParser

Bases: object

AbstractParser is a superclass of all other parsers.

All other parsers must inheric AbstractParser and implement their own static methods parse and get_section_name.

The first argument of the parse is a mutable mesh object, which parser modifies in-place. The second argument is io, where parser reads the text file line by line using readline(). Parser must stop reading the file to the section end mark, e.g. $EndNodes in the case of parser which is responsible to parse nodes, starting from a section start mark $Nodes.

Another must-to-implement static method is get_section_name(), which must return the name of the line where this parser should activate. For example, if the section name is $Nodes, then get_section_name() must return string $Nodes.

Source code in gmshparser/abstract_parser.py
class AbstractParser(object):
    """AbstractParser is a superclass of all other parsers.

    All other parsers must inheric ``AbstractParser`` and implement their own
    static methods ``parse`` and ``get_section_name``.

    The first argument of the ``parse`` is a mutable ``mesh`` object, which
    parser modifies in-place. The second argument is ``io``, where parser reads
    the text file line by line using `readline()`. Parser must stop reading the
    file to the section end mark, e.g. ``$EndNodes`` in the case of parser
    which is responsible to parse nodes, starting from a section start mark
    ``$Nodes``.

    Another must-to-implement static method is ``get_section_name()``, which
    must return the name of the line where this parser should activate. For
    example, if the section name is ``$Nodes``, then ``get_section_name()``
    must return string ``$Nodes``.
    """

    @staticmethod
    def get_section_name():
        raise NotImplementedError("Not implemented.")

    @staticmethod
    def parse(mesh: Mesh, io: TextIO) -> None:
        raise NotImplementedError("Not implemented.")

MeshFormatParser

Parses $MeshFormat section.

NodesParser

Parses $Nodes section (MSH 2.x and 4.x).

ElementsParser

Parses $Elements section (MSH 2.x and 4.x).

V1 Parsers

NodesParserV1

Parses $NOD section (MSH 1.0).

ElementsParserV1

Parses $ELM section (MSH 1.0).

MainParser

Coordinates all parsers and handles version detection.

gmshparser.main_parser.MainParser

Bases: AbstractParser

The main parser class, using other parsers.

This parser automatically detects the MSH format version and selects the appropriate parsers for that version.

Source code in gmshparser/main_parser.py
class MainParser(AbstractParser):
    """The main parser class, using other parsers.

    This parser automatically detects the MSH format version and selects
    the appropriate parsers for that version.
    """

    def __init__(self, parsers=None):
        """Initialize the main parser.

        Parameters
        ----------
        parsers : list, optional
            List of parser classes to use. If None, parsers will be selected
            automatically based on the detected version.
        """
        self.parsers = parsers
        self.version_detected = False

    def parse(self, mesh: Mesh, io: TextIO) -> None:
        """Parse the mesh file.

        The parser first reads the MeshFormat section to detect the version,
        then selects the appropriate parsers for that version.

        For MSH 1.0 files (which don't have $MeshFormat), version is detected
        from the $NOD section name.

        Parameters
        ----------
        mesh : Mesh
            Mesh object to populate
        io : TextIO
            Input stream to read from

        Raises
        ------
        ValueError
            If the version is not supported or if parsing fails
        """
        for line in io:
            line = line.strip()

            # Check for MSH 1.0 format (starts with $NOD instead of $MeshFormat)
            if line == "$NOD" and not self.version_detected:
                # Set version to 1.0
                mesh.set_version(1.0)
                self.version_detected = True

                # Select MSH 1.0 parsers
                if self.parsers is None:
                    self.parsers = DEFAULT_PARSERS_V1

                # Parse the $NOD section
                try:
                    NodesParserV1.parse(mesh, io)
                except Exception:
                    print("Unable to parse section %s from mesh!" % line)
                    raise
                continue

            # Handle MeshFormat for MSH 2.x and 4.x
            if line == "$MeshFormat" and not self.version_detected:
                try:
                    MeshFormatParser.parse(mesh, io)
                    self.version_detected = True

                    # Select parsers based on detected version if not explicitly set
                    if self.parsers is None:
                        self.parsers = self._get_parsers_for_version(mesh)

                except Exception:
                    print("Unable to parse section %s from mesh!" % line)
                    raise
                continue

            # Then, handle other sections with version-specific parsers
            if self.parsers:
                for parser in self.parsers:
                    if parser.get_section_name() == line:
                        try:
                            parser.parse(mesh, io)
                        except Exception:
                            print("Unable to parse section %s from mesh!" % line)
                            raise
                        break

    def _get_parsers_for_version(self, mesh: Mesh) -> List[Type[AbstractParser]]:
        """Get the appropriate parsers for the detected mesh version.

        Parameters
        ----------
        mesh : Mesh
            Mesh with version information

        Returns
        -------
        List[Type[AbstractParser]]
            List of parser classes to use

        Raises
        ------
        ValueError
            If version information is not available
        """
        version = mesh.get_version()
        if version is None:
            raise ValueError("Cannot determine parsers: version not detected")

        major = mesh.get_version_major()

        if major == 1:
            return DEFAULT_PARSERS_V1
        elif major == 2:
            return DEFAULT_PARSERS_V2
        elif major == 4:
            return DEFAULT_PARSERS_V4
        else:
            raise ValueError(f"Unsupported MSH format version: {version}")

__init__(parsers=None)

Initialize the main parser.

Parameters

parsers : list, optional List of parser classes to use. If None, parsers will be selected automatically based on the detected version.

Source code in gmshparser/main_parser.py
def __init__(self, parsers=None):
    """Initialize the main parser.

    Parameters
    ----------
    parsers : list, optional
        List of parser classes to use. If None, parsers will be selected
        automatically based on the detected version.
    """
    self.parsers = parsers
    self.version_detected = False

parse(mesh, io)

Parse the mesh file.

The parser first reads the MeshFormat section to detect the version, then selects the appropriate parsers for that version.

For MSH 1.0 files (which don't have $MeshFormat), version is detected from the $NOD section name.

Parameters

mesh : Mesh Mesh object to populate io : TextIO Input stream to read from

Raises

ValueError If the version is not supported or if parsing fails

Source code in gmshparser/main_parser.py
def parse(self, mesh: Mesh, io: TextIO) -> None:
    """Parse the mesh file.

    The parser first reads the MeshFormat section to detect the version,
    then selects the appropriate parsers for that version.

    For MSH 1.0 files (which don't have $MeshFormat), version is detected
    from the $NOD section name.

    Parameters
    ----------
    mesh : Mesh
        Mesh object to populate
    io : TextIO
        Input stream to read from

    Raises
    ------
    ValueError
        If the version is not supported or if parsing fails
    """
    for line in io:
        line = line.strip()

        # Check for MSH 1.0 format (starts with $NOD instead of $MeshFormat)
        if line == "$NOD" and not self.version_detected:
            # Set version to 1.0
            mesh.set_version(1.0)
            self.version_detected = True

            # Select MSH 1.0 parsers
            if self.parsers is None:
                self.parsers = DEFAULT_PARSERS_V1

            # Parse the $NOD section
            try:
                NodesParserV1.parse(mesh, io)
            except Exception:
                print("Unable to parse section %s from mesh!" % line)
                raise
            continue

        # Handle MeshFormat for MSH 2.x and 4.x
        if line == "$MeshFormat" and not self.version_detected:
            try:
                MeshFormatParser.parse(mesh, io)
                self.version_detected = True

                # Select parsers based on detected version if not explicitly set
                if self.parsers is None:
                    self.parsers = self._get_parsers_for_version(mesh)

            except Exception:
                print("Unable to parse section %s from mesh!" % line)
                raise
            continue

        # Then, handle other sections with version-specific parsers
        if self.parsers:
            for parser in self.parsers:
                if parser.get_section_name() == line:
                    try:
                        parser.parse(mesh, io)
                    except Exception:
                        print("Unable to parse section %s from mesh!" % line)
                        raise
                    break

See Also