#| hybrid.scm -- operations on hybrid lists Copyright © 2026 Hernán Ibarra Mejia. This file is part of `raw`. `raw` is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License. `raw` is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with `raw` If not, see . |# ;;; A hybrid list is a list whose elements are either Scheme expressions (to be ;;; evaluated later) or charlists. (import (chicken string)) (define (charlist? obj) (eq? (car obj) 'charlist)) (define (charlist-list charlst) (cdr charlst)) (define (make-empty-charlist) (list 'charlist)) (define (make-charlist1 char) (list 'charlist char)) (define (add-char-to-charlist char charlst) (cons 'charlist (cons char (charlist-list charlst)))) (define (expression? obj) (eq? (car obj) 'expression)) (define (make-expression expr prefix) (list 'expression expr prefix)) (define (expression-content expr) (cadr expr)) (define (expression-prefix expr) (caddr expr)) (define (make-empty-hybrid) (list (make-empty-charlist))) (define (add-char-to-hybrid char hyb) (let ((first (car hyb))) (cond ((expression? first) (cons (make-charlist1 char) hyb)) ((charlist? first) (cons (add-char-to-charlist char first) (cdr hyb))) (else (error-fatal))))) (define (add-expression-to-hybrid expr hyb #!optional #!key prefix?) (cons (make-expression expr (if prefix? (hybrid-last-line hyb) #f)) hyb)) (define (hybrid-last-line hyb) (define (reverse-list-until-newline lst) (let loop ((head '()) (rest lst)) (if (or (null? rest) (char=? (car rest) #\newline)) head (loop (cons (car rest) head) (cdr rest))))) (let ((first (car hyb))) (cond ((expression? first) '()) ((charlist? first) (list->string (reverse-list-until-newline (charlist-list first)))) (else (error-fatal))))) (define (hybrid->tokens hyb) (let loop ((result '()) (remaining hyb)) (if (null? remaining) result (let ((first (car remaining)) (rest (cdr remaining))) (loop (cond ((expression? first) (let ((prefix (expression-prefix first)) (content (expression-content first))) (if prefix (cons #t (cons prefix (cons content result))) (cons #f (cons content result))))) ((charlist? first) (cons (reverse-list->string (charlist-list first)) result)) (else (error-fatal))) rest)))))