dev-validator
Matthew Butterick 11 years ago
parent 310cba9903
commit 89438bbcaf

@ -1,18 +1,18 @@
#lang scribble/manual #lang scribble/manual
@(require scribble/eval (for-label racket "../main.rkt")) @(require scribble/eval (for-label racket "../main.rkt" xml))
@(define my-eval (make-base-eval)) @(define my-eval (make-base-eval))
@(my-eval `(require tagged-xexpr)) @(my-eval `(require tagged-xexpr xml))
@title{tagged-xexpr} @title{tagged-xexpr}
@author[(author+email "Matthew Butterick" "mb@mbtype.com")] @author[(author+email "Matthew Butterick" "mb@mbtype.com")]
Convenience functions for working with X-expressions in Racket. Convenience functions for working with tagged X-expressions.
@section{Installation & updates} @section{Installation}
At the command line: At the command line:
@verbatim{raco pkg install tagged-xexpr} @verbatim{raco pkg install tagged-xexpr}
@ -20,12 +20,54 @@ At the command line:
After that, you can update the package from the command line: After that, you can update the package from the command line:
@verbatim{raco pkg update tagged-xexpr} @verbatim{raco pkg update tagged-xexpr}
@section{Whats a tagged X-expression?}
It's an X-expression with the following grammar:
@racketgrammar[
#:literals (cons list valid-char?)
tagged-xexpr (list symbol (list (list symbol string) ...) xexpr ...)
(cons symbol (list xexpr ...))
]
A tagged X-expression has a symbol in the first position — the @italic{tag} — followed by a series of other X-expressions. Optionally, a tagged X-expression can have a list of @italic{attributes} in the second position, which are pairs of symbols and strings.
@examples[#:eval my-eval
(tagged-xexpr? '(tag "Brennan" "Dale"))
(tagged-xexpr? '(tag "Brennan" (tag2 "Richard") "Dale"))
(tagged-xexpr? '(tag [[key "value"][key2 "value"]] "Brennan" "Dale"))
(tagged-xexpr? '(tag symbols are fine))
(tagged-xexpr? '("No" "tag" "in front"))
(tagged-xexpr? '(tag [[bad attr-value]] "string"))
(tagged-xexpr? '(tag [key "value"] "Brennan"))
]
Be careful with the last one. Because the keyvalue pair is not enclosed in a @racket[list], it's interpreted as a nested @racket[_tagged-xexpr] within the first, as you may not find out until you try to read its attributes:
@margin-note{There's no way of eliminating this ambiguity, short of always requiring an attribute list — even empty — in your tagged X-expression. See also @racket[xexpr-drop-empty-attributes].}
@examples[#:eval my-eval
(tagged-xexpr-attr '(tag [key "value"] "Brennan"))
]
Tagged X-expressions are most commonly seen in XML & HTML documents. Though the notation is different in Racket, the data structure is identical:
@examples[#:eval my-eval
(xexpr->string '(p [[foo "bar"]] "Brennan" (em "Richard") "Dale"))
(string->xexpr "<p foo=\"bar\">Brennan<em>Richard</em>Dale</p>")
]
After converting to and from HTML, you get back your original X-expression. Well, not quite. The brackets turned into parentheses — no big deal, since they mean the same thing in Racket. Also true that @racket[string->xexpr] added an empty attribute list after @racket[em]. This is standard procedure, and also benign.
@section{Interface} @section{Interface}
@defmodule[tagged-xexpr] @defmodule[tagged-xexpr]
Hello tagged-xexpr. @defproc[
(tagged-xexpr?
[v any/c])
boolean?]
Simple predicate for functions that operate on @racket[tagged-xexpr]s.
@section{License & source code} @section{License & source code}

@ -30,7 +30,6 @@
(check-false (tagged-xexpr? '(p "foo" "bar" ((key "value"))))) ; malformed (check-false (tagged-xexpr? '(p "foo" "bar" ((key "value"))))) ; malformed
(check-false (tagged-xexpr? '("p" "foo" "bar"))) ; no name (check-false (tagged-xexpr? '("p" "foo" "bar"))) ; no name
(check-equal? (make-xexpr-attr 'foo "bar") '((foo "bar"))) (check-equal? (make-xexpr-attr 'foo "bar") '((foo "bar")))
(check-equal? (make-xexpr-attr "foo" 'bar) '((foo "bar"))) (check-equal? (make-xexpr-attr "foo" 'bar) '((foo "bar")))
(check-equal? (make-xexpr-attr "foo" "bar" "goo" "gar") '((foo "bar")(goo "gar"))) (check-equal? (make-xexpr-attr "foo" "bar" "goo" "gar") '((foo "bar")(goo "gar")))

Loading…
Cancel
Save