func main() { app := cli.NewApp() app.Action = func(ctx *cli.Context) { prog := ctx.GlobalString("prog") if prog == "" { log.Fatal( error_.New("--prog (or -p) required!"), ) } file, err := os.Open(prog) if err != nil { log.Fatal(err) } jsonDec := json.NewDecoder(file) var machineDesc machine.MachineDesc err = jsonDec.Decode(&machineDesc) if err != nil { log.Fatal(err) } machine, err := machine.NewMachine(&machineDesc) if err != nil { log.Fatal(err) } machine.Run() } app.Flags = []cli.Flag{ cli.StringFlag{ "prog,p", "", "Path to the turing machine \"program\" to run.", }, } app.Name = "turing-machine" app.Usage = "Turing machinez tho." app.Version = "0.0.1" err := app.Run(os.Args) if err != nil { log.Fatal(err) } }
func NewMachine(machineDesc *MachineDesc) (*Machine, error) { alphabet := make(map[Sym]bool) for i := range machineDesc.Alphabet { alphabet[machineDesc.Alphabet[i]] = true } states := make(map[State]bool) for i := range machineDesc.States { states[machineDesc.States[i]] = true } states[StateValHalt] = true for i := range machineDesc.InputSyms { if !alphabet[machineDesc.InputSyms[i]] { return nil, error_.New( fmt.Sprintf("<machine> Input symbol \"%s\" isn't in the alphabet!", machineDesc.InputSyms[i]), ) } } machine := Machine{ conf: &Conf{ currState: machineDesc.InitState, currTapePos: uint(0), }, tape: NewTape(machineDesc.InputSyms), transMap: make(map[MachineTransMapKey]MachineTransMapVal), } for i := range machineDesc.TransMap { if !states[machineDesc.TransMap[i].Map.State] { return nil, error_.New( fmt.Sprintf("<machine> Transition map output state \"%s\" isn't in the set of finite states!", machineDesc.TransMap[i].Map.State), ) } if !alphabet[machineDesc.TransMap[i].Map.Sym] { return nil, error_.New( fmt.Sprintf("<machine> Transition map output symbol \"%s\" isn't in the alphabet!", machineDesc.TransMap[i].Map.Sym), ) } if !states[machineDesc.TransMap[i].State] { return nil, error_.New( fmt.Sprintf("<machine> Transition map input state \"%s\" isn't in the set of finite states!", machineDesc.TransMap[i].State), ) } if !alphabet[machineDesc.TransMap[i].Sym] { return nil, error_.New( fmt.Sprintf("<machine> Transition map input symbol \"%s\" isn't in the alphabet!", machineDesc.TransMap[i].Sym), ) } switch machineDesc.TransMap[i].Map.Dir { case DirMovLeft, DirMovRight, DirStay: break default: return nil, error_.New( fmt.Sprintf("<machine> \"%s\" isn't a valid direction!", machineDesc.TransMap[i].Map.Dir), ) } machine.transMap[MachineTransMapKey{ state: machineDesc.TransMap[i].State, sym: machineDesc.TransMap[i].Sym, }] = MachineTransMapVal{ dir: machineDesc.TransMap[i].Map.Dir, state: machineDesc.TransMap[i].Map.State, sym: machineDesc.TransMap[i].Map.Sym, } } return &machine, nil }