;; Define helper functions
(define (drop-while pred lis)
(if (or (null? lis) (not (pred (car lis))))
lis
(drop-while pred (cdr lis))))
(define (take-while pred lis)
(define (take-while-helper pred lis result)
(if (and (not (null? lis)) (pred (car lis)))
(take-while-helper pred (cdr lis) (cons (car lis) result))
(reverse result)))
(take-while-helper pred lis '()))
(define (char-other? ch)
(not (or (= (char->integer ch) 91)
(= (char->integer ch) 93)
(= (char->integer ch) 40)
(= (char->integer ch) 41)
(= (char->integer ch) 32)
(= (char->integer ch) 10))))
(define (process-other chars)
(and (not (null? chars))
(let* ((token-chars (take-while char-other? chars))
(rest (drop-while char-other? chars)))
(list token-chars rest))))
;; Custom function to check if all elements in a list are characters
(define (all-char? lis)
(if (null? lis)
#t
(and (char? (car lis)) (all-char? (cdr lis)))))
(define (token-list x)
(if (and (pair? x) (all-char? x))
(list->string x)
x))
;; Functions for Dot Count
(define (process-dots chars)
(let* ((dot-chars (take-while (lambda (ch) (char=? ch (integer->char 46))) chars)) ; char 46 is '.'
(num-dots (length dot-chars))
(rest (drop-while (lambda (ch) (char=? ch (integer->char 46))) chars)))
(list num-dots rest)))
;; Function to gather a specified number of items from the list
(define (take n lis)
(if (or (<= n 0) (null? lis))
'()
(cons (car lis) (take (- n 1) (cdr lis)))))
;; Function to drop a specified number of items from the list
(define (drop n lis)
(if (or (<= n 0) (null? lis))
lis
(drop (- n 1) (cdr lis))))
;; Function to gather items based on the number of dots
(define (gather-items tokens num-dots)
(let loop ((remaining num-dots) (items '()) (rest (reverse tokens)))
(if (or (= remaining 0) (null? rest))
(list (reverse items) (reverse rest))
(loop (- remaining 1) (cons (car rest) items) (cdr rest)))))
;; Pretty-print function to print tokens on one line
(define (pretty-print tokens)
(if (null? tokens)
(newline)
(begin
(write (car tokens))
(when (not (null? (cdr tokens))) (display " ")) ; Add a space between tokens
(pretty-print (cdr tokens)))))
;; Define main tokenize function with debugging statements
(define (tokenize input)
(let loop ((chars (string->list input)) (tokens '()) (accumulated-tokens '()))
(cond
((null? chars) (let ((final-tokens (map token-list tokens)))
(pretty-print final-tokens) ; Pretty print the final tokens
final-tokens))
((char=? (car chars) (integer->char 91)) ; Handle opening bracket [
(begin
(display "Tokenizing [\n")
(loop (cdr chars) (cons "[" tokens) (cons "[" accumulated-tokens))))
((char=? (car chars) (integer->char 93)) ; Handle closing bracket ]
(begin
(display "Tokenizing ]\n")
(loop (cdr chars) (cons "]" tokens) (cons "]" accumulated-tokens))))
((char=? (car chars) (integer->char 40)) ; Handle opening parenthesis
(begin
(display "Tokenizing (\n")
(loop (cdr chars) (cons "(" tokens) (cons "(" accumulated-tokens))))
((char=? (car chars) (integer->char 41)) ; Handle closing parenthesis
(begin
(display "Tokenizing )\n")
(loop (cdr chars) (cons ")" tokens) (cons ")" accumulated-tokens))))
((char=? (car chars) (integer->char 32)) ; Skip spaces
(begin
(display "Skipping space\n")
(loop (cdr chars) tokens accumulated-tokens)))
((char=? (car chars) (integer->char 46)) ; Handle dots (.)
(let* ((result (process-dots chars))
(num-dots (car result))
(rest (cadr result))
(gathered-items (gather-items (reverse tokens) num-dots))) ; Gather from right
(begin
(display "Processing dots: ")
(display num-dots)
(display "\nGathered items: ")
(display (car gathered-items))
(display "\nRemaining tokens: ")
(display (cdr gathered-items))
(display "\n")
(loop rest (cons "(" (append (car gathered-items) (cons ")" tokens))) (cdr gathered-items)))))
(else
(let* ((result (process-other chars))
(token (car result))
(rest (cadr result)))
(begin
(display "Tokenizing ")
(display token)
(display "\n")
(loop rest (cons token tokens) (cons token accumulated-tokens))))))))
;; Example usage
(define input "(define) f g (). 1 2")
(tokenize input) ; Display tokens for debugging