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 =
|
base_block =
|
||||||
kind:'base' s ~
|
'base' s ~
|
||||||
id:identifier ':' s >attributes
|
id:identifier ':' s >attributes
|
||||||
n
|
n
|
||||||
choices:{ indent_choice_block }
|
choices:{ indent_choice_block }
|
||||||
|
@ -55,7 +55,6 @@ indent_choice_entry = n '\t\t' >choice_entry ;
|
||||||
|
|
||||||
# Toplevel choice definitions
|
# Toplevel choice definitions
|
||||||
choice_block =
|
choice_block =
|
||||||
kind:`choice_declaration`
|
|
||||||
id:identifier ':' s >attributes entries:{ noindent_choice_entry }
|
id:identifier ':' s >attributes entries:{ noindent_choice_entry }
|
||||||
n
|
n
|
||||||
;
|
;
|
||||||
|
|
|
@ -4,7 +4,8 @@ from glob import glob
|
||||||
from os import path, walk
|
from os import path, walk
|
||||||
from tatsu import parse as tatsu_parse
|
from tatsu import parse as tatsu_parse
|
||||||
import itertools
|
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
|
# 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()
|
GRAMMAR = fh.read()
|
||||||
|
|
||||||
|
|
||||||
def kind_equal_to(compare_to):
|
def filter_instance(cls, iterable):
|
||||||
return lambda item: item["kind"] == compare_to
|
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):
|
def parse(menu):
|
||||||
parsed = tatsu_parse(GRAMMAR, menu)
|
parsed = tatsu_parse(GRAMMAR, menu, semantics=SEMANTICS)
|
||||||
return parsed
|
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):
|
def parse_file(filename):
|
||||||
|
|
|
@ -3,27 +3,77 @@
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
|
|
||||||
|
def _format_tags(tags):
|
||||||
|
return (
|
||||||
|
" :: {}".format(" ".join(["{" + tag + "}" for tag in tags]))
|
||||||
|
if tags else
|
||||||
|
""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Option:
|
class Option:
|
||||||
def __init__(self, id_, name, description):
|
def __init__(self, id_, *, name, description, price, tags):
|
||||||
self.id = id_
|
self.id = id_
|
||||||
self.name = name
|
self.name = name
|
||||||
self.description = description
|
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:
|
class Choice:
|
||||||
def __init__(self, id_, name, description, options):
|
def __init__(self, id_, *, name, description, options):
|
||||||
self.id = id_
|
self.id = id_
|
||||||
self.name = name
|
self.name = name
|
||||||
self.description = description
|
self.description = description
|
||||||
|
|
||||||
self.options: List[Option] = options
|
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.id = id_
|
||||||
self.name = name
|
self.name = name
|
||||||
self.properties = properties
|
self.description = description
|
||||||
|
self.price = price
|
||||||
|
self.tags = tags
|
||||||
|
|
||||||
self.choices: List[Choice] = choices
|
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"""
|
{} --help Print this help text"""
|
||||||
|
|
||||||
|
|
||||||
def definitions():
|
|
||||||
from app.hlds.definitions import location_definitions
|
|
||||||
return location_definitions
|
|
||||||
|
|
||||||
|
|
||||||
def main(filenames):
|
def main(filenames):
|
||||||
locations = parse_files(filenames) if filenames else definitions()
|
if filenames:
|
||||||
print(json.dumps(asjson(locations), indent="\t"))
|
location_definitions = parse_files(filenames)
|
||||||
|
else:
|
||||||
|
from app.hlds.definitions import location_definitions
|
||||||
|
|
||||||
|
print("\n\n".join(map(str, location_definitions)))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
Loading…
Reference in a new issue