Add first version of the HLDS parser

This commit is contained in:
midgard 2019-12-01 01:04:13 +01:00 committed by Midgard
parent c0936d5a45
commit ca199f4a3b
Signed by: midgard
GPG key ID: 511C112F1331BBB4
7 changed files with 380 additions and 0 deletions

27
app/hlds/__init__.py Executable file
View file

@ -0,0 +1,27 @@
#!/usr/bin/env python3
from os import path
from tatsu import parse as tatsu_parse
# TODO Use proper way to get resources, see https://stackoverflow.com/a/10935674
with open(path.join(path.dirname(__file__), "hlds.tatsu")) as fh:
GRAMMAR = fh.read()
def parse(menu):
return tatsu_parse(GRAMMAR, menu)
def main(filename):
import json
from tatsu.util import asjson
with open(filename) as fh:
ast = parse(fh.read())
print(json.dumps(asjson(ast), indent="\t"))
if __name__ == "__main__":
import sys
main(*sys.argv[1:])

87
app/hlds/hlds.tatsu Normal file
View file

@ -0,0 +1,87 @@
# This is a Tatsu file.
# Syntax is explained at
# https://tatsu.readthedocs.io/en/stable/syntax.html
@@grammar :: Hlds
# Don't ignore any whitespace
@@whitespace :: //
@@eol_comments :: /[ \t]*#.*?$/
@@keyword :: single_choice multi_choice base preset only requires except
start = [n] { @:location } $ ;
location_header =
/={3,}\n/ ~
id:identifier ':' s name:string
attributes:{ location_attribute }
/\n={3,}\n+/
;
location_attribute =
n '\t' key:identifier ' ' value:string
;
location = >location_header items:{ block } ;
attributes =
name:/[^\n]*?(?= +-- | +:: | +€ |\n)/
[ s '--' ~ s description:/[^\n]*?(?= +:: | +€ |\n)/ ]
[ s '::' {s ('{' tags+:identifier '}')} ]
[ [ s '::' ~ ] s price:price ]
;
block =
| base_block
| choice_block
;
base_block =
kind:'base' s ~
id:identifier ':' s >attributes
n
choices:{ indent_choice_block }
;
choice_entry = id:identifier ':' s >attributes ;
noindent_choice_entry = n '\t' >choice_entry ;
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
;
# Appears in a base block. One of:
# 1) reference to toplevel choice definition
# 2) inline choice declaration (as opposed to globally declared and referenced)
indent_choice_block =
'\t' type:choice_type s
(
| kind:`reference` id:identifier [ s price:price ]
| kind:`declaration` id:identifier ':' ~ s >attributes entries:{ indent_choice_entry }
)
n
;
s = / +/ ;
n = '\n' {{'\t'} '\n'} ;
@name
identifier = /[a-z0-9_-]+/ ;
string = /[^\n]+/ ;
choice_type = 'single_choice' | 'multi_choice' ;
number = /[0-9]+(\.[0-9]+)?/ ;
currency = '€' ;
price = currency:currency s value:number ;

26
app/hlds/testfrituur.hlds Normal file
View file

@ -0,0 +1,26 @@
============================
testfrituur: Testfrituur
osm https://www.openstreetmap.org/node/4935648725
============================
sauce: Saus
ketchup: Ketchup -- Een tomatensaus met veel suiker € 0.8
mayo: Mayonaise -- Eierdooier en olie € 0.8
curry: Currysaus € 0.8
stoofvlees: Stoofvleessaus € 1.4
base veggieburger: Veggieburger € 4.2
base friet: Friet -- Een pakje friet :: {has_meat} {has_gluten}
single_choice size: Grootte
small: Small € 2
medium: Medium € 2.5
large: Large € 3
xlarge: Extra large -- Je hebt een auto nodig om dit te vervoeren € 50
multi_choice sauce
base vleeskroket: Vleeskroket -- Een vlezige kroket :: {has_meat} € 4.2
base vleeskroket: Vleeskroket :: {has_meat} € 4.2
base vleeskroket: Vleeskroket -- Een vlezige kroket

85
data/fritoloog.hlds Normal file
View file

