Peter Siebel - Practical Common Lisp

Здесь есть возможность читать онлайн «Peter Siebel - Practical Common Lisp» весь текст электронной книги совершенно бесплатно (целиком полную версию без сокращений). В некоторых случаях можно слушать аудио, скачать через торрент в формате fb2 и присутствует краткое содержание. Год выпуска: 2005, ISBN: 2005, Издательство: Apress, Жанр: Программирование, на английском языке. Описание произведения, (предисловие) а так же отзывы посетителей доступны на портале библиотеки ЛибКат.

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 evaluaterestart 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-htmlfor 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-pdetermines 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-htmlis 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 bodyand 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-pand paragraph-element-ptest 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 brand 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-formto 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-tagyou have to call freshlinewhen appropriate and then emit the attributes with emit-attributes. You need to pass the element's body to emit-open-tagso when it's emitting XHTML, it knows whether to finish the tag with />or >.

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Похожие книги на «Practical Common Lisp»

Представляем Вашему вниманию похожие книги на «Practical Common Lisp» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.


Отзывы о книге «Practical Common Lisp»

Обсуждение, отзывы о книге «Practical Common Lisp» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.

x