lark_parser¶
This submodule implements the LarkParser
class,
which uses the lark library to parse filter strings with a defined OPTIMADE filter grammar
into Lark.Tree
objects for use by the filter transformers.
LarkParser
¶
This class wraps a versioned OPTIMADE grammar and allows it to be parsed into Lark tree objects.
Source code in optimade/filterparser/lark_parser.py
class LarkParser:
"""This class wraps a versioned OPTIMADE grammar and allows
it to be parsed into Lark tree objects.
"""
def __init__(
self, version: Optional[tuple[int, int, int]] = None, variant: str = "default"
):
"""For a given version and variant, try to load the corresponding grammar.
Parameters:
version: The grammar version number to use (e.g., `(1, 0, 1)` for v1.0.1).
variant: The grammar variant to employ.
Raises:
ParserError: If the requested version/variant of the
grammar does not exist.
"""
if not version:
version = max(
_ for _ in AVAILABLE_PARSERS if AVAILABLE_PARSERS[_].get("default")
)
if version not in AVAILABLE_PARSERS:
raise ParserError(f"Unknown parser grammar version: {version}")
if variant not in AVAILABLE_PARSERS[version]:
raise ParserError(f"Unknown variant of the parser: {variant}")
self.version = version
self.variant = variant
with open(AVAILABLE_PARSERS[version][variant]) as f:
self.lark = Lark(f, maybe_placeholders=False)
self.tree: Optional[Tree] = None
self.filter: Optional[str] = None
def parse(self, filter_: str) -> Tree:
"""Parse a filter string into a `lark.Tree`.
Parameters:
filter_: The filter string to parse.
Raises:
BadRequest: If the filter cannot be parsed.
Returns:
The parsed filter.
"""
try:
self.tree = self.lark.parse(filter_)
self.filter = filter_
return self.tree
except Exception as exc:
raise BadRequest(
detail=f"Unable to parse filter {filter_}. Lark traceback: \n{exc}"
) from exc
def __repr__(self):
if isinstance(self.tree, Tree):
return self.tree.pretty()
return repr(self.lark)
__init__(self, version=None, variant='default')
special
¶
For a given version and variant, try to load the corresponding grammar.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
version |
Optional[tuple[int, int, int]] |
The grammar version number to use (e.g., |
None |
variant |
str |
The grammar variant to employ. |
'default' |
Exceptions:
Type | Description |
---|---|
ParserError |
If the requested version/variant of the grammar does not exist. |
Source code in optimade/filterparser/lark_parser.py
def __init__(
self, version: Optional[tuple[int, int, int]] = None, variant: str = "default"
):
"""For a given version and variant, try to load the corresponding grammar.
Parameters:
version: The grammar version number to use (e.g., `(1, 0, 1)` for v1.0.1).
variant: The grammar variant to employ.
Raises:
ParserError: If the requested version/variant of the
grammar does not exist.
"""
if not version:
version = max(
_ for _ in AVAILABLE_PARSERS if AVAILABLE_PARSERS[_].get("default")
)
if version not in AVAILABLE_PARSERS:
raise ParserError(f"Unknown parser grammar version: {version}")
if variant not in AVAILABLE_PARSERS[version]:
raise ParserError(f"Unknown variant of the parser: {variant}")
self.version = version
self.variant = variant
with open(AVAILABLE_PARSERS[version][variant]) as f:
self.lark = Lark(f, maybe_placeholders=False)
self.tree: Optional[Tree] = None
self.filter: Optional[str] = None
parse(self, filter_)
¶
Parse a filter string into a lark.Tree
.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
filter_ |
str |
The filter string to parse. |
required |
Exceptions:
Type | Description |
---|---|
BadRequest |
If the filter cannot be parsed. |
Returns:
Type | Description |
---|---|
Tree |
The parsed filter. |
Source code in optimade/filterparser/lark_parser.py
def parse(self, filter_: str) -> Tree:
"""Parse a filter string into a `lark.Tree`.
Parameters:
filter_: The filter string to parse.
Raises:
BadRequest: If the filter cannot be parsed.
Returns:
The parsed filter.
"""
try:
self.tree = self.lark.parse(filter_)
self.filter = filter_
return self.tree
except Exception as exc:
raise BadRequest(
detail=f"Unable to parse filter {filter_}. Lark traceback: \n{exc}"
) from exc
ParserError (Exception)
¶
Triggered by critical parsing errors that should lead to 500 Server Error HTTP statuses.
Source code in optimade/filterparser/lark_parser.py
class ParserError(Exception):
"""Triggered by critical parsing errors that should lead
to 500 Server Error HTTP statuses.
"""
get_versions()
¶
Find grammar files within this package's grammar directory, returning a dictionary broken down by scraped grammar version (major, minor, patch) and variant (a string tag).
Returns:
Type | Description |
---|---|
dict |
A mapping from version, variant to grammar file name. |
Source code in optimade/filterparser/lark_parser.py
def get_versions() -> dict[tuple[int, int, int], dict[str, Path]]:
"""Find grammar files within this package's grammar directory,
returning a dictionary broken down by scraped grammar version
(major, minor, patch) and variant (a string tag).
Returns:
A mapping from version, variant to grammar file name.
"""
dct: dict[tuple[int, int, int], dict[str, Path]] = {}
for filename in Path(__file__).parent.joinpath("../grammar").glob("*.lark"):
tags = filename.stem.lstrip("v").split(".")
version: tuple[int, int, int] = (int(tags[0]), int(tags[1]), int(tags[2]))
variant: str = "default" if len(tags) == 3 else str(tags[-1])
if version not in dct:
dct[version] = {}
dct[version][variant] = filename
return dct