mirror of https://github.com/lark-parser/lark.git
86 lines
1.9 KiB
Python
86 lines
1.9 KiB
Python
# This example implements a LOGO-like toy language for Python's turtle, with interpreter.
|
|
|
|
try:
|
|
input = raw_input # For Python2 compatibility
|
|
except NameError:
|
|
pass
|
|
|
|
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()
|