PasteRack.org
Paste # 12032
2019-08-13 19:17:22

Fork as a new paste.

Paste viewed 288 times.


Embed:

Parse nested

  1. #lang racket
  2.  
  3. ; <num> ::= <digit> <digit>*
  4.  
  5. ; <exp> ::= <number>
  6. ;        |  ( <exp> * )
  7.  
  8. (define (whitespace? c)
  9.   (or (eqv? c #\space)
  10.       (eqv? c #\newline)))
  11.  
  12. (define (open-paren? c)
  13.   (eqv? c #\())
  14.  
  15. (define (close-paren? c)
  16.   (eqv? c #\)))
  17.  
  18. (define (digit? c)
  19.   (memv c (string->list "0123456789")))
  20.  
  21. (define (skip-char)
  22.   (read-char))
  23.  
  24. (define (skip-whitespace)
  25.   (define c (peek-char))
  26.   (when (whitespace? c)
  27.     (skip-char)
  28.     (skip-whitespace)))
  29.  
  30. (define (read-digit)
  31.   (expect 'read-digit digit?)
  32.   (read-char))
  33.  
  34. (define (read-digit*)
  35.   (define c (peek-char))
  36.   (if (digit? c)
  37.       (cons (read-digit) (read-digit*))
  38.       '()))
  39.  
  40. (define (parse-number)
  41.   (define d0 (read-digit))
  42.   (define ds (read-digit*))
  43.   (string->number (list->string (cons d0 ds))))
  44.  
  45.  
  46. (define (expect who pred?)
  47.   (define c (peek-char))
  48.   (unless (pred? c)
  49.     (error who (~a "unexpected character: " c))))
  50.  
  51. (define (parse-exp)
  52.   (define c (peek-char))
  53.   (cond
  54.     [(digit? c)      (parse-number)]
  55.     [(open-paren? c) (read-char) ; (
  56.                      (skip-whitespace)
  57.                      (define exps (parse-exp*))
  58.                      (skip-whitespace)
  59.                      (expect 'parse-exp close-paren?)
  60.                      (read-char) ; ]
  61.                      exps]))
  62.  
  63. (define (parse-exp*)
  64.   (define c (peek-char))
  65.   (cond
  66.     [(or (digit? c) (open-paren? c))
  67.      (cons (begin0
  68.                (parse-exp)
  69.                (skip-whitespace))
  70.            (parse-exp*))]
  71.     [else
  72.      '()]))
  73.  
  74. (define (parse input)
  75.   (with-input-from-string input
  76.     (λ ()
  77.       (skip-whitespace)
  78.       (parse-exp))))
  79.  
  80. (parse " 123 ")
  81. (parse " () ")
  82. (parse " ( 1 ) ")
  83. (parse " ( 1 2 ) ")
  84. (parse " ( 1 2 3 ) ")
  85. (parse " ( 1 (11 12 13) 2 3 (41 42) 5 )")
  86.  

=>

123

'()

'(1)

'(1 2)

'(1 2 3)

'(1 (11 12 13) 2 3 (41 42) 5)