|
|
@@ -1,4 +1,5 @@ |
|
|
|
;;; Parser module building on comparse. |
|
|
|
;;; The function PARSE-LINE parses one line of text into symbols, quote-enclosed strings and numbers. |
|
|
|
|
|
|
|
(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) |
|
|
|
(import scheme) |
|
|
@@ -8,50 +9,70 @@ |
|
|
|
(import util) |
|
|
|
(import comparse) |
|
|
|
|
|
|
|
;; The set of all upper and lower case english letters. |
|
|
|
(define +letter-char-set+ |
|
|
|
(string->char-set "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVwXYZ")) |
|
|
|
|
|
|
|
;; The set of all charactes allowed for symbols. |
|
|
|
(define +symbol-char-set+ |
|
|
|
(char-set-union +letter-char-set+ (string->char-set "-0123456789"))) |
|
|
|
|
|
|
|
;; This has been accepted into upstream comparse by Moritz Heidkamp but might not |
|
|
|
;; exist locally. It lifts a function FN into the parser PARSER, creating a parser |
|
|
|
;; that has FN applied to its result. |
|
|
|
(define (lift fn parser) |
|
|
|
(bind parser (compose result fn))) |
|
|
|
|
|
|
|
;; The logical inverse of IS, returning the result if it is not EQV? to X. |
|
|
|
(define (is-not x) |
|
|
|
(satisfies (lambda (y) |
|
|
|
(not (eqv? x y))))) |
|
|
|
|
|
|
|
;; Parse a string of spaces. |
|
|
|
(define parse-whitespace |
|
|
|
(one-or-more (is #\space))) |
|
|
|
|
|
|
|
;; Skip any spaces, the input is unchanged if there are none. |
|
|
|
(define skip-whitespace |
|
|
|
(skip (zero-or-more (is #\space)))) |
|
|
|
|
|
|
|
;; Parse a symbol. |
|
|
|
(define parse-symbol |
|
|
|
(lift (compose string->symbol string-downcase list->string (applied append)) |
|
|
|
(sequence (lift list (in +letter-char-set+)) (zero-or-more (in +symbol-char-set+))))) |
|
|
|
|
|
|
|
;; Parse a number. |
|
|
|
(define parse-number |
|
|
|
(lift (compose string->number list->string) (one-or-more (in char-set:digit)))) |
|
|
|
|
|
|
|
;; Parse a quote-delimited string. |
|
|
|
(define parse-string |
|
|
|
(lift list->string (enclosed-by (is #\") (one-or-more (is-not #\")) (is #\")))) |
|
|
|
|
|
|
|
;; This is identical to FOLLOWED-BY from comparse, except it consumes |
|
|
|
;; the input from the SEPARATOR parser. |
|
|
|
(define (followed-by-consuming parser separator) |
|
|
|
(sequence* ((value parser) (_ separator)) |
|
|
|
(result value))) |
|
|
|
|
|
|
|
;; Parse a list of PARSER separated by SEPARATOR. |
|
|
|
(define (separated-by separator parser) |
|
|
|
(one-or-more (any-of (followed-by-consuming parser separator) parser))) |
|
|
|
|
|
|
|
;; Parse a symbol or a number or a quote-delimited string. |
|
|
|
(define parse-symbol-or-number-or-string |
|
|
|
(any-of parse-number parse-symbol parse-string)) |
|
|
|
|
|
|
|
;; Only successfully parse if PARSER fully parses the input. |
|
|
|
(define (completely-parse parser) |
|
|
|
(followed-by parser end-of-input)) |
|
|
|
|
|
|
|
;; Parse a statement, optionally preceded by whitespace, consisting of |
|
|
|
;; symbols or numbers or quote-delimited strings. |
|
|
|
(define parse-statement |
|
|
|
(all-of skip-whitespace (separated-by parse-whitespace parse-symbol-or-number-or-string))) |
|
|
|
|
|
|
|
;; Parse a line of text into a list of symbols, numbers |
|
|
|
;; and quote-delimited strings. |
|
|
|
(define (parse-line line) |
|
|
|
(parse (completely-parse parse-statement) line))) |