You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

79 lines
3.0KB

  1. ;;; Parser module building on comparse.
  2. ;;; The function PARSE-LINE parses one line of text into symbols, quote-enclosed strings and numbers.
  3. (module parse (lift followed-by-consuming is-not parse-whitespace skip-whitespace parse-symbol parse-number parse-string followed-by-consuming separated-by parse-symbol-or-number-or-string completely-parse parse-statement parse-line)
  4. (import scheme)
  5. (import chicken.base)
  6. (import srfi-13)
  7. (import srfi-14)
  8. (import util)
  9. (import comparse)
  10. ;; The set of all upper and lower case english letters.
  11. (define +letter-char-set+
  12. (string->char-set "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVwXYZ"))
  13. ;; The set of all charactes allowed for symbols.
  14. (define +symbol-char-set+
  15. (char-set-union +letter-char-set+ (string->char-set "-0123456789")))
  16. ;; This has been accepted into upstream comparse by Moritz Heidkamp but might not
  17. ;; exist locally. It lifts a function FN into the parser PARSER, creating a parser
  18. ;; that has FN applied to its result.
  19. (define (lift fn parser)
  20. (bind parser (compose result fn)))
  21. ;; The logical inverse of IS, returning the result if it is not EQV? to X.
  22. (define (is-not x)
  23. (satisfies (lambda (y)
  24. (not (eqv? x y)))))
  25. ;; Parse a string of spaces.
  26. (define parse-whitespace
  27. (one-or-more (is #\space)))
  28. ;; Skip any spaces, the input is unchanged if there are none.
  29. (define skip-whitespace
  30. (skip (zero-or-more (is #\space))))
  31. ;; Parse a symbol.
  32. (define parse-symbol
  33. (lift (compose string->symbol string-downcase list->string (applied append))
  34. (sequence (lift list (in +letter-char-set+)) (zero-or-more (in +symbol-char-set+)))))
  35. ;; Parse a number.
  36. (define parse-number
  37. (lift (compose string->number list->string) (one-or-more (in char-set:digit))))
  38. ;; Parse a quote-delimited string.
  39. (define parse-string
  40. (lift list->string (enclosed-by (is #\") (one-or-more (is-not #\")) (is #\"))))
  41. ;; This is identical to FOLLOWED-BY from comparse, except it consumes
  42. ;; the input from the SEPARATOR parser.
  43. (define (followed-by-consuming parser separator)
  44. (sequence* ((value parser) (_ separator))
  45. (result value)))
  46. ;; Parse a list of PARSER separated by SEPARATOR.
  47. (define (separated-by separator parser)
  48. (one-or-more (any-of (followed-by-consuming parser separator) parser)))
  49. ;; Parse a symbol or a number or a quote-delimited string.
  50. (define parse-symbol-or-number-or-string
  51. (any-of parse-number parse-symbol parse-string))
  52. ;; Only successfully parse if PARSER fully parses the input.
  53. (define (completely-parse parser)
  54. (followed-by parser end-of-input))
  55. ;; Parse a statement, optionally preceded by whitespace, consisting of
  56. ;; symbols or numbers or quote-delimited strings.
  57. (define parse-statement
  58. (all-of skip-whitespace (separated-by parse-whitespace parse-symbol-or-number-or-string)))
  59. ;; Parse a line of text into a list of symbols, numbers
  60. ;; and quote-delimited strings.
  61. (define (parse-line line)
  62. (parse (completely-parse parse-statement) line)))