@ -0,0 +1,85 @@
============================
fritoloog: Fritoloog
osm https://www.openstreetmap.org/node/5813542646
============================
base fries: Frietjes :: {has_meat}
# Gebakken in rundsvet dus {has_meat}
single_choice size: Formaat
extra_small: Extra small € 1.8
small: Small € 2
medium: Medium € 2.5
large: Large € 3.3
multi_choice sauce € 1.4
base standalone_sauce: Saus in potje € 0.8
single_choice sauce
sauce: Saus
ketchup: Ketchup
mayo: Mayonaise
bicky: Bickysaus
stew: Stoofvleessaus :: {has_meat} € 0.5
other: Andere (in commentaar)
extra_cheese: Extra kaas € 0.2
# FIXME extra kaas waarop?
base chicken_fingers: Kippenvingers :: {has_meat} € 3
base nuggiz: Nuggiz :: {has_meat} € 3
base mammoth_sausage: Mammoetworst :: {has_meat} € 2.1
base taco: Taco :: {has_meat} € 2.5
base ragoezi: Ragoezi :: {has_meat} € 2
base gypsy_stick: Zigeunerstick :: {has_meat} € 2
base frikandel: Frikandel :: {has_meat} € 1.5
base frikandel_special: Frikandel special :: {has_meat} € 2.2
base frikandel_xxl: XXL Frikandel :: {has_meat} € 3
base viandel: Viandel :: {has_meat} € 1.8
base viandel_spicy: Spicy-viandel :: {has_meat} € 1.8
base chicken_corn: Kipcorn :: {has_meat} € 1.8
base sito: Sito :: {has_meat} € 2.7
base horse_garlic_sausage: Paardenlookworst :: {has_meat} € 2.4
base garlic_sausage: Lookworst :: {has_meat} € 2.4
base bitterbal: Bitterbal :: {has_meat} € 1.5
base boulet: Boulet :: {has_meat} € 1.8
base chicken_spring_roll: Kippenloempia :: {has_meat} € 3
base meat_croquette: Vleeskroket :: {has_meat} € 1.8
base chicken_drumsticks: Kippenboutjes :: {has_meat} € 3.2
base fire_breather: Vuurvreter :: {has_meat} € 2
base mexicano: Mexicano :: {has_meat} € 2.4
base ardeens_satay: Ardeense saté :: {has_meat} € 2.5
base satay: Saté :: {has_meat} € 2.7
base grisley: Grisley :: {has_meat} € 2.7
base flemish_stew: Stoofvlees :: {has_meat} € 4.5
base meatballs_tomato_sauce: Balletjes in tomatensaus :: {has_meat} € 4.5
base hamburger: Hamburger :: {has_meat} € 2.6
base cheeseburger: Cheeseburger :: {has_meat} € 2.9
base chicken_burger: Chickenburger :: {has_meat} € 3.2
base bicky_burger: Bickyburger :: {has_meat} € 2.9
base bicky_rib: Bicky Rib :: {has_meat} € 3.5
base bicky_royal: Bicky Royal :: {has_meat} € 4.3
base bicky_chicken: Bicky Chicken :: {has_meat} € 3.2
base bicky_wrap: Bicky Wrap :: {has_meat} € 3
base assortment: Twijfelaar :: {has_meat} € 3
base chili_cheese: Chili cheese :: {has_meat} € 2.7
# FIXME zit hier vlees in?
base fish_burger: Fishburger :: {has_fish} € 3
base cod_stick: Kabeljauwstick :: {has_fish} € 2.5
base shrimp_croquette: Garnaalkroket :: {has_fish} € 2
base mozarella_sticks: Mozarellasticks € 3
base cheese_croquette: Kaaskroket € 1.5
base veggi_burger: Veggieburger € 3.2
base cheese_souflesse: Kaassouflesse € 1.5
# https://www.vangeloven.com/merk/souflesse
base bonita: Bonita € 2
# https://www.devriesvanoers.nl/assortiment/specialiteiten/vegetarisch-groentesnack-vries-bonita/
base sajoera: Sajoera € 2
# https://www.devriesvanoers.nl/assortiment/specialiteiten/vegetarisch-groentekroket-vries-sajoera/
base veg_cheese_disc: Groenten-kaasschijf € 2.4
base mini_spring_rolls: Mini-loempia's € 3
base bami: Bami € 2

66
data/oceangarden.hlds Normal file
View file

@ -0,0 +1,66 @@
=============================================
og: Ocean Garden
# Openingsuren, website, telefoonnummer, adres enz. worden uit OpenStreetMap gehaald
osm https://www.openstreetmap.org/node/2275105003
=============================================
bami_nasi: Bami of nasi
bami: Bami -- Tarwenoedels
nasi: Nasi -- Rijst
bami_mihoen: Bami of mihoen
bami: Bami -- Tarwenoedels
mihoen: Mihoen -- Dunne, Chinese noedels, gemaakt van rijstbloem
carbs: Koolhydraten
bami: Bami -- Tarwenoedels
nasi: Nasi -- Rijst
mihoen: Mihoen -- Dunne, Chinese noedels, gemaakt van rijstbloem
# FIXME De balletjes mogen enkel bij gerechten waar je "sweetsour" kán kiezen, en worden enkel
# geactiveerd als "sweetsour" ook effectief gekozen is idealiter staat bij een niet-actieve
# keuze ook de reden erbij
balls: Gepaneerde balletjes € 2.5
#requires sweetsour
sauce: Saus
bali: Bali -- Indonesische saus
yusiang: Yu-siang -- Chinese saus met chili, pijpajuin, gember en look
gonboa: Gon-boa -- Pikante kruidensaus uit het westen van China
curry: Curry
sweetsour: Zoetzuur
oyster: Oester :: {has_fish}
pepper: Pepersaus
mushroom: Champignon
malaysian: A la Maleisië -- Licht pikante saus
meat: Vlees :: {has_meat}
chicken: Kip
pork: Varken
duck: Eend
meat_no_duck: Vlees :: {has_meat}
chicken: Kip
pork: Varken
maybe_meat_no_duck: Vlees
chicken: Kip :: {has_meat}
pork: Varken :: {has_meat}
no_meat: Geen vlees
# Studentenwok 1 en 4 zijn eigenlijk hetzelfde
base wok1_4: Studentenwok met saus € 6
single_choice bamimihoen
single_choice maybe_meat_no_duck
base wok2: Studentenwok kip/varken bami/mihoen zonder saus € 6
single_choice bamimihoen
single_choice meat_no_duck
base wok3: Studentenwok kip bami/nasi zonder saus :: {has_meat} € 6
single_choice baminasi
base wok5: Studentenwok Babi Pangang -- Geroosterd varkensvlees :: {has_meat} € 6
single_choice baminasi
single_choice sauce

