X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=scm%2Fparser-ly-from-scheme.scm;h=dd3e698b9cbddba3271165f5fdddcecf20450630;hb=47db9a3883d726ca53e2133a3b2298f78dd6a32e;hp=1a51a3714006a04e26fbc67b0dc084388ee6736a;hpb=fecc5999e224304e9d54e48bc7a92cdbb123cd35;p=lilypond.git diff --git a/scm/parser-ly-from-scheme.scm b/scm/parser-ly-from-scheme.scm index 1a51a37140..dd3e698b9c 100644 --- a/scm/parser-ly-from-scheme.scm +++ b/scm/parser-ly-from-scheme.scm @@ -1,6 +1,6 @@ ;;;; This file is part of LilyPond, the GNU music typesetter. ;;;; -;;;; Copyright (C) 2004--2011 Nicolas Sceaux +;;;; Copyright (C) 2004--2015 Nicolas Sceaux ;;;; Jan Nieuwenhuizen ;;;; ;;;; LilyPond is free software: you can redistribute it and/or modify @@ -20,24 +20,62 @@ "Read a lilypond music expression enclosed within @code{#@{} and @code{#@}} from @var{port} and return the corresponding Scheme music expression. @samp{$} and @samp{#} introduce immediate and normal Scheme forms." - (let ((lily-string (call-with-output-string - (lambda (out) - (do ((c (read-char port) (read-char port))) - ((and (char=? c #\#) - (char=? (peek-char port) #\})) ;; we stop when #} is encountered - (read-char port)) - ;; a #scheme or $scheme expression - (if (or (char=? c #\#) (char=? c #\$)) - (format out "~a~s" c (read port)) - ;; other characters - (display c out))))))) - `(let* ((clone - (ly:parser-clone parser (procedure-environment (lambda () '())))) - (result (begin - (ly:parser-clear-error clone) - (ly:parse-string-expression clone ,lily-string)))) - (if (ly:parser-has-error? clone) - (ly:parser-error parser (_ "error in #{ ... #}"))) - result))) + (let* ((closures '()) + (filename (port-filename port)) + (line (port-line port)) + (lily-string (call-with-output-string + (lambda (out) + (let ((copycat + (make-soft-port + (vector #f #f #f + (lambda () + (let ((x (read-char port))) + (write-char x out) + x)) #f) + "r"))) + (set-port-filename! copycat filename) + (do ((c (read-char port) (read-char port))) + ((and (char=? c #\#) + (char=? (peek-char port) #\})) + ;; we stop when #} is encountered + (read-char port)) + (write-char c out) + ;; a #scheme or $scheme expression + (if (or (char=? c #\#) (char=? c #\$)) + (let* ((p (ftell out)) + (expr + (begin + (set-port-line! copycat + (port-line port)) + (set-port-column! copycat + (port-column port)) + (if (char=? (peek-char port) #\@) + (read-char copycat)) + (read copycat)))) + ;; kill unused lookahead, it has been + ;; written out already + (drain-input copycat) + ;; only put symbols and non-quote + ;; lists into closures -- constants + ;; don't need lexical environments + ;; for evaluation. + (if (or (symbol? expr) + (and (pair? expr) + (not (eq? 'quote (car expr))))) + (set! closures + (cons `(cons ,p (lambda () ,expr)) + closures))))))))))) + (define (embedded-lilypond parser lily-string filename line + closures location) + (let* ((clone (ly:parser-clone parser closures location)) + (result (ly:parse-string-expression clone lily-string + filename line))) + (if (ly:parser-has-error? clone) + (ly:parser-error parser (_ "error in #{ ... #}"))) + result)) + (list embedded-lilypond + 'parser lily-string filename line + (cons 'list (reverse! closures)) + 'location))) (read-hash-extend #\{ read-lily-expression)