Recently I decide to translate Hoffman & Kunze into Chinese. And I also want to put it on my homepage. Then I write down these programs to generate html, mathml, svg, and so on. Here is an example I pick up from the source code of the translation.
These look useful.
Are these to turn mathematical expressions into stand-lone images that
are patched into a document by other means,
or are they part of a larger document compiler?
I think I have to explain my ideas in detail. There is no magic.
In fact, mathematical expressions are rendered by the browser (Firefox) through MathML. MathML is a markup language based on XML.
There is a hierarchical structure in my mind. First, I define a represention for XML, which is just kind of XML in S-exp (SXML).
<xml> ::= <string> | (<symbol> (<attr>*) <xml>*) <attr> ::= (<symbol> <string>)
In xml.rkt, I provide a procedure Xml for transformation. For example,
> (Xml '(foo ((bar "baz")) "qux")) <foo bar="baz">qux</foo>
In html.rkt, I provide lots of procedures to create HTML (in SXML). For instance,
> (Xml (Prelude (H1 "foo") (P "foo " (B "bar") " baz"))) <html><head><meta charset="utf-8"/><title>index</title></head><body><h1>foo</h1><p>foo <b>bar</b> baz</p></body></html>
As you may expect, mathml.rkt provide tons of procedures to create MathML (in SXML) and to build abstractions for creating MathML. For example, we have procedure make-op which transforms an infix operator into a procedure by which you may write MathML in the style of Scheme.
(define ((make-op op n u) . x*) (cond ((null? x*) (n)) ((null? (cdr x*)) (u (car x*))) (else (let iter ((x (car x*)) (x* (cdr x*)) (r '())) (if (null? x*) (apply Mrow (reverse (cons x r))) (iter (car x*) (cdr x*) (cons op (cons x r))))))))
(define &cm (make-op $cm (lambda () $) (lambda (x) x)))
> (Xml (&cm)) <mrow/> > (Xml (&cm $1)) <mn>1</mn> > (Xml (&cm $1 $2)) <mrow><mn>1</mn><mo>,</mo><mn>2</mn></mrow> > (Xml (&cm $1 $2 $3)) <mrow><mn>1</mn><mo>,</mo><mn>2</mn><mo>,</mo><mn>3</mn></mrow>
In slt.rkt, I provide some abstractions to build tree transformations. (These are inspired by Oleg Kiselyov's SXSLT.) For now they haven't been efficiently implemented and I'd like to modify them in the future. As an illustration of the usage, I provide a procdure Tm in math-styles.rkt.
(define math-style* `(((default) *preorder* ,(lambda (tag attr* . xml*) (cond ((eq? tag 'math) `(,tag ,attr* . ,xml*)) ((memq tag '(merror mfrac mi mmultiscripts mn mo mover mpadded mphantom mroot mrow ms mspace msqrt mstyle msub msubsup msup mtable mtd mtext mtr munder munderover)) (Math `(,tag ,attr* . ,xml*))) (else `(,tag ,attr* . ,(map Tm xml*)))))) ((text) ,(lambda (str) str)))) (define Tm (T math-style*))