func format(args []string) { flags := flag.NewFlagSet("", flag.ExitOnError) write := flags.Bool("w", false, "write to file (instead of stdout)") if len(args) == 0 { log.SetPrefix("") log.Fatal("Usage: pg fmt [flags] <file>\nFlags:\n\t-w write to file (instead of stdout)") } in := args[len(args)-1] flags.Parse(args[:len(args)-1]) f, err := os.Open(in) if err != nil { log.Fatalf("cannot open file: %v", err) } defer f.Close() src, err := ioutil.ReadAll(f) if err != nil { log.Fatalf("cannot read file: %v", err) } g, err := parser.Parse(src, in) if err != nil { log.Fatalf(err.Error()) } if *write { f.Close() var buf bytes.Buffer if err := printer.Fprint(&buf, g); err != nil { log.Fatalf("cannot print grammar: %v", err) } if err = ioutil.WriteFile(in, buf.Bytes(), 0644); err != nil { log.Fatalf("cannot write grammar: %v", err) } return } if err := printer.Fprint(os.Stdout, g); err != nil { log.Fatalf("cannot print grammar: %v", err) } }
func TestFprint(t *testing.T) { const expected = `Expr → Term "+" Expr | Term "-" Expr | Term | ε . Term → Factor "*" Term | Factor "/" Term | Factor . Factor → "(" Expr ")" | Number . Number → Digit | Digit Number . Digit → "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" .` g := ast.Grammar([]*ast.Production{ { Name: &ast.Name{Name: "Expr"}, Expr: ast.Alternative([]ast.Expression{ ast.Sequence([]ast.Expression{ &ast.Name{Name: "Term"}, &ast.Terminal{Terminal: "+"}, &ast.Name{Name: "Expr"}, }), ast.Sequence([]ast.Expression{ &ast.Name{Name: "Term"}, &ast.Terminal{Terminal: "-"}, &ast.Name{Name: "Expr"}, }), &ast.Name{Name: "Term"}, &ast.Epsilon{Epsilon: "e"}, }), }, { Name: &ast.Name{Name: "Term"}, Expr: ast.Alternative([]ast.Expression{ ast.Sequence([]ast.Expression{ &ast.Name{Name: "Factor"}, &ast.Terminal{Terminal: "*"}, &ast.Name{Name: "Term"}, }), ast.Sequence([]ast.Expression{ &ast.Name{Name: "Factor"}, &ast.Terminal{Terminal: "/"}, &ast.Name{Name: "Term"}, }), &ast.Name{Name: "Factor"}, }), }, { Name: &ast.Name{Name: "Factor"}, Expr: ast.Alternative([]ast.Expression{ ast.Sequence([]ast.Expression{ &ast.Terminal{Terminal: "("}, &ast.Name{Name: "Expr"}, &ast.Terminal{Terminal: ")"}, }), &ast.Name{Name: "Number"}, }), }, { Name: &ast.Name{Name: "Number"}, Expr: ast.Alternative([]ast.Expression{ &ast.Name{Name: "Digit"}, ast.Sequence([]ast.Expression{ &ast.Name{Name: "Digit"}, &ast.Name{Name: "Number"}, }), }), }, { Name: &ast.Name{Name: "Digit"}, Expr: ast.Alternative([]ast.Expression{ &ast.Terminal{Terminal: "0"}, &ast.Terminal{Terminal: "1"}, &ast.Terminal{Terminal: "2"}, &ast.Terminal{Terminal: "3"}, &ast.Terminal{Terminal: "4"}, &ast.Terminal{Terminal: "5"}, &ast.Terminal{Terminal: "6"}, &ast.Terminal{Terminal: "7"}, &ast.Terminal{Terminal: "8"}, &ast.Terminal{Terminal: "9"}, }), }, }) var buf bytes.Buffer if err := printer.Fprint(&buf, g); err != nil { t.Errorf("error: %v", err) } if actual := buf.String(); actual != expected { t.Errorf("got\n'%s'\nwant\n'%s'", actual, expected) } }