repl.go 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. package repl
  2. import (
  3. "bufio"
  4. "fmt"
  5. "github/runnignwater/monkey/evaluator"
  6. "github/runnignwater/monkey/lexer"
  7. "github/runnignwater/monkey/parser"
  8. "io"
  9. "log"
  10. )
  11. /**
  12. * @Author: simon
  13. * @Author: ynwdlxm@163.com
  14. * @Date: 2022/10/2 下午5:41
  15. * @Desc: REPL that tokenizes Monkey source code and prints the tokens
  16. */
  17. const PROMPT = ">>> "
  18. func Start(in io.Reader, out io.Writer) {
  19. scanner := bufio.NewScanner(in)
  20. for {
  21. fmt.Printf(PROMPT)
  22. scan := scanner.Scan()
  23. if !scan {
  24. return
  25. }
  26. line := scanner.Text()
  27. l := lexer.New(line)
  28. p := parser.New(l)
  29. program := p.ParseProgram()
  30. if len(p.Errors()) != 0 {
  31. printParserErrors(out, p.Errors())
  32. continue
  33. }
  34. evaluated := evaluator.Eval(program)
  35. if evaluated != nil {
  36. if _, err := io.WriteString(out, evaluated.Inspect()); err != nil {
  37. panic(err)
  38. }
  39. if _, err := io.WriteString(out, "\n"); err != nil {
  40. panic(err)
  41. }
  42. }
  43. }
  44. }
  45. func printParserErrors(out io.Writer, errors []string) {
  46. if _, err := io.WriteString(out, "Woops! we ran into some monkey business here!\n"); err != nil {
  47. log.Fatal(err)
  48. }
  49. if _, err := io.WriteString(out, " parser errors:\n"); err != nil {
  50. log.Fatal(err)
  51. }
  52. for _, msg := range errors {
  53. _, err := io.WriteString(out, "\t"+msg+"\n")
  54. if err != nil {
  55. return
  56. }
  57. }
  58. }