/racket-5-0-2-bin-i386-osx-mac-dmg/collects/scribble/decode.rkt

http://github.com/smorin/f4f.arc · Racket · 327 lines · 302 code · 21 blank · 4 comment · 50 complexity · 73f3590adf85ec2ef46d39c3c3ce4791 MD5 · raw file

  1. #lang scheme/base
  2. (require "core.ss"
  3. "private/provide-structs.ss"
  4. "decode-struct.ss"
  5. scheme/contract
  6. scheme/class
  7. scheme/list)
  8. (define (pre-content? i)
  9. (or (string? i)
  10. (and (content? i)
  11. (not (list? i)))
  12. (and (splice? i)
  13. (andmap pre-content? (splice-run i)))
  14. (void? i)))
  15. (define (pre-flow? i)
  16. (or (string? i)
  17. (and (content? i)
  18. (not (list? i)))
  19. (block? i)
  20. (and (splice? i)
  21. (andmap pre-flow? (splice-run i)))
  22. (void? i)))
  23. (define (pre-part? v)
  24. (or (pre-flow? v)
  25. (title-decl? v)
  26. (part-start? v)
  27. (part-index-decl? v)
  28. (part-collect-decl? v)
  29. (part-tag-decl? v)
  30. (part? v)
  31. (and (splice? v)
  32. (andmap pre-part? (splice-run v)))))
  33. (provide-structs
  34. [title-decl ([tag-prefix (or/c false/c string?)]
  35. [tags (listof tag?)]
  36. [version (or/c string? false/c)]
  37. [style style?]
  38. [content content?])]
  39. [part-start ([depth integer?]
  40. [tag-prefix (or/c false/c string?)]
  41. [tags (listof tag?)]
  42. [style style?]
  43. [title content?])]
  44. [splice ([run list?])]
  45. [part-index-decl ([plain-seq (listof string?)]
  46. [entry-seq list?])]
  47. [part-collect-decl ([element (or/c element? part-relative-element?)])]
  48. [part-tag-decl ([tag tag?])])
  49. (provide whitespace?
  50. pre-content?
  51. pre-flow?
  52. pre-part?)
  53. (provide/contract
  54. [decode (-> (listof pre-part?)
  55. part?)]
  56. [decode-part (-> (listof pre-part?)
  57. (listof string?)
  58. (or/c #f content?)
  59. exact-nonnegative-integer?
  60. part?)]
  61. [decode-flow (-> (listof pre-flow?)
  62. (listof block?))]
  63. [decode-paragraph (-> (listof pre-content?)
  64. paragraph?)]
  65. [decode-compound-paragraph (-> (listof pre-flow?)
  66. paragraph?)]
  67. [decode-content (-> (listof pre-content?)
  68. content?)]
  69. [rename decode-content decode-elements
  70. (-> (listof pre-content?)
  71. content?)]
  72. [decode-string (-> string? content?)]
  73. [clean-up-index-string (-> string? string?)])
  74. (define (clean-up-index-string s)
  75. ;; Collapse whitespace, and remove leading or trailing spaces, which
  76. ;; might appear there due to images or something else that gets
  77. ;; dropped in string form.
  78. (let* ([s (regexp-replace* #px"\\s+" s " ")]
  79. [s (regexp-replace* #rx"^ " s "")]
  80. [s (regexp-replace* #rx" $" s "")])
  81. s))
  82. (define (decode-string s)
  83. (let loop ([l '((#rx"---" mdash)
  84. (#rx"--" ndash)
  85. (#rx"``" ldquo)
  86. (#rx"''" rdquo)
  87. (#rx"'" rsquo))])
  88. (cond [(null? l) (list s)]
  89. [(regexp-match-positions (caar l) s)
  90. => (lambda (m)
  91. (append (decode-string (substring s 0 (caar m)))
  92. (cdar l)
  93. (decode-string (substring s (cdar m)))))]
  94. [else (loop (cdr l))])))
  95. (define (line-break? v)
  96. (equal? v "\n"))
  97. (define (whitespace? v)
  98. (and (string? v) (regexp-match? #px"^[\\s]*$" v)))
  99. (define (decode-accum-para accum)
  100. (if (andmap whitespace? accum)
  101. null
  102. (list (decode-compound-paragraph (reverse (skip-whitespace accum))))))
  103. (define (decode-flow* l keys colls tag-prefix tags vers style title part-depth)
  104. (let loop ([l l] [next? #f] [keys keys] [colls colls] [accum null]
  105. [title title] [tag-prefix tag-prefix] [tags tags] [vers vers]
  106. [style style])
  107. (cond
  108. [(null? l)
  109. (let ([k-tags (map (lambda (k) `(idx ,(make-generated-tag))) keys)]
  110. [tags (if (null? tags)
  111. (list `(part ,(make-generated-tag)))
  112. tags)])
  113. (make-part
  114. tag-prefix
  115. (append tags k-tags)
  116. title
  117. (if vers
  118. (make-style (style-name style)
  119. (cons (make-document-version vers)
  120. (style-properties style)))
  121. style)
  122. (let ([l (append
  123. (map (lambda (k tag)
  124. (make-index-element #f null tag
  125. (part-index-decl-plain-seq k)
  126. (part-index-decl-entry-seq k)
  127. #f))
  128. keys k-tags)
  129. colls)])
  130. (if (and title
  131. (not (memq 'hidden (style-properties style))))
  132. (cons (make-index-element
  133. #f null (car tags)
  134. (list (clean-up-index-string
  135. (regexp-replace #px"^\\s+(?:(?:A|An|The)\\s)?"
  136. (content->string title) "")))
  137. (list (make-element #f title))
  138. (make-part-index-desc))
  139. l)
  140. l))
  141. (decode-accum-para accum)
  142. null))]
  143. [(void? (car l))
  144. (loop (cdr l) next? keys colls accum title tag-prefix tags vers style)]
  145. [(title-decl? (car l))
  146. (cond [(not part-depth) (error 'decode "misplaced title: ~e" (car l))]
  147. [title (error 'decode "found extra title: ~v" (car l))]
  148. [else (loop (cdr l) next? keys colls accum
  149. (title-decl-content (car l))
  150. (title-decl-tag-prefix (car l))
  151. (title-decl-tags (car l))
  152. (title-decl-version (car l))
  153. (title-decl-style (car l)))])]
  154. #;
  155. ;; Blocks are now handled by decode-accum-para
  156. [(block? (car l))
  157. (let ([para (decode-accum-para accum)]
  158. [part (decode-flow* (cdr l) keys colls tag-prefix tags vers style
  159. title part-depth)])
  160. (make-part
  161. (part-tag-prefix part)
  162. (part-tags part)
  163. (part-title-content part)
  164. (part-style part)
  165. (part-to-collect part)
  166. (append para (list (car l)) (part-flow part))
  167. (part-parts part)))]
  168. [(part? (car l))
  169. (let ([para (decode-accum-para accum)]
  170. [part (decode-flow* (cdr l) keys colls tag-prefix tags vers style
  171. title part-depth)])
  172. (make-part
  173. (part-tag-prefix part)
  174. (part-tags part)
  175. (part-title-content part)
  176. (part-style part)
  177. (part-to-collect part)
  178. (append para (part-blocks part))
  179. (cons (car l) (part-parts part))))]
  180. [(and (part-start? (car l))
  181. (or (not part-depth)
  182. ((part-start-depth (car l)) . <= . part-depth)))
  183. (unless part-depth (error 'decode "misplaced part: ~e" (car l)))
  184. (let ([s (car l)])
  185. (let loop ([l (cdr l)] [s-accum null])
  186. (if (or (null? l)
  187. (and (part-start? (car l))
  188. ((part-start-depth (car l)) . <= . part-depth))
  189. (part? (car l)))
  190. (let ([para (decode-accum-para accum)]
  191. [s (decode-styled-part (reverse s-accum)
  192. (part-start-tag-prefix s)
  193. (part-start-tags s)
  194. (part-start-style s)
  195. (part-start-title s)
  196. (add1 part-depth))]
  197. [part (decode-flow* l keys colls tag-prefix tags vers style
  198. title part-depth)])
  199. (make-part (part-tag-prefix part)
  200. (part-tags part)
  201. (part-title-content part)
  202. (part-style part)
  203. (part-to-collect part)
  204. para
  205. (cons s (part-parts part))))
  206. (if (splice? (car l))
  207. (loop (append (splice-run (car l)) (cdr l)) s-accum)
  208. (loop (cdr l) (cons (car l) s-accum))))))]
  209. [(splice? (car l))
  210. (loop (append (splice-run (car l)) (cdr l))
  211. next? keys colls accum title tag-prefix tags vers style)]
  212. [(null? (cdr l))
  213. (loop null #f keys colls (cons (car l) accum) title tag-prefix tags
  214. vers style)]
  215. [(part-index-decl? (car l))
  216. (loop (cdr l) next? (cons (car l) keys) colls accum title tag-prefix
  217. tags vers style)]
  218. [(part-collect-decl? (car l))
  219. (loop (cdr l) next? keys
  220. (cons (part-collect-decl-element (car l)) colls)
  221. accum title tag-prefix tags vers style)]
  222. [(part-tag-decl? (car l))
  223. (loop (cdr l) next? keys colls accum title tag-prefix
  224. (append tags (list (part-tag-decl-tag (car l))))
  225. vers style)]
  226. [(and (pair? (cdr l))
  227. (splice? (cadr l)))
  228. (loop (cons (car l) (append (splice-run (cadr l)) (cddr l)))
  229. next? keys colls accum title tag-prefix tags vers style)]
  230. [(line-break? (car l))
  231. (if next?
  232. (loop (cdr l) #t keys colls accum title tag-prefix tags vers style)
  233. (let ([m (match-newline-whitespace (cdr l))])
  234. (if m
  235. (let ([part (loop m #t keys colls null title tag-prefix tags vers
  236. style)])
  237. (make-part
  238. (part-tag-prefix part)
  239. (part-tags part)
  240. (part-title-content part)
  241. (part-style part)
  242. (part-to-collect part)
  243. (append (decode-accum-para accum)
  244. (part-blocks part))
  245. (part-parts part)))
  246. (loop (cdr l) #f keys colls (cons (car l) accum) title tag-prefix
  247. tags vers style))))]
  248. [else (loop (cdr l) #f keys colls (cons (car l) accum) title tag-prefix
  249. tags vers style)])))
  250. (define (decode-part l tags title depth)
  251. (decode-flow* l null null #f tags #f plain title depth))
  252. (define (decode-styled-part l tag-prefix tags style title depth)
  253. (decode-flow* l null null tag-prefix tags #f style title depth))
  254. (define (decode-flow l)
  255. (part-blocks (decode-flow* l null null #f null #f plain #f #f)))
  256. (define (match-newline-whitespace l)
  257. (cond [(null? l) #f]
  258. [(void? (car l)) (match-newline-whitespace (cdr l))]
  259. [(line-break? (car l)) (skip-whitespace l)]
  260. [(splice? (car l))
  261. (match-newline-whitespace (append (splice-run (car l)) (cdr l)))]
  262. [(whitespace? (car l)) (match-newline-whitespace (cdr l))]
  263. [else #f]))
  264. (define (skip-whitespace l)
  265. (if (or (null? l)
  266. (not (or (whitespace? (car l))
  267. (void? (car l)))))
  268. l
  269. (skip-whitespace (cdr l))))
  270. (define (decode l)
  271. (decode-part l null #f 0))
  272. (define (decode-paragraph l)
  273. (make-paragraph plain (decode-content l)))
  274. (define (decode-content l)
  275. (append-map (lambda (s) (cond
  276. [(string? s) (decode-string s)]
  277. [(void? s) null]
  278. [(splice? s) (decode-content (splice-run s))]
  279. [else (list s)]))
  280. (skip-whitespace l)))
  281. (define (decode-compound-paragraph l)
  282. (define (finish-accum para-accum)
  283. (if (null? para-accum)
  284. null
  285. (list (make-paragraph plain (skip-whitespace (apply append (reverse para-accum)))))))
  286. (let ([r (let loop ([l (skip-whitespace l)]
  287. [para-accum null])
  288. (cond
  289. [(null? l)
  290. (finish-accum para-accum)]
  291. [else
  292. (let ([s (car l)])
  293. (cond
  294. [(block? s) (append
  295. (finish-accum para-accum)
  296. (cons s (loop (skip-whitespace (cdr l)) null)))]
  297. [(string? s) (loop (cdr l)
  298. (cons (decode-string s) para-accum))]
  299. [else (loop (cdr l)
  300. (cons (list (car l)) para-accum))]))]))])
  301. (cond
  302. [(null? r)
  303. (make-paragraph plain null)]
  304. [(null? (cdr r))
  305. (car r)]
  306. [(make-compound-paragraph plain r)])))