|
@@ -0,0 +1,80 @@ |
|
|
|
|
|
# This example implements a LOGO-like toy language for Python's turtle, with interpreter. |
|
|
|
|
|
|
|
|
|
|
|
import turtle |
|
|
|
|
|
|
|
|
|
|
|
from lark import Lark |
|
|
|
|
|
|
|
|
|
|
|
turtle_grammar = """ |
|
|
|
|
|
start: instruction+ |
|
|
|
|
|
|
|
|
|
|
|
instruction: MOVEMENT NUMBER -> movement |
|
|
|
|
|
| "c" COLOR [COLOR] -> change_color |
|
|
|
|
|
| "fill" code_block -> fill |
|
|
|
|
|
| "repeat" NUMBER code_block -> repeat |
|
|
|
|
|
|
|
|
|
|
|
code_block: "{" instruction+ "}" |
|
|
|
|
|
|
|
|
|
|
|
MOVEMENT: "f"|"b"|"l"|"r" |
|
|
|
|
|
COLOR: LETTER+ |
|
|
|
|
|
|
|
|
|
|
|
%import common.LETTER |
|
|
|
|
|
%import common.INT -> NUMBER |
|
|
|
|
|
%import common.WS |
|
|
|
|
|
%ignore WS |
|
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
parser = Lark(turtle_grammar) |
|
|
|
|
|
|
|
|
|
|
|
def run_instruction(t): |
|
|
|
|
|
if t.data == 'change_color': |
|
|
|
|
|
turtle.color(*t.children) # We just pass the color names as-is |
|
|
|
|
|
|
|
|
|
|
|
elif t.data == 'movement': |
|
|
|
|
|
name, number = t.children |
|
|
|
|
|
{ 'f': turtle.fd, |
|
|
|
|
|
'b': turtle.bk, |
|
|
|
|
|
'l': turtle.lt, |
|
|
|
|
|
'r': turtle.rt, }[name](int(number)) |
|
|
|
|
|
|
|
|
|
|
|
elif t.data == 'repeat': |
|
|
|
|
|
count, block = t.children |
|
|
|
|
|
for i in range(int(count)): |
|
|
|
|
|
run_instruction(block) |
|
|
|
|
|
|
|
|
|
|
|
elif t.data == 'fill': |
|
|
|
|
|
turtle.begin_fill() |
|
|
|
|
|
run_instruction(t.children[0]) |
|
|
|
|
|
turtle.end_fill() |
|
|
|
|
|
|
|
|
|
|
|
elif t.data == 'code_block': |
|
|
|
|
|
for cmd in t.children: |
|
|
|
|
|
run_instruction(cmd) |
|
|
|
|
|
else: |
|
|
|
|
|
raise SyntaxError('Unknown instruction: %s' % t.data) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def run_turtle(program): |
|
|
|
|
|
parse_tree = parser.parse(program) |
|
|
|
|
|
for inst in parse_tree.children: |
|
|
|
|
|
run_instruction(inst) |
|
|
|
|
|
|
|
|
|
|
|
def main(): |
|
|
|
|
|
while True: |
|
|
|
|
|
code = input('> ') |
|
|
|
|
|
try: |
|
|
|
|
|
run_turtle(code) |
|
|
|
|
|
except Exception as e: |
|
|
|
|
|
print(e) |
|
|
|
|
|
|
|
|
|
|
|
def test(): |
|
|
|
|
|
text = """ |
|
|
|
|
|
c red yellow |
|
|
|
|
|
fill { repeat 36 { |
|
|
|
|
|
f200 l170 |
|
|
|
|
|
}} |
|
|
|
|
|
""" |
|
|
|
|
|
run_turtle(text) |
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__': |
|
|
|
|
|
#test |
|
|
|
|
|
main() |