regexp.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. package glispext
  2. import (
  3. "errors"
  4. "fmt"
  5. "regexp"
  6. glisp "github.com/zhemao/glisp/interpreter"
  7. )
  8. type SexpRegexp regexp.Regexp
  9. func (re SexpRegexp) SexpString() string {
  10. r := regexp.Regexp(re)
  11. return fmt.Sprintf(`(regexp-compile "%v")`, r.String())
  12. }
  13. func regexpFindIndex(
  14. needle regexp.Regexp, haystack string) (glisp.Sexp, error) {
  15. loc := needle.FindStringIndex(haystack)
  16. arr := make([]glisp.Sexp, len(loc))
  17. for i := range arr {
  18. arr[i] = glisp.Sexp(glisp.SexpInt(loc[i]))
  19. }
  20. return glisp.SexpArray(arr), nil
  21. }
  22. func RegexpFind(env *glisp.Glisp, name string,
  23. args []glisp.Sexp) (glisp.Sexp, error) {
  24. if len(args) != 2 {
  25. return glisp.SexpNull, glisp.WrongNargs
  26. }
  27. var haystack string
  28. switch t := args[1].(type) {
  29. case glisp.SexpStr:
  30. haystack = string(t)
  31. default:
  32. return glisp.SexpNull,
  33. errors.New(fmt.Sprintf("2nd argument of %v should be a string", name))
  34. }
  35. var needle regexp.Regexp
  36. switch t := args[0].(type) {
  37. case SexpRegexp:
  38. needle = regexp.Regexp(t)
  39. default:
  40. return glisp.SexpNull,
  41. errors.New(fmt.Sprintf("1st argument of %v should be a compiled regular expression", name))
  42. }
  43. switch name {
  44. case "regexp-find":
  45. str := needle.FindString(haystack)
  46. return glisp.SexpStr(str), nil
  47. case "regexp-find-index":
  48. return regexpFindIndex(needle, haystack)
  49. case "regexp-match":
  50. matches := needle.MatchString(haystack)
  51. return glisp.SexpBool(matches), nil
  52. }
  53. return glisp.SexpNull, errors.New("unknown function")
  54. }
  55. func RegexpCompile(env *glisp.Glisp, name string,
  56. args []glisp.Sexp) (glisp.Sexp, error) {
  57. if len(args) < 1 {
  58. return glisp.SexpNull, glisp.WrongNargs
  59. }
  60. var re string
  61. switch t := args[0].(type) {
  62. case glisp.SexpStr:
  63. re = string(t)
  64. default:
  65. return glisp.SexpNull,
  66. errors.New("argument of regexp-compile should be a string")
  67. }
  68. r, err := regexp.Compile(re)
  69. if err != nil {
  70. return glisp.SexpNull, errors.New(
  71. fmt.Sprintf("error during regexp-compile: '%v'", err))
  72. }
  73. return glisp.Sexp(SexpRegexp(*r)), nil
  74. }
  75. func ImportRegex(env *glisp.Glisp) {
  76. env.AddFunction("regexp-compile", RegexpCompile)
  77. env.AddFunction("regexp-find-index", RegexpFind)
  78. env.AddFunction("regexp-find", RegexpFind)
  79. env.AddFunction("regexp-match", RegexpFind)
  80. }