Skip to content

Instantly share code, notes, and snippets.

@edelooff
Created July 11, 2020 10:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save edelooff/7cbddd42b4842a37aa7f0ccb48e9296b to your computer and use it in GitHub Desktop.
Save edelooff/7cbddd42b4842a37aa7f0ccb48e9296b to your computer and use it in GitHub Desktop.
Parsing a simple DSL with Lark
?start: design
design: UCASE SIZE flower* INT+
flower: INT+ LCASE
SIZE: ("S"|"L")
%import common.LCASE_LETTER -> LCASE
%import common.UCASE_LETTER -> UCASE
%import common.INT
%ignore "\n"
from __future__ import annotations
import sys
from collections import Counter
from operator import attrgetter
from typing import Dict, NamedTuple
from lark import Lark
class Design(NamedTuple):
name: str
size: str
required: Dict[Flower, int]
additional: int
class Flower(NamedTuple):
species: str
size: str
def create_design(tree):
name, size, *flower_trees, total_count = tree.children
required = Counter()
for count, species in map(attrgetter('children'), flower_trees):
if (flower := Flower(str(species), str(size))) in required:
raise ValueError(f"Multiple definitions of same required flower {flower}")
required[flower] = int(count)
if (additional := int(total_count) - sum(required.values())) < 0:
raise ValueError("Sum of required flowers greater than total size")
return Design(str(name), str(size), required, additional)
def main(*designs):
parser = Lark.open("design.lark")
for design in designs:
print(design)
print(create_design(parser.parse(design)))
if __name__ == "__main__":
main(*sys.argv[1:])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment