i-exp.rkt
#lang racket/unit

;; Implements I-Expressions from SRFI-49 and the extensions for
;; Sweet Expressions

;; An indented line is a parameter of its parent, later terms on a line are parameters of the first term,
;; and lists of lists are prefixed with the term "group".

;; A line with exactly one datum, and no child lines, is simply that item; otherwise that line and its
;; child lines are themselves a new list. Indentation is disabled inside the grouping pairs (), [], and {},
;; whether they are prefixed or not. Lines with only leading whitespace and a ;-comment are completely ignored -
;; even their indentation is irrelevant. Empty lines, possibly with tabs and spaces, are ignored during reading
;; of the initial line of an expression; otherwise they end an expression.

;; A blank line always terminates a datum, so once you've entered a complete expression, "Enter Enter" will always end it.
;; The "blank lines at the beginning are ignored" rule eliminates a usability problem with the original I-expression spec,
;; in which two sequential blank lines surprisingly return (). (The sample implementation did end expressions on a blank line
;; - the problem was that the spec didn't capture this.) A function call with 0 parameters must be surrounded or
;; immediately followed by a pair of parentheses: (pi) or pi().

;; Generally it's best to start each new expression on the left edge; if you choose not do to that, include a blank line
;; between each new expression.

(require "read-sig.rkt"
         "util.rkt")

(import read^)
(export (rename read^
                [iexp-read read]
                [iexp-read-syntax read-syntax]))

;; read-syntax for I-Expressions
(define (iexp-read-syntax [source-name #f]
                          [port (current-input-port)])
  (when (not source-name)
    (set! source-name (object-name port)))
  (parameterize ([current-source-name source-name]
                 [current-input-port port])
    (read-syntax-helper 0)))

;; indent - indentation level as an e-n-i?
(define (read-syntax-helper indent)
  (define-values (line col pos) (port-next-location))
  (define c (peek-char))
  (cond [(char-whitespace? c)
         (read-char)
         (read-syntax-helper (add1 indent))]
        [(comment-char? c) (skip-line)]
        [else (read-item)]))