main.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. package main
  2. import (
  3. "flag"
  4. "io/ioutil"
  5. "log"
  6. "os"
  7. "os/exec"
  8. "strings"
  9. )
  10. var outFilename string
  11. var nfadotFile, dfadotFile string
  12. var autorun, standalone, customError bool
  13. var prefix string
  14. var prefixReplacer *strings.Replacer
  15. func init() {
  16. prefixReplacer = strings.NewReplacer()
  17. }
  18. func main() {
  19. flag.StringVar(&prefix, "p", "yy", "name prefix to use in generated code")
  20. flag.StringVar(&outFilename, "o", "", `output file`)
  21. flag.BoolVar(&standalone, "s", false, `standalone code; NN_FUN macro substitution, no Lex() method`)
  22. flag.BoolVar(&customError, "e", false, `custom error func; no Error() method`)
  23. flag.BoolVar(&autorun, "r", false, `run generated program`)
  24. flag.StringVar(&nfadotFile, "nfadot", "", `show NFA graph in DOT format`)
  25. flag.StringVar(&dfadotFile, "dfadot", "", `show DFA graph in DOT format`)
  26. flag.Parse()
  27. if len(prefix) > 0 {
  28. prefixReplacer = strings.NewReplacer("yy", prefix)
  29. }
  30. nfadot = createDotFile(nfadotFile)
  31. dfadot = createDotFile(dfadotFile)
  32. defer func() {
  33. if nfadot != nil {
  34. dieErr(nfadot.Close(), "Close")
  35. }
  36. if dfadot != nil {
  37. dieErr(dfadot.Close(), "Close")
  38. }
  39. }()
  40. infile, outfile := os.Stdin, os.Stdout
  41. var err error
  42. if flag.NArg() > 0 {
  43. dieIf(flag.NArg() > 1, "nex: extraneous arguments after", flag.Arg(0))
  44. dieIf(strings.HasSuffix(flag.Arg(0), ".go"), "nex: input filename ends with .go:", flag.Arg(0))
  45. basename := flag.Arg(0)
  46. n := strings.LastIndex(basename, ".")
  47. if n >= 0 {
  48. basename = basename[:n]
  49. }
  50. infile, err = os.Open(flag.Arg(0))
  51. dieErr(err, "nex")
  52. defer infile.Close()
  53. if !autorun {
  54. if outFilename == "" {
  55. outFilename = basename + ".nn.go"
  56. outfile, err = os.Create(outFilename)
  57. } else {
  58. outfile, err = os.Create(outFilename)
  59. }
  60. dieErr(err, "nex")
  61. defer outfile.Close()
  62. }
  63. }
  64. if autorun {
  65. tmpdir, err := ioutil.TempDir("", "nex")
  66. dieIf(err != nil, "tempdir:", err)
  67. defer func() {
  68. dieErr(os.RemoveAll(tmpdir), "RemoveAll")
  69. }()
  70. outfile, err = os.Create(tmpdir + "/lets.go")
  71. dieErr(err, "nex")
  72. defer outfile.Close()
  73. }
  74. err = process(outfile, infile)
  75. if err != nil {
  76. log.Fatal(err)
  77. }
  78. if autorun {
  79. c := exec.Command("go", "run", outfile.Name())
  80. c.Stdin, c.Stdout, c.Stderr = os.Stdin, os.Stdout, os.Stderr
  81. dieErr(c.Run(), "go run")
  82. }
  83. }