Please export and document:
lark.tools.standalone.gen_standalone
While I love the standalone parser, I don't like the fact that the grammar has to live in its own file. My experience is that the grammar and the Transformer evolve in parallel, and having them next to each other makes that task easier.
I've been using the following code to let me quickly switch between using the standalone parser and the standard parser. I've had to reach into lark.tools.standalone and use methods that I'm not sure are public. But the grammar is just a string in the file.
def generate_standalone(filename: Path | str, compress=False, verbose=True):
from lark import lark
from lark.tools.standalone import gen_standalone
parser = lark.Lark(GRAMMAR, parser='lalr', start='statement')
with open(filename, "w") as out:
gen_standalone(parser, out=out, compress=compress)
out.write(f"\nGRAMMAR_HASH = '{get_grammar_hash()}'\n")
assert filename.exists() and filename.stat().st_size > 1_000, f"Failed to generate {filename}"
if verbose:
print(f"Generated {filename} size: {filename.stat().st_size:,} bytes")
def get_grammar_hash() -> str:
return hashlib.sha256(GRAMMAR.encode('utf-8')).hexdigest()
At use time I then have:
USE_PREBUILT = True
# Note that "lark" is a module if USE_PREBUILT is True and a package if it is False.
# This makes "from XX import YY" difficult. However, qualified names, Lark.XX, work the
# same for both, so we use those.
if USE_PREBUILT:
import solver.equation_parser_prebuilt as lark
else:
import lark
.....
def MyParser:
@staticmethod
def get_parser(transformer: lark.Transformer | None) -> lark.Lark:
if not USE_PREBUILT:
parser = lark.Lark(GRAMMAR, parser='lalr', cache=True, start='statement',
transformer=transformer)
else:
parser = lark.Lark_StandAlone(transformer=transformer)
if lark.GRAMMAR_HASH != EquationParser.get_grammar_hash():
raise Exception("Prebuilt parser is out of date")
return parser
Please export and document:
lark.tools.standalone.gen_standalone
While I love the standalone parser, I don't like the fact that the grammar has to live in its own file. My experience is that the grammar and the Transformer evolve in parallel, and having them next to each other makes that task easier.
I've been using the following code to let me quickly switch between using the standalone parser and the standard parser. I've had to reach into lark.tools.standalone and use methods that I'm not sure are public. But the grammar is just a string in the file.
At use time I then have: