Peter Siebel - Practical Common Lisp
Здесь есть возможность читать онлайн «Peter Siebel - Practical Common Lisp» весь текст электронной книги совершенно бесплатно (целиком полную версию без сокращений). В некоторых случаях можно слушать аудио, скачать через торрент в формате fb2 и присутствует краткое содержание. Год выпуска: 2005, ISBN: 2005, Издательство: Apress, Жанр: Программирование, на английском языке. Описание произведения, (предисловие) а так же отзывы посетителей доступны на портале библиотеки ЛибКат.
- Название:Practical Common Lisp
- Автор:
- Издательство:Apress
- Жанр:
- Год:2005
- ISBN:1-59059-239-5
- Рейтинг книги:4 / 5. Голосов: 1
-
Избранное:Добавить в избранное
- Отзывы:
-
Ваша оценка:
- 80
- 1
- 2
- 3
- 4
- 5
Practical Common Lisp: краткое содержание, описание и аннотация
Предлагаем к чтению аннотацию, описание, краткое содержание или предисловие (зависит от того, что написал сам автор книги «Practical Common Lisp»). Если вы не нашли необходимую информацию о книге — напишите в комментариях, мы постараемся отыскать её.
Practical Common Lisp — читать онлайн бесплатно полную книгу (весь текст) целиком
Ниже представлен текст книги, разбитый по страницам. Система сохранения места последней прочитанной страницы, позволяет с удобством читать онлайн бесплатно книгу «Practical Common Lisp», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.
Интервал:
Закладка:
(defun evaluate (&optional condition)
(declare (ignore condition))
(invoke-restart 'evaluate))
(defun eval-dynamic-variables (&optional condition)
(when (and (symbolp (form condition)) (boundp (form condition)))
(evaluate)))
(defun eval-code (&optional condition)
(when (consp (form condition))
(evaluate)))
Now you can use HANDLER-BIND
to set up a handler to automatically invoke the evaluate
restart for you.
HTML> (handler-bind ((value-in-interpreter #'evaluate)) (emit-html '(:p *x*)))
10
T
Finally, you can define a macro to provide a nicer syntax for binding handlers for the two kinds of errors.
(defmacro with-dynamic-evaluation ((&key values code) &body body)
`(handler-bind (
,@(if values `((value-in-interpreter #'evaluate)))
,@(if code `((code-in-interpreter #'evaluate))))
,@body))
With this macro defined, you can write this:
HTML> (with-dynamic-evaluation (:values t) (emit-html '(:p *x*)))
10
T
The Basic Evaluation Rule
Now to connect the FOO language to the processor interface, all you need is a function that takes an object and processes it, invoking the appropriate processor functions to generate HTML. For instance, when given a simple form like this:
(:p "Foo")
this function might execute this sequence of calls on the processor:
(freshline processor)
(raw-string processor "
(raw-string processor ">" nil)
(raw-string processor "Foo" nil)
(raw-string processor "
" nil)
(freshline processor)
For now you can define a simple function that just checks whether a form is, in fact, a legal FOO form and, if it is, hands it off to the function process-sexp-html
for processing. In the next chapter, you'll add some bells and whistles to this function to allow it to handle macros and special operators. But for now it looks like this:
(defun process (processor form)
(if (sexp-html-p form)
(process-sexp-html processor form)
(error "Malformed FOO form: ~s" form)))
The function sexp-html-p
determines whether the given object is a legal FOO expression, either a self-evaluating form or a properly formatted cons.
(defun sexp-html-p (form)
(or (self-evaluating-p form) (cons-form-p form)))
Self-evaluating forms are easily handled: just convert to a string with PRINC-TO-STRING
and escape the characters in the variable *escapes*
, which, as you'll recall, is initially bound to the value of *element-escapes*
. Cons forms you pass off to process-cons-sexp-html
.
(defun process-sexp-html (processor form)
(if (self-evaluating-p form)
(raw-string processor (escape (princ-to-string form) *escapes*) t)
(process-cons-sexp-html processor form)))
The function process-cons-sexp-html
is then responsible for emitting the opening tag, any attributes, the body, and the closing tag. The main complication here is that to generate pretty HTML, you need to emit fresh lines and adjust the indentation according to the type of the element being emitted. You can categorize all the elements defined in HTML into one of three categories: block, paragraph, and inline. Block elements—such as body
and ul
—are emitted with fresh lines before and after both their opening and closing tags and with their contents indented one level. Paragraph elements—such as p
, li
, and blockquote
—are emitted with a fresh line before the opening tag and after the closing tag. Inline elements are simply emitted in line. The following three parameters list the elements of each type:
(defparameter *block-elements*
'(:body :colgroup :dl :fieldset :form :head :html :map :noscript :object
:ol :optgroup :pre :script :select :style :table :tbody :tfoot :thead
:tr :ul))
(defparameter *paragraph-elements*
'(:area :base :blockquote :br :button :caption :col :dd :div :dt :h1
:h2 :h3 :h4 :h5 :h6 :hr :input :li :link :meta :option :p :param
:td :textarea :th :title))
(defparameter *inline-elements*
'(:a :abbr :acronym :address :b :bdo :big :cite :code :del :dfn :em
:i :img :ins :kbd :label :legend :q :samp :small :span :strong :sub
:sup :tt :var))
The functions block-element-p
and paragraph-element-p
test whether a given tag is a member of the corresponding list. [316] You don't need a predicate for *inline-elements* since you only ever test for block and paragraph elements. I include the parameter here for completeness.
(defun block-element-p (tag) (find tag *block-elements*))
(defun paragraph-element-p (tag) (find tag *paragraph-elements*))
Two other categorizations with their own predicates are the elements that are always empty, such as br
and hr
, and the three elements, pre
, style
, and script
, in which whitespace is supposed to be preserved. The former are handled specially when generating regular HTML (in other words, not XHTML) since they're not supposed to have a closing tag. And when emitting the three tags in which whitespace is preserved, you can temporarily turn off indentation so the pretty printer doesn't add any spaces that aren't part of the element's actual contents.
(defparameter *empty-elements*
'(:area :base :br :col :hr :img :input :link :meta :param))
(defparameter *preserve-whitespace-elements* '(:pre :script :style))
(defun empty-element-p (tag) (find tag *empty-elements*))
(defun preserve-whitespace-p (tag) (find tag *preserve-whitespace-elements*))
The last piece of information you need when generating HTML is whether you're generating XHTML since that affects how you emit empty elements.
(defparameter *xhtml* nil)
With all that information, you're ready to process a cons FOO form. You use parse-cons-form
to parse the list into three parts, the tag symbol, a possibly empty plist of attribute key/value pairs, and a possibly empty list of body forms. You then emit the opening tag, the body, and the closing tag with the helper functions emit-open-tag
, emit-element-body
, and emit-close-tag
.
(defun process-cons-sexp-html (processor form)
(when (string= *escapes* *attribute-escapes*)
(error "Can't use cons forms in attributes: ~a" form))
(multiple-value-bind (tag attributes body) (parse-cons-form form)
(emit-open-tag processor tag body attributes)
(emit-element-body processor tag body)
(emit-close-tag processor tag body)))
In emit-open-tag
you have to call freshline
when appropriate and then emit the attributes with emit-attributes
. You need to pass the element's body to emit-open-tag
so when it's emitting XHTML, it knows whether to finish the tag with />
or >
.
Интервал:
Закладка:
Похожие книги на «Practical Common Lisp»
Представляем Вашему вниманию похожие книги на «Practical Common Lisp» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.
Обсуждение, отзывы о книге «Practical Common Lisp» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.