1 Quick Start🔗

A Parser turns a string into a Value. The constructors given to seq and seq* decide what that Value is, so a grammar can compute the data the program needs while it parses.

Take numbers such as "0", "-7", and "140". A number is an optional minus sign followed by either a lone zero or a non-zero digit and any number of further digits. ZERO and NONZERO-DIGIT use string->number as their constructor, so the digit parsers produce each digit’s value instead of its text:

(require parser-combinator/parse)
 
; Parser
; matches the digit 0, producing its value
(define-parser ZERO
  (seq* string->number (lit "0")))
 
; Parser
; matches a digit 1 through 9, producing its value
(define-parser NONZERO-DIGIT
  (seq* string->number (rx #rx"[1-9]")))
 
; Parser
; matches any digit, producing its value
(define-parser DIGIT
  (alt ZERO NONZERO-DIGIT))

A natural number other than zero starts with a non-zero digit, and foldl adds the digits after it from left to right. A missing sign is '(), and a minus sign negates the number:

; Natural Natural -> Natural
; adds the digit d to the end of n
(define (add-digit d n)
  (+ (* 10 n) d))
 
; Parser
; matches a natural number, producing its value
(define-parser NATURAL
  (alt ZERO
       (seq (lambda (d ds) (foldl add-digit d ds))
            NONZERO-DIGIT
            (star DIGIT))))
 
; Parser
; matches an integer, producing its value
(define-parser NUMBER
  (seq (lambda (sign n) (if (null? sign) n (- n)))
       (opt (lit "-"))
       NATURAL))

Running a parser with parse produces the number:

> (parse NUMBER "0")

0

> (parse NUMBER "-7")

-7

> (parse NUMBER "140")

140

Input that is not in the grammar is an error:

> (parse NUMBER "007")

bad input, had leftover text "07"

The source of parser-combinator/json builds its data the same way, for a larger grammar.