cc-haxe/src/lib/turtle/TurtleInstructionParser.hx
2023-07-30 15:55:22 +02:00

111 lines
2.5 KiB
Haxe

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<TurtleInstruction>):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<TurtleInstruction> {
var rtn:Array<TurtleInstruction> = [];
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<String, TurtleInstruction> = [
"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),
];
}