diff --git a/src/lib/turtle/TurtleInstructionParser.hx b/src/lib/turtle/TurtleInstructionParser.hx new file mode 100644 index 0000000..c4b0002 --- /dev/null +++ b/src/lib/turtle/TurtleInstructionParser.hx @@ -0,0 +1,126 @@ +package lib.turtle; + +// Check usage of NativeStringTools +// here https://api.haxe.org/lua/NativeStringTools.html +// and here http://lua-users.org/wiki/StringLibraryTutorial + +import kernel.turtle.Types.TurtleSlot; +import kernel.turtle.Turtle; +import lua.NativeStringTools; + +using tink.CoreApi; + + +/** + Save a set of turtle instructions to a string and execute them. +**/ +class TurtleInstructionParser { + + public function new() { + + } + + public function encode(instructions: Array): String { + var s = ""; + + var times = 0; + var lastInstruction: TurtleInstruction = null; + + for (inst in instructions){ + if (inst == lastInstruction){ + times++; + continue; + } + + if (lastInstruction != null){ + var encoded = encodeInstruction(lastInstruction); + s = s + '${times + 1}$encoded'; + } + + times = 0; + lastInstruction = inst; + } + + var encoded = encodeInstruction(lastInstruction); + s = s + '${times + 1}$encoded'; + + return s; + } + + private function encodeInstruction(inst: TurtleInstruction): String { + for (k => v in cmdMap){ + if (v == inst){ + return k; + } + } + + switch inst { + case Select(slot): + return "m" + encodeSlot(slot); + default: + return ""; + } + + return ""; + } + + private function encodeSlot(slot: TurtleSlot): String { + return String.fromCharCode(slot + 97); + } + + public function parse(instructionsString: String): Array { + var rtn: Array = []; + var mfunc = NativeStringTools.gmatch(instructionsString,"%d+%D+"); + + while(true){ + var found = mfunc(); + + if (found == null) { + break; + } + + var times = Std.parseInt(NativeStringTools.match(found, "%d+")); + var command = NativeStringTools.match(found, "%D+"); + + var cmd = cmdMap.get(command); + if (cmd != null){ + rtn = rtn.concat([for (i in 0...times) cmd]); + } + + switch command.charAt(0) { + case "m": // select + var slot = parseSlot(command.charAt(1)); + rtn = rtn.concat([for (i in 0...times) Select(slot)]); + } + } + + return rtn; + } + + private static function parseSlot(slot: String): TurtleSlot { + var slot = slot.charCodeAt(0) - 97; + + if (slot < 0 || slot > Turtle.MAX_SLOTS) { + // TODO: better error handling + throw new Error("Invalid slot: " + slot); + } + + return slot; + } + + private var cmdMap:Map = [ + "a" => Forward, + "b" => Back, + "c" => TurnLeft, + "d" => TurnRight, + "e" => Up, + "f" => Down, + "g" => Dig(Front), + "h" => Dig(Up), + "i" => Dig(Down), + "j" => Place(Front), + "k" => Place(Up), + "l" => Place(Down), + ]; + +}