View file

@ -0,0 +1,88 @@
# Syntaxprimer:
# • Bestanden kunnen geconcateneerd worden, de syntax “== label: Naam” opent een nieuwe locatie.
# • Alle labels binnen een locatie moeten uniek zijn.
# • “single_choice” is een keyword dat betekent: optiegroep met verplicht 1 keuze. “multi_choice”
# betekent: keuzegroep met 0..∞ keuzes.
# • Dubbelepunt leidt de naam in, dubbele hyphen de beschrijving. Bij basisgerechten en opties kan
# ook een prijs gegeven worden. Alles kan ook tags krijgen, ik dacht aan allergiën of diëten:
# {has_meat} en {has_fish} markeren dingen als niet-vegetarisch. Volgorde is altijd
# “label: Naam -- Beschrijving :: {tag1} {tag2} €prijs”.
# • *label (mix-in) voegt alle entries in in het huidige blok. Bruikbaar in basisgerechten en in
# opties.
# • Attributen propageren van optiegroep naar de opties erin. Daarmee bedoel ik dat de {has_meat}
# op “meat” op de “pork” zal plakken, zodat “wok1_4” {has_meat} krijgt als je “pork” bij kiest.
=============================================
og: Ocean Garden
# Openingsuren, website, telefoonnummer, adres enz. worden uit OpenStreetMap gehaald
osm https://www.openstreetmap.org/node/2275105003
=============================================
carbs: Koolhydraten
bami: Bami -- Noedels
nasi: Nasi -- Rijst
mihoen: Mihoen -- Wtf is dit
# De balletjes worden enkel getoond bij gerechten waar je "sweetsour" kán kiezen, en worden enkel
# geactiveerd als "sweetsour" ook effectief gekozen is idealiter staat bij een niet-actieve
# keuze ook de reden erbij
balls: Gepaneerde balletjes € 2.5
requires sweetsour
baminasi: Bami of nasi
single_choice baminasi
only bami, nasi
sauce: Saus
bali: Bali -- Indonesische saus
yusiang: Yu-siang -- Chinese saus met chili, pijpajuin, gember en look
gonboa: Gon-boa -- Pikante kruidensaus uit het westen van China
curry: Curry -- Iedereen kent het maar niemand weet wat het is
sweetsour: Zoetzuur
oyster: Oester :: {has_fish}
pepper: Pepersaus
mushroom: Champignon -- Wist je dat champignons geen groenten zijn?
malaysian: A la Maleisië -- Licht pikante saus
meat: Vlees :: {has_meat}
chicken: Kip
pork: Varken
duck: Eend
maybe_meat: Vlees
*meat
no_meat: Geen vlees
# Studentenwok 1 en 4 zijn eigenlijk hetzelfde
base wok1_4: Studentenwok met saus € 6
single_choice carbs
except nasi
single_choice maybe_meat
except duck
base wok2: Studentenwok kip/varken bami/mihoen zonder saus € 6
single_choice carbs
except nasi
single_choice meat
only chicken, pork
base wok3: Studentenwok kip bami/nasi zonder saus € 6
single_choice baminasi
single_choice meat
only chicken
base wok5: Studentenwok Babi Pangang -- Geroosterd varkensvlees :: {has_meat} € 6
single_choice baminasi
single_choice sauce
base veggie: VEGETARISCH-PURISTISCH demo-entry waarbij je ENKEL VEGGIE kan kiezen = LETTERLIJIK HET BESTE € 6
single_choice baminasi
single_choice sauce
except {has_fish}
except {has_meat}
preset bbp: Bami Babi Pangang
wok5
bami

View file

@ -11,3 +11,4 @@ Flask-Migrate
Flask-Script Flask-Script
black black
pymysql pymysql
tatsu