113 lines
2.5 KiB
Python
113 lines
2.5 KiB
Python
|
# After being inspired by...
|
||
|
# craftinginterpreters.com/representing-code.html
|
||
|
# ...I'm implementing the breakfast generator that the author describes
|
||
|
# therein.
|
||
|
|
||
|
import random
|
||
|
import string
|
||
|
|
||
|
# Breakfast
|
||
|
|
||
|
def breakfast():
|
||
|
fn = random.choice([
|
||
|
lambda: " ".join([protein(), "with", breakfast(), "on the side"]),
|
||
|
lambda: protein(),
|
||
|
lambda: bread(),
|
||
|
])
|
||
|
return fn()
|
||
|
|
||
|
def protein():
|
||
|
fn = random.choice([
|
||
|
lambda: " ".join([qualifier(), "crispy", "bacon"]),
|
||
|
lambda: "sausage",
|
||
|
lambda: " ".join([cooking_method(), "sausage"]),
|
||
|
])
|
||
|
return fn()
|
||
|
|
||
|
def qualifier():
|
||
|
fn = random.choice([
|
||
|
lambda: "really",
|
||
|
lambda: "super",
|
||
|
lambda: " ".join(["really", qualifier()]),
|
||
|
])
|
||
|
return fn()
|
||
|
|
||
|
def cooking_method():
|
||
|
return random.choice([
|
||
|
"scrambled",
|
||
|
"poached",
|
||
|
"fried",
|
||
|
])
|
||
|
|
||
|
def bread():
|
||
|
return random.choice([
|
||
|
"toast",
|
||
|
"biscuits",
|
||
|
"English muffin",
|
||
|
])
|
||
|
|
||
|
print(breakfast())
|
||
|
|
||
|
# Expression Language
|
||
|
|
||
|
# Because Python is a strictly evaluated language any functions that are
|
||
|
# mutually recursive won't terminate and will overflow our stack. Therefore, any
|
||
|
# non-terminals expressed in an alternative are wrapped in lambdas as thunks.
|
||
|
|
||
|
def expression():
|
||
|
fn = random.choice([
|
||
|
lambda: literal(),
|
||
|
lambda: binary(),
|
||
|
])
|
||
|
return fn()
|
||
|
|
||
|
def literal():
|
||
|
return str(random.randint(0, 100))
|
||
|
|
||
|
def binary():
|
||
|
return " ".join([expression(), operator(), expression()])
|
||
|
|
||
|
def operator():
|
||
|
return random.choice(["+", "*"])
|
||
|
|
||
|
print(expression())
|
||
|
|
||
|
# Lox
|
||
|
|
||
|
def lox_expression():
|
||
|
fn = random.choice([
|
||
|
lambda: lox_literal(),
|
||
|
lambda: lox_unary(),
|
||
|
lambda: lox_binary(),
|
||
|
lambda: lox_grouping(),
|
||
|
])
|
||
|
return fn()
|
||
|
|
||
|
def lox_literal():
|
||
|
fn = random.choice([
|
||
|
lambda: str(random.randint(0, 100)),
|
||
|
lambda: lox_string(),
|
||
|
lambda: random.choice(["true", "false"]),
|
||
|
lambda: "nil",
|
||
|
])
|
||
|
return fn()
|
||
|
|
||
|
def lox_string():
|
||
|
return "\"{}\"".format(
|
||
|
"".join(random.choice(string.ascii_lowercase)
|
||
|
for _ in range(random.randint(0, 25))))
|
||
|
|
||
|
def lox_grouping():
|
||
|
return "(" + lox_expression() + ")"
|
||
|
|
||
|
def lox_unary():
|
||
|
return random.choice(["-", "!"]) + lox_expression()
|
||
|
|
||
|
def lox_binary():
|
||
|
return lox_expression() + lox_operator() + lox_expression()
|
||
|
|
||
|
def lox_operator():
|
||
|
return random.choice(["==", "!=", "<", "<=", ">", ">=", "+", "-", "*", "/"])
|
||
|
|
||
|
print(lox_expression())
|