(use comparse) (define whitespace (in #\space #\tab)) (define nl (is #\newline)) (define end-of-input (none-of item)) (define headline-marks (sequence* ((marks (one-or-more (is #\*))) (_ (one-or-more whitespace))) (result (length marks)))) (define tag-delim (is #\:)) (define tag (preceded-by tag-delim (as-string (repeated item until: (any-of whitespace tag-delim))))) (define headline-text (as-string (repeated item until: (any-of (one-or-more tag) nl end-of-input)))) (define headline (sequence* ((level headline-marks) (text headline-text) (tags (zero-or-more tag))) (let* ((value `(headline (level ,level) (text ,text))) (value (if (null? tags) value (append value `((tags . ,tags)))))) (result value)))) ;; Examples: ;; ;; * Hi this is a simple headline ;; * Another one with a :tag: ;; * Two tags :one:two: ;; * This should not be a tag :haha: as its inside the title ;; * Nor is this a tag as it contains whitespaces :aha : (use test) (define-syntax test-parser (syntax-rules () ((_ parser in out) (test out (parse parser in))))) (test-parser whitespace " " #\space) (test-parser headline "* Hi this is a simple headline" '(headline (level 1) (text "Hi this is a simple headline"))) (test-parser headline "* Another one with a :tag:" '(headline (level 1) (text "Another one with a ") (tags "tag")))