X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=scm%2Fparser-ly-from-scheme.scm;h=00368e881fea665152831be7f4dc7938d1647b11;hb=90e4d7057f3857da049dfda3d130017d4719bd6b;hp=3f19641916c51a87030a13a10bfa6df1afce49a4;hpb=48dfdac8c2a8044d3154041bf67a531f302ac4d1;p=lilypond.git diff --git a/scm/parser-ly-from-scheme.scm b/scm/parser-ly-from-scheme.scm index 3f19641916..00368e881f 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,22 +20,60 @@ "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 (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 lily-string filename line closures) + (let* ((clone (ly:parser-clone closures (*location*))) + (result (ly:parse-string-expression clone lily-string + filename line))) + (if (ly:parser-has-error? clone) + (ly:parser-error (_ "error in #{ ... #}") (*location*))) + result)) + (list embedded-lilypond + lily-string filename line + (cons 'list (reverse! closures))))) (read-hash-extend #\{ read-lily-expression)