main.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. // ll1lex is a lexer generator based on regular expressions
  2. package main
  3. import "flag"
  4. import "os"
  5. // import "text/template"
  6. import "fmt"
  7. import "src.eruta.nl/beoran/ll1/common"
  8. import "src.eruta.nl/beoran/ll1/flexgen"
  9. import "src.eruta.nl/beoran/ll1/parser"
  10. import "src.eruta.nl/beoran/ll1/grammar"
  11. import "src.eruta.nl/beoran/ll1/ast"
  12. func showUsage() {
  13. fmt.Fprintf(flag.CommandLine.Output(),
  14. "%s: %s [options] input_file.ll1lex\n",
  15. os.Args[0], os.Args[0])
  16. fmt.Fprintf(flag.CommandLine.Output(),
  17. "\n [options] may be one of the following:\n\n")
  18. flag.PrintDefaults()
  19. fmt.Fprintf(flag.CommandLine.Output(), "\n")
  20. }
  21. const helpText = `
  22. ll1flex is a leger generator based on regular expressions.
  23. Usage:
  24. ll1lex [options] input_file.ll1lex
  25. The [options] are:
  26. -p name
  27. Name of the package to generate code for.
  28. -help -h
  29. Shows the help page.
  30. -o file
  31. Name of output file to overwrite.
  32. -v
  33. Be more verbose. Shows the scanned tokens as well.
  34. `
  35. func showHelp() {
  36. fmt.Fprintf(flag.CommandLine.Output(), "\n%s\n", helpText)
  37. }
  38. // LL1Lex contains the options and variables of the ll1lex program.
  39. type Ll1Lex struct {
  40. packageName string
  41. outName string
  42. usedName string
  43. appendName string
  44. help bool
  45. verbose bool
  46. fout *os.File
  47. tokens []common.Token
  48. parser *parser.Parser
  49. grammar *grammar.Grammar
  50. }
  51. func main() {
  52. var err error
  53. flag.Usage = showUsage
  54. ll1lex := Ll1Lex{}
  55. flag.BoolVar(&ll1lex.verbose, "v", false, "Be more verbose. ")
  56. flag.StringVar(&ll1lex.outName, "o", "", "Name of output `file` to overwrite.")
  57. flag.StringVar(&ll1lex.packageName, "p", "lexer", "Name of package `package` to use.")
  58. flag.BoolVar(&ll1lex.help, "h", false, "Shows the help page.")
  59. flag.BoolVar(&ll1lex.help, "help", false, "Shows the help page.")
  60. flag.Parse()
  61. if ll1lex.help {
  62. showUsage()
  63. showHelp()
  64. os.Exit(1)
  65. }
  66. if len(flag.Args()) < 1 {
  67. showUsage()
  68. os.Exit(1)
  69. return
  70. }
  71. ll1lexName := flag.Arg(0)
  72. // Parse lexer description
  73. tokens, err := flexgen.LexFileName(ll1lexName)
  74. if err != nil {
  75. fmt.Fprintf(os.Stderr, "%v\n", err)
  76. }
  77. if ll1lex.verbose {
  78. for _, tok := range tokens {
  79. fmt.Fprintf(os.Stderr, "%s\n", tok)
  80. }
  81. }
  82. ll1lex.parser = flexgen.MakeFlexerParser()
  83. if ll1lex.verbose {
  84. fmt.Fprintf(os.Stderr, "Parsing\n")
  85. }
  86. err = ll1lex.parser.Parse(tokens)
  87. if err != nil {
  88. fmt.Fprintf(os.Stderr, "%s\n", err)
  89. for _, e := range ll1lex.parser.Errors {
  90. fmt.Fprintf(os.Stderr, "error: %v\n", e)
  91. }
  92. os.Exit(2)
  93. }
  94. // Determine output file
  95. ll1lex.usedName = ll1lex.outName
  96. if ll1lex.outName == "" {
  97. ll1lex.fout = os.Stdout
  98. } else {
  99. ll1lex.fout, err = os.Create(ll1lex.outName)
  100. if err != nil {
  101. fmt.Fprintf(os.Stderr, "Could not open output file %s: %s\n", ll1lex.outName, err)
  102. }
  103. defer ll1lex.fout.Close()
  104. }
  105. if ll1lex.verbose {
  106. fmt.Fprintf(os.Stderr, "Dumping\n")
  107. }
  108. i := ll1lex.parser.Index
  109. l := len(tokens)
  110. fmt.Fprintf(ll1lex.fout, "%s\nTokens:%d/%d\n", ast.Dump(ll1lex.parser.Result), i, l)
  111. if i < l {
  112. fmt.Fprintf(os.Stderr, "%s\n", tokens[i])
  113. }
  114. }