Add semantic actions to create models, add str for models
This commit is contained in:
parent
edb1677523
commit
37e3799985
4 changed files with 119 additions and 26 deletions
|
@ -41,7 +41,7 @@ block =
|
|||
;
|
||||
|
||||
base_block =
|
||||
kind:'base' s ~
|
||||
'base' s ~
|
||||
id:identifier ':' s >attributes
|
||||
n
|
||||
choices:{ indent_choice_block }
|
||||
|
@ -55,7 +55,6 @@ indent_choice_entry = n '\t\t' >choice_entry ;
|
|||
|
||||
# Toplevel choice definitions
|
||||
choice_block =
|
||||
kind:`choice_declaration`
|
||||
id:identifier ':' s >attributes entries:{ noindent_choice_entry }
|
||||
n
|
||||
;
|
||||
|
|
|
@ -4,7 +4,8 @@ from glob import glob
|
|||
from os import path, walk
|
||||
from tatsu import parse as tatsu_parse
|
||||
import itertools
|
||||
from .models import Location
|
||||
from .models import Location, Choice, Option, Dish
|
||||
import operator
|
||||
|
||||
|
||||
# TODO Use proper way to get resources, see https://stackoverflow.com/a/10935674
|
||||
|
@ -12,20 +13,64 @@ with open(path.join(path.dirname(__file__), "hlds.tatsu")) as fh:
|
|||
GRAMMAR = fh.read()
|
||||
|
||||
|
||||
def kind_equal_to(compare_to):
|
||||
return lambda item: item["kind"] == compare_to
|
||||
def filter_instance(cls, iterable):
|
||||
return [item for item in iterable if isinstance(item, cls)]
|
||||
|
||||
|
||||
class HldsSemanticActions:
|
||||
def location(self, ast):
|
||||
return Location(
|
||||
ast["id"],
|
||||
name=ast["name"],
|
||||
attributes={att["key"]: att["value"] for att in ast["attributes"]},
|
||||
dishes=filter_instance(Dish, ast["items_"]),
|
||||
)
|
||||
|
||||
def base_block(self, ast):
|
||||
return Dish(
|
||||
ast["id"],
|
||||
name=ast["name"],
|
||||
description=ast["description"],
|
||||
price=ast["price"],
|
||||
tags=ast["tags"] if ast["tags"] else [],
|
||||
choices=ast["choices"],
|
||||
)
|
||||
|
||||
def choice_block(self, ast):
|
||||
return Choice(
|
||||
ast["id"],
|
||||
name=ast["name"],
|
||||
description=ast["description"],
|
||||
options=ast["entries"],
|
||||
)
|
||||
|
||||
def indent_choice_block(self, ast):
|
||||
if ast["kind"] == "declaration":
|
||||
return self.choice_block(ast)
|
||||
else:
|
||||
return ast
|
||||
|
||||
def indent_choice_entry(self, ast):
|
||||
return Option(
|
||||
ast["id"],
|
||||
name=ast["name"],
|
||||
description=ast["description"],
|
||||
price=ast["price"],
|
||||
tags=ast["tags"],
|
||||
)
|
||||
|
||||
def price(self, ast):
|
||||
return "{0[currency]} {0[value]}".format(ast)
|
||||
|
||||
def _default(self, ast):
|
||||
return ast
|
||||
|
||||
SEMANTICS = HldsSemanticActions()
|
||||
|
||||
|
||||
def parse(menu):
|
||||
parsed = tatsu_parse(GRAMMAR, menu)
|
||||
parsed = tatsu_parse(GRAMMAR, menu, semantics=SEMANTICS)
|
||||
return parsed
|
||||
return dict((
|
||||
*((att["key"], att["value"]) for att in parsed["attributes"]),
|
||||
("id", parsed["id"]),
|
||||
("name", parsed["name"]),
|
||||
("choices", (kind_equal_to("choice_declaration"), parsed["items_"])),
|
||||
("bases", (kind_equal_to("base"), parsed["items_"])),
|
||||
))
|
||||
|
||||
|
||||
def parse_file(filename):
|
||||
|
|
|
@ -3,27 +3,77 @@
|
|||
from typing import List
|
||||
|
||||
|
||||
def _format_tags(tags):
|
||||
return (
|
||||
" :: {}".format(" ".join(["{" + tag + "}" for tag in tags]))
|
||||
if tags else
|
||||
""
|
||||
)
|
||||
|
||||
|
||||
class Option:
|
||||
def __init__(self, id_, name, description):
|
||||
def __init__(self, id_, *, name, description, price, tags):
|
||||
self.id = id_
|
||||
self.name = name
|
||||
self.description = description
|
||||
self.price = price
|
||||
self.tags = tags
|
||||
|
||||
def __str__(self):
|
||||
return "{0.id}: {0.name}{1}{2}{3}".format(
|
||||
self,
|
||||
" -- {}".format(self.description) if self.description else "",
|
||||
_format_tags(self.tags),
|
||||
" {}".format(self.price) if self.price else ""
|
||||
)
|
||||
|
||||
|
||||
class Choice:
|
||||
def __init__(self, id_, name, description, options):
|
||||
def __init__(self, id_, *, name, description, options):
|
||||
self.id = id_
|
||||
self.name = name
|
||||
self.description = description
|
||||
|
||||
self.options: List[Option] = options
|
||||
|
||||
def __str__(self):
|
||||
return "{0.id}: {0.name}{1}\n\t\t{2}".format(
|
||||
self,
|
||||
" -- {}".format(self.description) if self.description else "",
|
||||
"\n\t\t".join(map(str, self.options))
|
||||
)
|
||||
|
||||
class Location:
|
||||
def __init__(self, id_, name, properties, choices, bases):
|
||||
|
||||
class Dish:
|
||||
def __init__(self, id_, *, name, description, price, tags, choices):
|
||||
self.id = id_
|
||||
self.name = name
|
||||
self.properties = properties
|
||||
self.description = description
|
||||
self.price = price
|
||||
self.tags = tags
|
||||
|
||||
self.choices: List[Choice] = choices
|
||||
self.bases = bases
|
||||
|
||||
def __str__(self):
|
||||
return "{0.id}: {0.name}{1}{2}{3}\n\t{4}".format(
|
||||
self,
|
||||
" -- {}".format(self.description) if self.description else "",
|
||||
_format_tags(self.tags),
|
||||
" {}".format(self.price) if self.price else "",
|
||||
"\n\t".join(map(str, self.choices))
|
||||
)
|
||||
|
||||
|
||||
class Location:
|
||||
def __init__(self, id_, *, name, attributes, dishes):
|
||||
self.id = id_
|
||||
self.name = name
|
||||
self.attributes = attributes
|
||||
|
||||
self.dishes: List[Dish] = dishes
|
||||
|
||||
def __str__(self):
|
||||
return "============================\n{0.id}: {0.name}\n============================\n\n{1}".format(
|
||||
self,
|
||||
"\n\n".join(map(str, self.dishes))
|
||||
)
|
||||
|
|
|
@ -14,14 +14,13 @@ With filenames as arguments, parse those files as HLDS.
|
|||
{} --help Print this help text"""
|
||||
|
||||
|
||||
def definitions():
|
||||
from app.hlds.definitions import location_definitions
|
||||
return location_definitions
|
||||
|
||||
|
||||
def main(filenames):
|
||||
locations = parse_files(filenames) if filenames else definitions()
|
||||
print(json.dumps(asjson(locations), indent="\t"))
|
||||
if filenames:
|
||||
location_definitions = parse_files(filenames)
|
||||
else:
|
||||
from app.hlds.definitions import location_definitions
|
||||
|
||||
print("\n\n".join(map(str, location_definitions)))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
Loading…
Reference in a new issue