|
|
@@ -0,0 +1,51 @@ |
|
|
|
""" |
|
|
|
Grammar Composition |
|
|
|
=================== |
|
|
|
|
|
|
|
This example shows how to do grammar composition in Lark, by creating a new |
|
|
|
file format that allows both CSV and JSON to co-exist. |
|
|
|
|
|
|
|
1) We define ``storage.lark``, which imports both ``csv.lark`` and ``json.lark``, |
|
|
|
and allows them to be used one after the other. |
|
|
|
|
|
|
|
In the generated tree, each imported rule/terminal is automatically prefixed (with ``json__`` or ``csv__), |
|
|
|
which creates an implicit namespace and allows them to coexist without collisions. |
|
|
|
|
|
|
|
2) We merge their respective transformers (unaware of each other) into a new base transformer. |
|
|
|
The resulting transformer can evaluate both JSON and CSV in the parse tree. |
|
|
|
|
|
|
|
The methods of each transformer are renamed into their appropriate namespace, using the given prefix. |
|
|
|
This appraoch allows full re-use: the transformers don't need to care if their grammar is used directly, |
|
|
|
or being imported, or who is doing the importing. |
|
|
|
|
|
|
|
""" |
|
|
|
from pathlib import Path |
|
|
|
from lark import Lark |
|
|
|
from json import dumps |
|
|
|
from lark.visitors import Transformer, merge_transformers |
|
|
|
|
|
|
|
from eval_csv import CsvTreeToPandasDict |
|
|
|
from eval_json import JsonTreeToJson |
|
|
|
|
|
|
|
__dir__ = Path(__file__).parent |
|
|
|
|
|
|
|
class Storage(Transformer): |
|
|
|
def start(self, children): |
|
|
|
return children |
|
|
|
|
|
|
|
storage_transformer = merge_transformers(Storage(), csv=CsvTreeToPandasDict(), json=JsonTreeToJson()) |
|
|
|
|
|
|
|
parser = Lark.open("storage.lark", rel_to=__file__) |
|
|
|
|
|
|
|
def main(): |
|
|
|
json_tree = parser.parse(dumps({"test": "a", "dict": { "list": [1, 1.2] }})) |
|
|
|
res = storage_transformer.transform(json_tree) |
|
|
|
print("Just JSON: ", res) |
|
|
|
|
|
|
|
csv_json_tree = parser.parse(open(__dir__ / 'combined_csv_and_json.txt').read()) |
|
|
|
res = storage_transformer.transform(csv_json_tree) |
|
|
|
print("JSON + CSV: ", dumps(res, indent=2)) |
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
|
main() |