####################################################################### # Name: robot.py # Purpose: Simple DSL for defining robot movement. # Author: Igor R. Dejanovic <igor DOT dejanovic AT gmail DOT com> # Copyright: (c) 2011 Igor R. Dejanovic <igor DOT dejanovic AT gmail DOT com> # License: MIT License # # This example is inspired by an example from LISA tool (http://labraj.uni-mb.si/lisa/) # presented during the lecture given by prof. Marjan Mernik (http://lpm.uni-mb.si/mernik/) # at the University of Novi Sad in June, 2011. # # An example of the robot program: # begin # up # up # left # down # right # end ####################################################################### from __future__ import print_function from arpeggio import * from arpeggio.export import PMDOTExporter, PTDOTExporter # Grammar rules def program(): return Kwd('begin'), ZeroOrMore(command), Kwd('end'), EOF def command(): return [up, down, left, right] def up(): return 'up' def down(): return 'down' def left(): return 'left' def right(): return 'right' # Semantic actions class Up(SemanticAction): def first_pass(self, parser, node, children): if parser.debug: print("Going up") return (0, 1) class Down(SemanticAction): def first_pass(self, parser, node, children): if parser.debug: print("Going down") return (0, -1) class Left(SemanticAction): def first_pass(self, parser, node, children): if parser.debug: print("Going left") return (-1, 0) class Right(SemanticAction): def first_pass(self, parser, node, children): if parser.debug: print("Going right") return (1, 0) class Command(SemanticAction): def first_pass(self, parser, node, children): if parser.debug: print("Command") return children[0] class Program(SemanticAction): def first_pass(self, parser, node, children): if parser.debug: print("Evaluating position") position = [0, 0] for move in children: position[0] += move[0] position[1] += move[1] return position # Connecting rules with semantic actions program.sem = Program() command.sem = Command() up.sem = Up() down.sem = Down() left.sem = Left() right.sem = Right() def main(debug=False): # Program code input_program = ''' begin up up left down right end ''' # First we will make a parser - an instance of the robot parser model. # Parser model is given in the form of python constructs therefore we # are using ParserPython class. parser = ParserPython(program, debug=debug) if debug: # Then we export it to a dot file in order to visualize it. # This step is optional but it is handy for debugging purposes. # We can make a png out of it using dot (part of graphviz) like this # dot -O -Tpng robot_parser_model.dot PMDOTExporter().exportFile(parser.parser_model, "robot_parser_model.dot") # We create a parse tree out of textual input parse_tree = parser.parse(input_program) if debug: # Then we export it to a dot file in order to visualize it. # dot -O -Tpng robot_parse_tree.dot PTDOTExporter().exportFile(parse_tree, "robot_parse_tree.dot") # getASG will start semantic analysis. # In this case semantic analysis will evaluate expression and # returned value will be the final position of the robot. result = parser.getASG() if debug: print("position = ", result) if __name__ == "__main__": main(debug=True)