parser.scm 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. #lang racket
  2. ;; this code implements a parser using racket specific functions
  3. ;;
  4. ;; in future it needs to be reimplemented in plain scheme
  5. (require racket/match)
  6. (provide parse-file
  7. sid sid? sid-id sid-metadata set-sid-id! set-sid-metadata!
  8. special special? special-id special-metadata set-special-id! set-special-metadata!
  9. syx->datum)
  10. (define (parse-file filename)
  11. (call-with-input-file filename
  12. (lambda (in)
  13. (port-count-lines! in)
  14. (let loop ()
  15. (let ((object (read-syntax filename in)))
  16. (if (eof-object? object)
  17. '()
  18. (cons (process-syntax-object object) (loop))))))))
  19. (struct sid ((id #:mutable) (metadata #:mutable)) #:transparent)
  20. (struct special ((id #:mutable) (metadata #:mutable)) #:transparent)
  21. (define (syntax-metadata stx)
  22. (list (cons 'source (syntax-source stx))
  23. (cons 'line (syntax-line stx))
  24. (cons 'column (syntax-column stx))))
  25. (define (process-syntax-object stx)
  26. (let ((e (if (syntax? stx) (syntax-e stx) stx)))
  27. (cond ((or (number? e) (boolean? e) (string? e)) e)
  28. ((symbol? e) (sid e (syntax-metadata stx)))
  29. ((pair? e) (cons (process-syntax-object (car e))
  30. (process-syntax-object (cdr e))))
  31. ((null? e) '())
  32. (else (error "unknown syntax object" stx)))))
  33. ;; > (parse-file "t1.scm")
  34. ;; (list
  35. ;; (list
  36. ;; (sid 'define '((source . "t1.scm") (line . 1) (column . 1)))
  37. ;; (sid 'main '((source . "t1.scm") (line . 1) (column . 8)))
  38. ;; (list (sid 'print '((source . "t1.scm") (line . 1) (column . 14))) "hello world!")))
  39. (define (syx->datum e)
  40. (cond ((or (number? e) (boolean? e) (string? e)) e)
  41. ((sid? e) (sid-id e))
  42. ((special? e) (special-id e))
  43. ((list? e) (map syx->datum e))
  44. (else (error "syx->datum" e))))