func read(path string) (*fsm.Adapter, *partition.Partition) { // Read file and construct FSM f, err := os.Open(path) if err != nil { panic(err) } a := fsm.NewAdapter(fsm.DotParser{}) a.Scan(bufio.NewScanner(f)) m := a.FSM() states, inputs, outputs := m.States(), m.Inputs(), m.Outputs() // Construct transition (f) and output (g) functions fs := make([]func(int) int, 0, inputs) gs := make([]func(int) int, 0, inputs) for input := 0; input < inputs; input++ { f, _ := m.TransitionFunction(input) fs = append(fs, f) g, _ := m.OutputFunction(input) gs = append(gs, g) } // Construct the partition p := partition.New(states, outputs, gs...) p.Refine(0, fs...) // Print results var not string if p.Size() != states { not = "not " } fmt.Printf("FSM %s is %sminimal.\n", path, not) return a, p }
func main() { fnopt := flag.String("f", "", "C source code") flag.Parse() fn := *fnopt // Read dot file if fn == "" { fn = "/dev/stdin" } f, err := os.Open(fn) if err != nil { panic(err) } // Construct fsm a := fsm.NewAdapter(fsm.DotParser{}) a.Scan(bufio.NewScanner(f)) m := a.FSM() states, inputs := m.States(), m.Inputs() // Print state, input and output sets in header fmt.Println("// states:", a.States()) fmt.Println("// inputs:", a.Inputs()) fmt.Println("// outputs:", a.Outputs()) // Print program header header for c file fmt.Println(header) // Print switch function for each input for state := 0; state < states; state++ { fmt.Printf("int step_state_%d(int input) {\n\tswitch (input) {", state) for input := 0; input < inputs; input++ { output, target, err := m.Transition(state, input) if err != nil { panic(err) } fmt.Printf("\n\t\tcase %d:\n\t\t\tcurrent_state = %d;\n\t\t\treturn %d;", input, target, output) } fmt.Println(epilogue) } // Print switch for each state fmt.Println("int step(int input) {\n\tswitch (current_state) {") for state := 0; state < states; state++ { fmt.Printf("\t\tcase %d:\n\t\t\treturn step_state_%d(input);\n", state, state) } fmt.Println(epilogue) // Print footer fmt.Println(footer) }