comparison lisp/progmodes/ebnf2ps.el @ 27451:f062cc830f07

*** empty log message ***
author Gerd Moellmann <gerd@gnu.org>
date Thu, 27 Jan 2000 14:31:16 +0000
parents
children 507d8bb34bef
comparison
equal deleted inserted replaced
27450:1f69452af743 27451:f062cc830f07
1 ;;; ebnf2ps --- Translate an EBNF to a syntatic chart on PostScript
2
3 ;; Copyright (C) 1999 Vinicius Jose Latorre
4
5 ;; Author: Vinicius Jose Latorre <vinicius@cpqd.com.br>
6 ;; Maintainer: Vinicius Jose Latorre <vinicius@cpqd.com.br>
7 ;; Keywords: wp, ebnf, PostScript
8 ;; Time-stamp: <99/12/11 21:41:24 vinicius>
9 ;; Version: 3.1
10
11 (defconst ebnf-version "3.1"
12 "ebnf2ps.el, v 3.1 <99/12/11 vinicius>
13
14 Vinicius's last change version. When reporting bugs, please also
15 report the version of Emacs, if any, that ebnf2ps was running with.
16
17 Please send all bug fixes and enhancements to
18 Vinicius Jose Latorre <vinicius@cpqd.com.br>.
19 ")
20
21 ;; This file is *NOT* (yet?) part of GNU Emacs.
22
23 ;; This program is free software; you can redistribute it and/or modify
24 ;; it under the terms of the GNU General Public License as published by
25 ;; the Free Software Foundation; either version 2, or (at your option)
26 ;; any later version.
27
28 ;; This program is distributed in the hope that it will be useful,
29 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
30 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 ;; GNU General Public License for more details.
32
33 ;; You should have received a copy of the GNU General Public License
34 ;; along with GNU Emacs; see the file COPYING. If not, write to the
35 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
36 ;; Boston, MA 02111-1307, USA.
37
38 ;;; Commentary:
39
40 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
41 ;;
42 ;; Introduction
43 ;; ------------
44 ;;
45 ;; This package translates an EBNF to a syntatic chart on PostScript.
46 ;;
47 ;; To use ebnf2ps, insert in your ~/.emacs:
48 ;;
49 ;; (require 'ebnf2ps)
50 ;;
51 ;; ebnf2ps uses ps-print package (version 3.05.1 or later), so see ps-print to
52 ;; know how to set options like landscape printing, page headings, margins, etc.
53 ;;
54 ;; NOTE: ps-print zebra stripes and line number options doesn't have effect on
55 ;; ebnf2ps, they behave as it's turned off.
56 ;;
57 ;; For good performance, be sure to byte-compile ebnf2ps.el, e.g.
58 ;;
59 ;; M-x byte-compile-file <give the path to ebnf2ps.el when prompted>
60 ;;
61 ;; This will generate ebnf2ps.elc, which will be loaded instead of ebnf2ps.el.
62 ;;
63 ;; ebnf2ps was tested with GNU Emacs 20.4.1.
64 ;;
65 ;;
66 ;; Using ebnf2ps
67 ;; -------------
68 ;;
69 ;; ebnf2ps provides six commands for generating PostScript syntatic chart images
70 ;; of Emacs buffers:
71 ;;
72 ;; ebnf-print-buffer
73 ;; ebnf-print-region
74 ;; ebnf-spool-buffer
75 ;; ebnf-spool-region
76 ;; ebnf-eps-buffer
77 ;; ebnf-eps-region
78 ;;
79 ;; These commands all perform essentially the same function: they generate
80 ;; PostScript syntatic chart images suitable for printing on a PostScript
81 ;; printer or displaying with GhostScript. These commands are collectively
82 ;; referred to as "ebnf- commands".
83 ;;
84 ;; The word "print", "spool" and "eps" in the command name determines when the
85 ;; PostScript image is sent to the printer (or file):
86 ;;
87 ;; print - The PostScript image is immediately sent to the printer;
88 ;;
89 ;; spool - The PostScript image is saved temporarily in an Emacs buffer.
90 ;; Many images may be spooled locally before printing them. To
91 ;; send the spooled images to the printer, use the command
92 ;; `ebnf-despool'.
93 ;;
94 ;; eps - The PostScript image is immediately sent to a EPS file.
95 ;;
96 ;; The spooling mechanism is the same as used by ps-print and was designed for
97 ;; printing lots of small files to save paper that would otherwise be wasted on
98 ;; banner pages, and to make it easier to find your output at the printer (it's
99 ;; easier to pick up one 50-page printout than to find 50 single-page
100 ;; printouts). As ebnf2ps and ps-print use the same Emacs buffer to spool
101 ;; images, you can intermix the spooling of ebnf2ps and ps-print images.
102 ;;
103 ;; ebnf2ps use the same hook of ps-print in the `kill-emacs-hook' so that you
104 ;; won't accidentally quit from Emacs while you have unprinted PostScript
105 ;; waiting in the spool buffer. If you do attempt to exit with spooled
106 ;; PostScript, you'll be asked if you want to print it, and if you decline,
107 ;; you'll be asked to confirm the exit; this is modeled on the confirmation that
108 ;; Emacs uses for modified buffers.
109 ;;
110 ;; The word "buffer" or "region" in the command name determines how much of the
111 ;; buffer is printed:
112 ;;
113 ;; buffer - Print the entire buffer.
114 ;;
115 ;; region - Print just the current region.
116 ;;
117 ;; Two ebnf- command examples:
118 ;;
119 ;; ebnf-print-buffer - translate and print the entire buffer, and send
120 ;; it immediately to the printer.
121 ;;
122 ;; ebnf-spool-region - translate and print just the current region, and
123 ;; spool the image in Emacs to send to the printer
124 ;; later.
125 ;;
126 ;; Note that `ebnf-eps-buffer' and `ebnf-eps-region' never spool the EPS image,
127 ;; so they don't use the ps-print spooling mechanism. See section "Actions in
128 ;; Comments" for an explanation about EPS file generation.
129 ;;
130 ;;
131 ;; Invoking Ebnf2ps
132 ;; ----------------
133 ;;
134 ;; To translate and print your buffer, type
135 ;;
136 ;; M-x ebnf-print-buffer
137 ;;
138 ;; or substitute one of the other four ebnf- commands. The command will
139 ;; generate the PostScript image and print or spool it as specified. By giving
140 ;; the command a prefix argument
141 ;;
142 ;; C-u M-x ebnf-print-buffer
143 ;;
144 ;; it will save the PostScript image to a file instead of sending it to the
145 ;; printer; you will be prompted for the name of the file to save the image to.
146 ;; The prefix argument is ignored by the commands that spool their images, but
147 ;; you may save the spooled images to a file by giving a prefix argument to
148 ;; `ebnf-despool':
149 ;;
150 ;; C-u M-x ebnf-despool
151 ;;
152 ;; When invoked this way, `ebnf-despool' will prompt you for the name of the
153 ;; file to save to.
154 ;;
155 ;; The prefix argument is also ignored by `ebnf-eps-buffer' and
156 ;; `ebnf-eps-region'.
157 ;;
158 ;; Any of the `ebnf-' commands can be bound to keys. Here are some examples:
159 ;;
160 ;; (global-set-key 'f22 'ebnf-print-buffer) ;f22 is prsc
161 ;; (global-set-key '(shift f22) 'ebnf-print-region)
162 ;; (global-set-key '(control f22) 'ebnf-despool)
163 ;;
164 ;;
165 ;; EBNF Syntax
166 ;; -----------
167 ;;
168 ;; The current EBNF that ebnf2ps accepts has the following constructions:
169 ;;
170 ;; ; comment (until end of line)
171 ;; A non-terminal
172 ;; "C" terminal
173 ;; ?C? special
174 ;; $A default non-terminal (see text below)
175 ;; $"C" default terminal (see text below)
176 ;; $?C? default special (see text below)
177 ;; A = B. production (A is the header and B the body)
178 ;; C D sequence (C occurs before D)
179 ;; C | D alternative (C or D occurs)
180 ;; A - B exception (A excluding B, B without any non-terminal)
181 ;; n * A repetition (A repeats n (integer) times)
182 ;; (C) group (expression C is grouped together)
183 ;; [C] optional (C may or not occurs)
184 ;; C+ one or more occurrences of C
185 ;; {C}+ one or more occurrences of C
186 ;; {C}* zero or more occurrences of C
187 ;; {C} zero or more occurrences of C
188 ;; C / D equivalent to: C {D C}*
189 ;; {C || D}+ equivalent to: C {D C}*
190 ;; {C || D}* equivalent to: [C {D C}*]
191 ;; {C || D} equivalent to: [C {D C}*]
192 ;;
193 ;; The EBNF syntax written using the notation above is:
194 ;;
195 ;; EBNF = {production}+.
196 ;;
197 ;; production = non_terminal "=" body ".". ;; production
198 ;;
199 ;; body = {sequence || "|"}*. ;; alternative
200 ;;
201 ;; sequence = {exception}*. ;; sequence
202 ;;
203 ;; exception = repeat [ "-" repeat]. ;; exception
204 ;;
205 ;; repeat = [ integer "*" ] term. ;; repetition
206 ;;
207 ;; term = factor
208 ;; | [factor] "+" ;; one-or-more
209 ;; | [factor] "/" [factor] ;; one-or-more
210 ;; .
211 ;;
212 ;; factor = [ "$" ] "\"" terminal "\"" ;; terminal
213 ;; | [ "$" ] non_terminal ;; non-terminal
214 ;; | [ "$" ] "?" special "?" ;; special
215 ;; | "(" body ")" ;; group
216 ;; | "[" body "]" ;; zero-or-one
217 ;; | "{" body [ "||" body ] "}+" ;; one-or-more
218 ;; | "{" body [ "||" body ] "}*" ;; zero-or-more
219 ;; | "{" body [ "||" body ] "}" ;; zero-or-more
220 ;; .
221 ;;
222 ;; non_terminal = "[A-Za-z\\240-\\377][!#%&'*-,0-:<>@-Z\\^-z~\\240-\\377]*".
223 ;;
224 ;; terminal = "\\([^\"\\]\\|\\\\[ -~\\240-\\377]\\)+".
225 ;;
226 ;; special = "[^?\\n\\000-\\010\\016-\\037\\177-\\237]*".
227 ;;
228 ;; integer = "[0-9]+".
229 ;;
230 ;; comment = ";" "[^\\n\\000-\\010\\016-\\037\\177-\\237]*" "\\n".
231 ;;
232 ;; Try to use the above EBNF to test ebnf2ps.
233 ;;
234 ;; The `default' terminal, non-terminal and special is a way to indicate a
235 ;; default path in a production. For example, the production:
236 ;;
237 ;; X = [ $A ( B | $C ) | D ].
238 ;;
239 ;; Indicates that the default meaning for "X" is "A C" if "X" is empty.
240 ;;
241 ;; The terminal name is controlled by `ebnf-terminal-regexp' and
242 ;; `ebnf-case-fold-search', so it's possible to match other kind of terminal
243 ;; name besides that enclosed by `"'.
244 ;;
245 ;; Let's see an example:
246 ;;
247 ;; (setq ebnf-terminal-regexp "[A-Z][_A-Z]*") ; upper case name
248 ;; (setq ebnf-case-fold-search nil) ; exact matching
249 ;;
250 ;; If you have the production:
251 ;;
252 ;; Logical = "(" Expression ( OR | AND | "XOR" ) Expression ")".
253 ;;
254 ;; The names are classified as:
255 ;;
256 ;; Logical Expression non-terminal
257 ;; "(" OR AND "XOR" ")" terminal
258 ;;
259 ;; The line comment is controlled by `ebnf-lex-comment-char'. The default value
260 ;; is ?\; (character `;').
261 ;;
262 ;; The end of production is controlled by `ebnf-lex-eop-char'. The default
263 ;; value is ?. (character `.').
264 ;;
265 ;; The variable `ebnf-syntax' specifies which syntax to recognize:
266 ;;
267 ;; `ebnf' ebnf2ps recognizes the syntax described above.
268 ;; The following variables *ONLY* have effect with this
269 ;; setting:
270 ;; `ebnf-terminal-regexp', `ebnf-case-fold-search',
271 ;; `ebnf-lex-comment-char' and `ebnf-lex-eop-char'.
272 ;;
273 ;; `iso-ebnf' ebnf2ps recognizes the syntax described in the URL:
274 ;; `http://www.cl.cam.ac.uk/~mgk25/iso-ebnf.html'
275 ;; ("International Standard of the ISO EBNF Notation").
276 ;; The following variables *ONLY* have effect with this
277 ;; setting:
278 ;; `ebnf-iso-alternative-p' and `ebnf-iso-normalize-p'.
279 ;;
280 ;; `yacc' ebnf2ps recognizes the Yacc/Bison syntax.
281 ;; The following variable *ONLY* has effect with this
282 ;; setting:
283 ;; `ebnf-yac-ignore-error-recovery'.
284 ;;
285 ;; Any other value is treated as `ebnf'.
286 ;;
287 ;; The default value is `ebnf'.
288 ;;
289 ;;
290 ;; Optimizations
291 ;; -------------
292 ;;
293 ;; The following EBNF optimizations are done:
294 ;;
295 ;; [ { A }* ] ==> { A }*
296 ;; [ { A }+ ] ==> { A }*
297 ;; [ A ] + ==> { A }*
298 ;; { A }* + ==> { A }*
299 ;; { A }+ + ==> { A }+
300 ;; { A }- ==> { A }+
301 ;; [ A ]- ==> A
302 ;; ( A | EMPTY )- ==> A
303 ;; ( A | B | EMPTY )- ==> A | B
304 ;; [ A | B ] ==> A | B | EMPTY
305 ;; n * EMPTY ==> EMPTY
306 ;; EMPTY + ==> EMPTY
307 ;; EMPTY / EMPTY ==> EMPTY
308 ;; EMPTY - A ==> EMPTY
309 ;;
310 ;; The following optimizations are done when `ebnf-optimize' is non-nil:
311 ;;
312 ;; left recursion:
313 ;; 1. A = B | A C. ==> A = B {C}*.
314 ;; 2. A = B | A B. ==> A = {B}+.
315 ;; 3. A = | A B. ==> A = {B}*.
316 ;; 4. A = B | A C B. ==> A = {B || C}+.
317 ;; 5. A = B | D | A C | A E. ==> A = ( B | D ) { C | E }*.
318 ;;
319 ;; optional:
320 ;; 6. A = B | . ==> A = [B].
321 ;; 7. A = | B . ==> A = [B].
322 ;;
323 ;; factoration:
324 ;; 8. A = B C | B D. ==> A = B (C | D).
325 ;; 9. A = C B | D B. ==> A = (C | D) B.
326 ;; 10. A = B C E | B D E. ==> A = B (C | D) E.
327 ;;
328 ;; The above optimizations are specially useful when `ebnf-syntax' is `yacc'.
329 ;;
330 ;;
331 ;; Form Feed
332 ;; ---------
333 ;;
334 ;; You may use form feed (^L \014) to force a production to start on a new page,
335 ;; for example:
336 ;;
337 ;; a) A = B | C.
338 ;; ^L
339 ;; X = Y | Z.
340 ;;
341 ;; b) A = B ^L | C.
342 ;; X = Y | Z.
343 ;;
344 ;; c) A = B ^L^L^L | C.^L
345 ;; ^L
346 ;; X = Y | Z.
347 ;;
348 ;; In all examples above, only the production X will start on a new page.
349 ;;
350 ;;
351 ;; Actions in Comments
352 ;; -------------------
353 ;;
354 ;; ebnf2ps accepts the following actions in comments:
355 ;;
356 ;; ;> the next production starts in the same line as the current one.
357 ;; It is useful when `ebnf-horizontal-orientation' is nil.
358 ;;
359 ;; ;< the next production starts in the next line.
360 ;; It is useful when `ebnf-horizontal-orientation' is non-nil.
361 ;;
362 ;; ;[EPS open a new EPS file. The EPS file name has the form:
363 ;; <PREFIX><NAME>.eps
364 ;; where <PREFIX> is given by variable `ebnf-eps-prefix' and <NAME>
365 ;; is the string given by ;[ action comment, this string is mapped
366 ;; to form a valid file name (see documentation for
367 ;; `ebnf-eps-buffer' or `ebnf-eps-region').
368 ;; It has effect only during `ebnf-eps-buffer' or
369 ;; `ebnf-eps-region' execution.
370 ;; It's an error to try to open an already opened EPS file.
371 ;;
372 ;; ;]EPS close an opened EPS file.
373 ;; It has effect only during `ebnf-eps-buffer' or
374 ;; `ebnf-eps-region' execution.
375 ;; It's an error to try to close a not opened EPS file.
376 ;;
377 ;; So if you have:
378 ;;
379 ;; (setq ebnf-horizontal-orientation nil)
380 ;;
381 ;; A = t.
382 ;; C = x.
383 ;; ;> C and B are drawn in the same line
384 ;; B = y.
385 ;; W = v.
386 ;;
387 ;; The graphical result is:
388 ;;
389 ;; +---+
390 ;; | A |
391 ;; +---+
392 ;;
393 ;; +---------+ +-----+
394 ;; | | | |
395 ;; | C | | |
396 ;; | | | B |
397 ;; +---------+ | |
398 ;; | |
399 ;; +-----+
400 ;;
401 ;; +-----------+
402 ;; | W |
403 ;; +-----------+
404 ;;
405 ;; Note that if ascending production sort is used, the productions A and B will
406 ;; be drawn in the same line instead of C and B.
407 ;;
408 ;; If consecutive actions occur, only the last one takes effect, so if you have:
409 ;;
410 ;; A = X.
411 ;; ;<
412 ;; ^L
413 ;; ;>
414 ;; B = Y.
415 ;;
416 ;; Only the ;> will take effect, that is, A and B will be drawn in the same
417 ;; line.
418 ;;
419 ;; In ISO EBNF the above actions are specified as (*>*), (*<*), (*[EPS*) and
420 ;; (*]EPS*). The first example above should be written:
421 ;;
422 ;; A = t;
423 ;; C = x;
424 ;; (*> C and B are drawn in the same line *)
425 ;; B = y;
426 ;; W = v;
427 ;;
428 ;; For an example of EPS action when executing `ebnf-eps-buffer' or
429 ;; `ebnf-eps-region':
430 ;;
431 ;; Z = B0.
432 ;; ;[CC
433 ;; ;[AA
434 ;; A = B1.
435 ;; ;[BB
436 ;; C = B2.
437 ;; ;]AA
438 ;; B = B3.
439 ;; ;]BB
440 ;; ;]CC
441 ;; D = B4.
442 ;; E = B5.
443 ;; ;[CC
444 ;; F = B6.
445 ;; ;]CC
446 ;; G = B7.
447 ;;
448 ;; The following table summarizes the results:
449 ;;
450 ;; EPS FILE NAME NO SORT ASCENDING SORT DESCENDING SORT
451 ;; ebnf--AA.eps A C A C C A
452 ;; ebnf--BB.eps C B B C C B
453 ;; ebnf--CC.eps A C B F A B C F F C B A
454 ;; ebnf--D.eps D D D
455 ;; ebnf--E.eps E E E
456 ;; ebnf--G.eps G G G
457 ;; ebnf--Z.eps Z Z Z
458 ;;
459 ;; As you can see if EPS actions is not used, each single production is
460 ;; generated per EPS file. To avoid overriding EPS files, use names in ;[ that
461 ;; it's not an existing production name.
462 ;;
463 ;; In the following case:
464 ;;
465 ;; A = B0.
466 ;; ;[AA
467 ;; A = B1.
468 ;; ;[BB
469 ;; A = B2.
470 ;;
471 ;; The production A is generated in both files ebnf--AA.eps and ebnf--BB.eps.
472 ;;
473 ;;
474 ;; Utilities
475 ;; ---------
476 ;;
477 ;; Some tools are provided to help you.
478 ;;
479 ;; `ebnf-setup' returns the current setup.
480 ;;
481 ;; `ebnf-syntax-buffer' does a syntatic analysis of your EBNF in the current
482 ;; buffer.
483 ;;
484 ;; `ebnf-syntax-region' does a syntatic analysis of your EBNF in the current
485 ;; region.
486 ;;
487 ;; `ebnf-customize' activates a customization buffer for ebnf2ps options.
488 ;;
489 ;; `ebnf-syntax-buffer', `ebnf-syntax-region' and `ebnf-customize' can be bound
490 ;; to keys in the same way as `ebnf-' commands.
491 ;;
492 ;;
493 ;; Hooks
494 ;; -----
495 ;;
496 ;; ebn2ps has the following hook variables:
497 ;;
498 ;; `ebnf-hook'
499 ;; It is evaluated once before any ebnf2ps process.
500 ;;
501 ;; `ebnf-production-hook'
502 ;; It is evaluated on each beginning of production.
503 ;;
504 ;; `ebnf-page-hook'
505 ;; It is evaluated on each beginning of page.
506 ;;
507 ;;
508 ;; Options
509 ;; -------
510 ;;
511 ;; Below it's shown a brief description of ebnf2ps options, please, see the
512 ;; options declaration in the code for a long documentation.
513 ;;
514 ;; `ebnf-horizontal-orientation' Non-nil means productions are drawn
515 ;; horizontally.
516 ;;
517 ;; `ebnf-horizontal-max-height' Non-nil means to use maximum production
518 ;; height in horizontal orientation.
519 ;;
520 ;; `ebnf-production-horizontal-space' Specify horizontal space in points
521 ;; between productions.
522 ;;
523 ;; `ebnf-production-vertical-space' Specify vertical space in points between
524 ;; productions.
525 ;;
526 ;; `ebnf-justify-sequence' Specify justification of terms in a
527 ;; sequence inside alternatives.
528 ;;
529 ;; `ebnf-terminal-regexp' Specify how it's a terminal name.
530 ;;
531 ;; `ebnf-case-fold-search' Non-nil means ignore case on matching.
532 ;;
533 ;; `ebnf-terminal-font' Specify terminal font.
534 ;;
535 ;; `ebnf-terminal-shape' Specify terminal box shape.
536 ;;
537 ;; `ebnf-terminal-shadow' Non-nil means terminal box will have a
538 ;; shadow.
539 ;;
540 ;; `ebnf-terminal-border-width' Specify border width for terminal box.
541 ;;
542 ;; `ebnf-terminal-border-color' Specify border color for terminal box.
543 ;;
544 ;; `ebnf-sort-production' Specify how productions are sorted.
545 ;;
546 ;; `ebnf-production-font' Specify production font.
547 ;;
548 ;; `ebnf-non-terminal-font' Specify non-terminal font.
549 ;;
550 ;; `ebnf-non-terminal-shape' Specify non-terminal box shape.
551 ;;
552 ;; `ebnf-non-terminal-shadow' Non-nil means non-terminal box will have
553 ;; a shadow.
554 ;;
555 ;; `ebnf-non-terminal-border-width' Specify border width for non-terminal
556 ;; box.
557 ;;
558 ;; `ebnf-non-terminal-border-color' Specify border color for non-terminal
559 ;; box.
560 ;;
561 ;; `ebnf-special-font' Specify special font.
562 ;;
563 ;; `ebnf-special-shape' Specify special box shape.
564 ;;
565 ;; `ebnf-special-shadow' Non-nil means special box will have a
566 ;; shadow.
567 ;;
568 ;; `ebnf-special-border-width' Specify border width for special box.
569 ;;
570 ;; `ebnf-special-border-color' Specify border color for special box.
571 ;;
572 ;; `ebnf-except-font' Specify except font.
573 ;;
574 ;; `ebnf-except-shape' Specify except box shape.
575 ;;
576 ;; `ebnf-except-shadow' Non-nil means except box will have a
577 ;; shadow.
578 ;;
579 ;; `ebnf-except-border-width' Specify border width for except box.
580 ;;
581 ;; `ebnf-except-border-color' Specify border color for except box.
582 ;;
583 ;; `ebnf-repeat-font' Specify repeat font.
584 ;;
585 ;; `ebnf-repeat-shape' Specify repeat box shape.
586 ;;
587 ;; `ebnf-repeat-shadow' Non-nil means repeat box will have a
588 ;; shadow.
589 ;;
590 ;; `ebnf-repeat-border-width' Specify border width for repeat box.
591 ;;
592 ;; `ebnf-repeat-border-color' Specify border color for repeat box.
593 ;;
594 ;; `ebnf-entry-percentage' Specify entry height on alternatives.
595 ;;
596 ;; `ebnf-arrow-shape' Specify the arrow shape.
597 ;;
598 ;; `ebnf-chart-shape' Specify chart flow shape.
599 ;;
600 ;; `ebnf-color-p' Non-nil means use color.
601 ;;
602 ;; `ebnf-line-width' Specify flow line width.
603 ;;
604 ;; `ebnf-line-color' Specify flow line color.
605 ;;
606 ;; `ebnf-user-arrow' Specify a user arrow shape (a PostScript
607 ;; code).
608 ;;
609 ;; `ebnf-debug-ps' Non-nil means to generate PostScript
610 ;; debug procedures.
611 ;;
612 ;; `ebnf-lex-comment-char' Specify the line comment character.
613 ;;
614 ;; `ebnf-lex-eop-char' Specify the end of production character.
615 ;;
616 ;; `ebnf-syntax' Specify syntax to be recognized.
617 ;;
618 ;; `ebnf-iso-alternative-p' Non-nil means use alternative ISO EBNF.
619 ;;
620 ;; `ebnf-iso-normalize-p' Non-nil means normalize ISO EBNF syntax
621 ;; names.
622 ;;
623 ;; `ebnf-default-width' Specify additional border width over
624 ;; default terminal, non-terminal or
625 ;; special.
626 ;;
627 ;; `ebnf-eps-prefix' Specify EPS prefix file name.
628 ;;
629 ;; `ebnf-use-float-format' Non-nil means use `%f' float format.
630 ;;
631 ;; `ebnf-yac-ignore-error-recovery' Non-nil means ignore error recovery.
632 ;;
633 ;; `ebnf-ignore-empty-rule' Non-nil means ignore empty rules.
634 ;;
635 ;; `ebnf-optimize' Non-nil means optimize syntatic chart of
636 ;; rules.
637 ;;
638 ;; To set the above options you may:
639 ;;
640 ;; a) insert the code in your ~/.emacs, like:
641 ;;
642 ;; (setq ebnf-terminal-shape 'bevel)
643 ;;
644 ;; This way always keep your default settings when you enter a new Emacs
645 ;; session.
646 ;;
647 ;; b) or use `set-variable' in your Emacs session, like:
648 ;;
649 ;; M-x set-variable RET ebnf-terminal-shape RET bevel RET
650 ;;
651 ;; This way keep your settings only during the current Emacs session.
652 ;;
653 ;; c) or use customization, for example:
654 ;; click on menu-bar *Help* option,
655 ;; then click on *Customize*,
656 ;; then click on *Browse Customization Groups*,
657 ;; expand *PostScript* group,
658 ;; expand *Ebnf2ps* group
659 ;; and then customize ebnf2ps options.
660 ;; Through this way, you may choose if the settings are kept or not when
661 ;; you leave out the current Emacs session.
662 ;;
663 ;; d) or see the option value:
664 ;;
665 ;; C-h v ebnf-terminal-shape RET
666 ;;
667 ;; and click the *customize* hypertext button.
668 ;; Through this way, you may choose if the settings are kept or not when
669 ;; you leave out the current Emacs session.
670 ;;
671 ;; e) or invoke:
672 ;;
673 ;; M-x ebnf-customize RET
674 ;;
675 ;; and then customize ebnf2ps options.
676 ;; Through this way, you may choose if the settings are kept or not when
677 ;; you leave out the current Emacs session.
678 ;;
679 ;;
680 ;; Styles
681 ;; ------
682 ;;
683 ;; Sometimes you need to change the EBNF style you are using, for example,
684 ;; change the shapes and colors. These changes may force you to set some
685 ;; variables and after use, set back the variables to the old values.
686 ;;
687 ;; To help to handle this situation, ebnf2ps has the following commands to
688 ;; handle styles:
689 ;;
690 ;; `ebnf-insert-style' Insert a new style NAME with inheritance INHERITS and
691 ;; values VALUES.
692 ;;
693 ;; `ebnf-merge-style' Merge values of style NAME with style VALUES.
694 ;;
695 ;; `ebnf-apply-style' Set STYLE to current style.
696 ;;
697 ;; `ebnf-reset-style' Reset current style.
698 ;;
699 ;; `ebnf-push-style' Push the current style and set STYLE to current style.
700 ;;
701 ;; `ebnf-pop-style' Pop a style and set it to current style.
702 ;;
703 ;; These commands helps to put together a lot of variable settings in a group
704 ;; and name this group. So when you wish to apply these settings it's only
705 ;; needed to give the name.
706 ;;
707 ;; There is also a notion of simple inheritance of style; so if you declare that
708 ;; a style A inherits from a style B, all settings of B is applied first and
709 ;; then the settings of A is applied. This is useful when you wish to modify
710 ;; some aspects of an existing style, but at same time wish to keep it
711 ;; unmodified.
712 ;;
713 ;; See documentation for `ebnf-style-database'.
714 ;;
715 ;;
716 ;; Layout
717 ;; ------
718 ;;
719 ;; Below it is the layout of minimum area to draw each element, and it's used
720 ;; the following terms:
721 ;;
722 ;; font height is given by:
723 ;; (terminal font height + non-terminal font height) / 2
724 ;;
725 ;; entry is the vertical position used to know where it should be
726 ;; drawn the flow line in the current element.
727 ;;
728 ;;
729 ;; * SPECIAL, TERMINAL and NON-TERMINAL
730 ;;
731 ;; +==============+...................................
732 ;; | | } font height / 2 } entry }
733 ;; | XXXXXXXX...|....... } }
734 ;; ====+ XXXXXXXX +==== } text height ...... } height
735 ;; : | XXXXXXXX...|...:... }
736 ;; : | : : | : } font height / 2 }
737 ;; : +==============+...:...............................
738 ;; : : : : : :
739 ;; : : : : : :......................
740 ;; : : : : : } font height }
741 ;; : : : : :....... }
742 ;; : : : : } font height / 2 }
743 ;; : : : :........... }
744 ;; : : : } text width } width
745 ;; : : :.................. }
746 ;; : : } font height / 2 }
747 ;; : :...................... }
748 ;; : } font height }
749 ;; :.............................................
750 ;;
751 ;;
752 ;; * OPTIONAL
753 ;;
754 ;; +==========+.....................................
755 ;; | | } } }
756 ;; | | } entry } }
757 ;; | | } } }
758 ;; ===+===+ +===+===... } element height } height
759 ;; : \ | | / : } }
760 ;; : + | | + : } }
761 ;; : | +==========+.|................. }
762 ;; : | : : | : } font height }
763 ;; : +==============+...................................
764 ;; : : : :
765 ;; : : : :......................
766 ;; : : : } font height * 2 }
767 ;; : : :.......... }
768 ;; : : } element width } width
769 ;; : :..................... }
770 ;; : } font height * 2 }
771 ;; :...............................................
772 ;;
773 ;;
774 ;; * ALTERNATIVE
775 ;;
776 ;; +===+...................................
777 ;; +==+ A +==+ } A height } }
778 ;; | +===+..|........ } entry }
779 ;; + + } font height } }
780 ;; / +===+...\....... } }
781 ;; ===+====+ B +====+=== } B height ..... } height
782 ;; : \ +===+.../....... }
783 ;; : + + : } font height }
784 ;; : | +===+..|........ }
785 ;; : +==+ C +==+ : } C height }
786 ;; : : +===+...................................
787 ;; : : : :
788 ;; : : : :......................
789 ;; : : : } font height * 2 }
790 ;; : : :......... }
791 ;; : : } max width } width
792 ;; : :................. }
793 ;; : } font height * 2 }
794 ;; :..........................................
795 ;;
796 ;; NOTES:
797 ;; 1. An empty alternative has zero of height.
798 ;;
799 ;; 2. The variable `ebnf-entry-percentage' is used to determine the
800 ;; entry point.
801 ;;
802 ;;
803 ;; * ZERO OR MORE
804 ;;
805 ;; +===========+...............................
806 ;; +=+ separator +=+ } separator height }
807 ;; / +===========+..\........ }
808 ;; + + } }
809 ;; | | } font height }
810 ;; + + } }
811 ;; \ +===========+../........ } height = entry
812 ;; +=+ element +=+ } element height }
813 ;; /: +===========+..\........ }
814 ;; + : : + } }
815 ;; + : : + } font height }
816 ;; / : : \ } }
817 ;; ==+=======================+==.......................
818 ;; : : : :
819 ;; : : : :.......................
820 ;; : : : } font height * 2 }
821 ;; : : :......... }
822 ;; : : } max width } width
823 ;; : :......................... }
824 ;; : } font height * 2 }
825 ;; :...................................................
826 ;;
827 ;;
828 ;; * ONE OR MORE
829 ;;
830 ;; +===========+......................................
831 ;; +=+ separator +=+ } separator height } }
832 ;; / +===========+..\...... } }
833 ;; + + } } entry }
834 ;; | | } font height } } height
835 ;; + + } } }
836 ;; \ +===========+../...... } }
837 ;; ===+=+ element +=+=== } element height .... }
838 ;; : : +===========+......................................
839 ;; : : : :
840 ;; : : : :........................
841 ;; : : : } font height * 2 }
842 ;; : : :....... }
843 ;; : : } max width } width
844 ;; : :....................... }
845 ;; : } font height * 2 }
846 ;; :..............................................
847 ;;
848 ;;
849 ;; * PRODUCTION
850 ;;
851 ;; XXXXXX:......................................
852 ;; XXXXXX: } production font height }
853 ;; XXXXXX:............ }
854 ;; } font height }
855 ;; +======+....... } height = entry
856 ;; | | } }
857 ;; ====+ +==== } element height }
858 ;; : | | : } }
859 ;; : +======+.................................
860 ;; : : : :
861 ;; : : : :......................
862 ;; : : : } font height * 2 }
863 ;; : : :....... }
864 ;; : : } element width } width
865 ;; : :.............. }
866 ;; : } font height * 2 }
867 ;; :.....................................
868 ;;
869 ;;
870 ;; * REPEAT
871 ;;
872 ;; +================+...................................
873 ;; | | } font height / 2 } entry }
874 ;; | +===+...|....... } }
875 ;; ====+ N * | X | +==== } X height ......... } height
876 ;; : | : : +===+...|...:... }
877 ;; : | : : : : | : } font height / 2 }
878 ;; : +================+...:...............................
879 ;; : : : : : : : :
880 ;; : : : : : : : :......................
881 ;; : : : : : : : } font height }
882 ;; : : : : : : :....... }
883 ;; : : : : : : } font height / 2 }
884 ;; : : : : : :........... }
885 ;; : : : : : } X width }
886 ;; : : : : :............... }
887 ;; : : : : } font height / 2 } width
888 ;; : : : :.................. }
889 ;; : : : } text width }
890 ;; : : :..................... }
891 ;; : : } font height / 2 }
892 ;; : :........................ }
893 ;; : } font height }
894 ;; :...............................................
895 ;;
896 ;;
897 ;; * EXCEPT
898 ;;
899 ;; +==================+...................................
900 ;; | | } font height / 2 } entry }
901 ;; | +===+ +===+...|....... } }
902 ;; ====+ | X | - | y | +==== } max height ....... } height
903 ;; : | +===+ +===+...|...:... }
904 ;; : | : : : : | : } font height / 2 }
905 ;; : +==================+...:...............................
906 ;; : : : : : : : :
907 ;; : : : : : : : :......................
908 ;; : : : : : : : } font height }
909 ;; : : : : : : :....... }
910 ;; : : : : : : } font height / 2 }
911 ;; : : : : : :........... }
912 ;; : : : : : } Y width }
913 ;; : : : : :............... }
914 ;; : : : : } font height } width
915 ;; : : : :................... }
916 ;; : : : } X width }
917 ;; : : :....................... }
918 ;; : : } font height / 2 }
919 ;; : :.......................... }
920 ;; : } font height }
921 ;; :.................................................
922 ;;
923 ;; NOTE: If Y element is empty, it's draw nothing at Y place.
924 ;;
925 ;;
926 ;; Internal Structures
927 ;; -------------------
928 ;;
929 ;; ebnf2ps has two passes. The first pass does a lexical and syntatic analysis
930 ;; of current buffer and generates an intermediate representation. The second
931 ;; pass uses the intermediate representation to generate the PostScript syntatic
932 ;; chart.
933 ;;
934 ;; The intermediate representation is a list of vectors, the vector element
935 ;; represents a syntatic chart element. Below is a vector representation for
936 ;; each syntatic chart element.
937 ;;
938 ;; [production WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH NAME PRODUCTION ACTION]
939 ;; [alternative WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH LIST]
940 ;; [sequence WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH LIST]
941 ;; [terminal WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH NAME DEFAULT]
942 ;; [non-terminal WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH NAME DEFAULT]
943 ;; [special WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH NAME DEFAULT]
944 ;; [empty WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH]
945 ;; [optional WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH ELEMENT]
946 ;; [one-or-more WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH ELEMENT SEPARATOR]
947 ;; [zero-or-more WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH ELEMENT SEPARATOR]
948 ;; [repeat WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH TIMES ELEMENT]
949 ;; [except WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH ELEMENT ELEMENT]
950 ;;
951 ;; The first vector position is a function symbol used to generate PostScript
952 ;; for this element.
953 ;; WIDTH-FUN is a function symbol called to adjust the element width.
954 ;; DIM-FUN is a function symbol called to set the element dimensions.
955 ;; ENTRY is the element entry point.
956 ;; HEIGHT and WIDTH are the element height and width, respectively.
957 ;; NAME is a string that it's the element name.
958 ;; DEFAULT is a boolean that indicates if it's a `default' element.
959 ;; PRODUCTION and ELEMENT are vectors that represents sub-elements of current
960 ;; one.
961 ;; LIST is a list of vector that represents the list part for alternatives and
962 ;; sequences.
963 ;; SEPARATOR is a vector that represents the sub-element used to separate the
964 ;; list elements.
965 ;; TIMES is a string representing the number of times that ELEMENT is repeated
966 ;; on a repeat construction.
967 ;; ACTION indicates some action that should be done before production is
968 ;; generated. The current actions are:
969 ;;
970 ;; nil no action.
971 ;;
972 ;; form-feed current production starts on a new page.
973 ;;
974 ;; newline current production starts on next line, this is useful
975 ;; when `ebnf-horizontal-orientation' is non-nil.
976 ;;
977 ;; keep-line current production continues on the current line, this
978 ;; is useful when `ebnf-horizontal-orientation' is nil.
979 ;;
980 ;;
981 ;; Things To Change
982 ;; ----------------
983 ;;
984 ;; . Handle situations when syntatic chart is out of paper.
985 ;; . Use other alphabet than ascii.
986 ;; . Optimizations...
987 ;;
988 ;;
989 ;; Acknowledgements
990 ;; ----------------
991 ;;
992 ;; Thanks to all who emailed comments.
993 ;;
994 ;;
995 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
996
997 ;;; code:
998
999
1000 (require 'ps-print)
1001
1002 (and (string< ps-print-version "3.05.1")
1003 (error "`ebnf2ps' requires `ps-print' package version 3.05.1 or later"))
1004
1005
1006 ;; temporary fix for ps-print
1007 (or (fboundp 'set-buffer-multibyte)
1008 (defun set-buffer-multibyte (arg)
1009 (setq enable-multibyte-characters arg)))
1010
1011 (or (fboundp 'string-as-unibyte)
1012 (defun string-as-unibyte (arg) arg))
1013
1014 (or (fboundp 'string-as-multibyte)
1015 (defun string-as-multibyte (arg) arg))
1016
1017 (or (fboundp 'charset-after)
1018 (defun charset-after (&optional arg)
1019 (char-charset (char-after arg))))
1020
1021
1022 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1023 ;; User Variables:
1024
1025
1026 ;;; Interface to the command system
1027
1028 (defgroup postscript nil
1029 "PostScript Group"
1030 :tag "PostScript"
1031 :group 'emacs)
1032
1033
1034 (defgroup ebnf2ps nil
1035 "Translate an EBNF to a syntatic chart on PostScript"
1036 :prefix "ebnf-"
1037 :group 'wp
1038 :group 'postscript)
1039
1040
1041 (defgroup ebnf-special nil
1042 "Special customization"
1043 :prefix "ebnf-"
1044 :tag "Special"
1045 :group 'ebnf2ps)
1046
1047
1048 (defgroup ebnf-except nil
1049 "Except customization"
1050 :prefix "ebnf-"
1051 :tag "Except"
1052 :group 'ebnf2ps)
1053
1054
1055 (defgroup ebnf-repeat nil
1056 "Repeat customization"
1057 :prefix "ebnf-"
1058 :tag "Repeat"
1059 :group 'ebnf2ps)
1060
1061
1062 (defgroup ebnf-terminal nil
1063 "Terminal customization"
1064 :prefix "ebnf-"
1065 :tag "Terminal"
1066 :group 'ebnf2ps)
1067
1068
1069 (defgroup ebnf-non-terminal nil
1070 "Non-Terminal customization"
1071 :prefix "ebnf-"
1072 :tag "Non-Terminal"
1073 :group 'ebnf2ps)
1074
1075
1076 (defgroup ebnf-production nil
1077 "Production customization"
1078 :prefix "ebnf-"
1079 :tag "Production"
1080 :group 'ebnf2ps)
1081
1082
1083 (defgroup ebnf-shape nil
1084 "Shapes customization"
1085 :prefix "ebnf-"
1086 :tag "Shape"
1087 :group 'ebnf2ps)
1088
1089
1090 (defgroup ebnf-displacement nil
1091 "Displacement customization"
1092 :prefix "ebnf-"
1093 :tag "Displacement"
1094 :group 'ebnf2ps)
1095
1096
1097 (defgroup ebnf-syntatic nil
1098 "Syntatic customization"
1099 :prefix "ebnf-"
1100 :tag "Syntatic"
1101 :group 'ebnf2ps)
1102
1103
1104 (defgroup ebnf-optimization nil
1105 "Optimization customization"
1106 :prefix "ebnf-"
1107 :tag "Optimization"
1108 :group 'ebnf2ps)
1109
1110
1111 (defcustom ebnf-horizontal-orientation nil
1112 "*Non-nil means productions are drawn horizontally."
1113 :type 'boolean
1114 :group 'ebnf-displacement)
1115
1116
1117 (defcustom ebnf-horizontal-max-height nil
1118 "*Non-nil means to use maximum production height in horizontal orientation.
1119
1120 It is only used when `ebnf-horizontal-orientation' is non-nil."
1121 :type 'boolean
1122 :group 'ebnf-displacement)
1123
1124
1125 (defcustom ebnf-production-horizontal-space 0.0 ; use ebnf2ps default value
1126 "*Specify horizontal space in points between productions.
1127
1128 Value less or equal to zero forces ebnf2ps to set a proper default value."
1129 :type 'number
1130 :group 'ebnf-displacement)
1131
1132
1133 (defcustom ebnf-production-vertical-space 0.0 ; use ebnf2ps default value
1134 "*Specify vertical space in points between productions.
1135
1136 Value less or equal to zero forces ebnf2ps to set a proper default value."
1137 :type 'number
1138 :group 'ebnf-displacement)
1139
1140
1141 (defcustom ebnf-justify-sequence 'center
1142 "*Specify justification of terms in a sequence inside alternatives.
1143
1144 Valid values are:
1145
1146 `left' left justification
1147 `right' right justification
1148 any other value centralize"
1149 :type '(radio :tag "Sequence Justification"
1150 (const left) (const right) (other :tag "center" center))
1151 :group 'ebnf-displacement)
1152
1153
1154 (defcustom ebnf-special-font '(7 Courier "Black" "Gray95" bold italic)
1155 "*Specify special font.
1156
1157 See documentation for `ebnf-production-font'."
1158 :type '(list :tag "Special Font"
1159 (number :tag "Font Size")
1160 (symbol :tag "Font Name")
1161 (choice :tag "Foreground Color"
1162 (string :tag "Name")
1163 (other :tag "Default" nil))
1164 (choice :tag "Background Color"
1165 (string :tag "Name")
1166 (other :tag "Default" nil))
1167 (repeat :tag "Font Attributes" :inline t
1168 (choice (const bold) (const italic)
1169 (const underline) (const strikeout)
1170 (const overline) (const shadow)
1171 (const box) (const outline))))
1172 :group 'ebnf-special)
1173
1174
1175 (defcustom ebnf-special-shape 'bevel
1176 "*Specify special box shape.
1177
1178 See documentation for `ebnf-non-terminal-shape'."
1179 :type '(radio :tag "Special Shape"
1180 (const miter) (const round) (const bevel))
1181 :group 'ebnf-special)
1182
1183
1184 (defcustom ebnf-special-shadow nil
1185 "*Non-nil means special box will have a shadow."
1186 :type 'boolean
1187 :group 'ebnf-special)
1188
1189
1190 (defcustom ebnf-special-border-width 0.5
1191 "*Specify border width for special box."
1192 :type 'number
1193 :group 'ebnf-special)
1194
1195
1196 (defcustom ebnf-special-border-color "Black"
1197 "*Specify border color for special box."
1198 :type 'string
1199 :group 'ebnf-special)
1200
1201
1202 (defcustom ebnf-except-font '(7 Courier "Black" "Gray90" bold italic)
1203 "*Specify except font.
1204
1205 See documentation for `ebnf-production-font'."
1206 :type '(list :tag "Except Font"
1207 (number :tag "Font Size")
1208 (symbol :tag "Font Name")
1209 (choice :tag "Foreground Color"
1210 (string :tag "Name")
1211 (other :tag "Default" nil))
1212 (choice :tag "Background Color"
1213 (string :tag "Name")
1214 (other :tag "Default" nil))
1215 (repeat :tag "Font Attributes" :inline t
1216 (choice (const bold) (const italic)
1217 (const underline) (const strikeout)
1218 (const overline) (const shadow)
1219 (const box) (const outline))))
1220 :group 'ebnf-except)
1221
1222
1223 (defcustom ebnf-except-shape 'bevel
1224 "*Specify except box shape.
1225
1226 See documentation for `ebnf-non-terminal-shape'."
1227 :type '(radio :tag "Except Shape"
1228 (const miter) (const round) (const bevel))
1229 :group 'ebnf-except)
1230
1231
1232 (defcustom ebnf-except-shadow nil
1233 "*Non-nil means except box will have a shadow."
1234 :type 'boolean
1235 :group 'ebnf-except)
1236
1237
1238 (defcustom ebnf-except-border-width 0.25
1239 "*Specify border width for except box."
1240 :type 'number
1241 :group 'ebnf-except)
1242
1243
1244 (defcustom ebnf-except-border-color "Black"
1245 "*Specify border color for except box."
1246 :type 'string
1247 :group 'ebnf-except)
1248
1249
1250 (defcustom ebnf-repeat-font '(7 Courier "Black" "Gray85" bold italic)
1251 "*Specify repeat font.
1252
1253 See documentation for `ebnf-production-font'."
1254 :type '(list :tag "Repeat Font"
1255 (number :tag "Font Size")
1256 (symbol :tag "Font Name")
1257 (choice :tag "Foreground Color"
1258 (string :tag "Name")
1259 (other :tag "Default" nil))
1260 (choice :tag "Background Color"
1261 (string :tag "Name")
1262 (other :tag "Default" nil))
1263 (repeat :tag "Font Attributes" :inline t
1264 (choice (const bold) (const italic)
1265 (const underline) (const strikeout)
1266 (const overline) (const shadow)
1267 (const box) (const outline))))
1268 :group 'ebnf-repeat)
1269
1270
1271 (defcustom ebnf-repeat-shape 'bevel
1272 "*Specify repeat box shape.
1273
1274 See documentation for `ebnf-non-terminal-shape'."
1275 :type '(radio :tag "Repeat Shape"
1276 (const miter) (const round) (const bevel))
1277 :group 'ebnf-repeat)
1278
1279
1280 (defcustom ebnf-repeat-shadow nil
1281 "*Non-nil means repeat box will have a shadow."
1282 :type 'boolean
1283 :group 'ebnf-repeat)
1284
1285
1286 (defcustom ebnf-repeat-border-width 0.0
1287 "*Specify border width for repeat box."
1288 :type 'number
1289 :group 'ebnf-repeat)
1290
1291
1292 (defcustom ebnf-repeat-border-color "Black"
1293 "*Specify border color for repeat box."
1294 :type 'string
1295 :group 'ebnf-repeat)
1296
1297
1298 (defcustom ebnf-terminal-font '(7 Courier "Black" "White")
1299 "*Specify terminal font.
1300
1301 See documentation for `ebnf-production-font'."
1302 :type '(list :tag "Terminal Font"
1303 (number :tag "Font Size")
1304 (symbol :tag "Font Name")
1305 (choice :tag "Foreground Color"
1306 (string :tag "Name")
1307 (other :tag "Default" nil))
1308 (choice :tag "Background Color"
1309 (string :tag "Name")
1310 (other :tag "Default" nil))
1311 (repeat :tag "Font Attributes" :inline t
1312 (choice (const bold) (const italic)
1313 (const underline) (const strikeout)
1314 (const overline) (const shadow)
1315 (const box) (const outline))))
1316 :group 'ebnf-terminal)
1317
1318
1319 (defcustom ebnf-terminal-shape 'miter
1320 "*Specify terminal box shape.
1321
1322 See documentation for `ebnf-non-terminal-shape'."
1323 :type '(radio :tag "Terminal Shape"
1324 (const miter) (const round) (const bevel))
1325 :group 'ebnf-terminal)
1326
1327
1328 (defcustom ebnf-terminal-shadow nil
1329 "*Non-nil means terminal box will have a shadow."
1330 :type 'boolean
1331 :group 'ebnf-terminal)
1332
1333
1334 (defcustom ebnf-terminal-border-width 1.0
1335 "*Specify border width for terminal box."
1336 :type 'number
1337 :group 'ebnf-terminal)
1338
1339
1340 (defcustom ebnf-terminal-border-color "Black"
1341 "*Specify border color for terminal box."
1342 :type 'string
1343 :group 'ebnf-terminal)
1344
1345
1346 (defcustom ebnf-sort-production nil
1347 "*Specify how productions are sorted.
1348
1349 Valid values are:
1350
1351 nil don't sort productions.
1352 `ascending' ascending sort.
1353 any other value descending sort."
1354 :type '(radio :tag "Production Sort"
1355 (const :tag "Ascending" ascending)
1356 (const :tag "Descending" descending)
1357 (other :tag "No Sort" nil))
1358 :group 'ebnf-production)
1359
1360
1361 (defcustom ebnf-production-font '(10 Helvetica "Black" "White" bold)
1362 "*Specify production header font.
1363
1364 It is a list with the following form:
1365
1366 (SIZE NAME FOREGROUND BACKGROUND ATTRIBUTE...)
1367
1368 Where:
1369 SIZE is the font size.
1370 NAME is the font name symbol.
1371 ATTRIBUTE is one of the following symbols:
1372 bold - use bold font.
1373 italic - use italic font.
1374 underline - put a line under text.
1375 strikeout - like underline, but the line is in middle of text.
1376 overline - like underline, but the line is over the text.
1377 shadow - text will have a shadow.
1378 box - text will be surrounded by a box.
1379 outline - print characters as hollow outlines.
1380 FOREGROUND is a foreground string color name; if it's nil, the default color is
1381 \"Black\".
1382 BACKGROUND is a background string color name; if it's nil, the default color is
1383 \"White\".
1384
1385 See `ps-font-info-database' for valid font name."
1386 :type '(list :tag "Production Font"
1387 (number :tag "Font Size")
1388 (symbol :tag "Font Name")
1389 (choice :tag "Foreground Color"
1390 (string :tag "Name")
1391 (other :tag "Default" nil))
1392 (choice :tag "Background Color"
1393 (string :tag "Name")
1394 (other :tag "Default" nil))
1395 (repeat :tag "Font Attributes" :inline t
1396 (choice (const bold) (const italic)
1397 (const underline) (const strikeout)
1398 (const overline) (const shadow)
1399 (const box) (const outline))))
1400 :group 'ebnf-production)
1401
1402
1403 (defcustom ebnf-non-terminal-font '(7 Helvetica "Black" "White")
1404 "*Specify non-terminal font.
1405
1406 See documentation for `ebnf-production-font'."
1407 :type '(list :tag "Non-Terminal Font"
1408 (number :tag "Font Size")
1409 (symbol :tag "Font Name")
1410 (choice :tag "Foreground Color"
1411 (string :tag "Name")
1412 (other :tag "Default" nil))
1413 (choice :tag "Background Color"
1414 (string :tag "Name")
1415 (other :tag "Default" nil))
1416 (repeat :tag "Font Attributes" :inline t
1417 (choice (const bold) (const italic)
1418 (const underline) (const strikeout)
1419 (const overline) (const shadow)
1420 (const box) (const outline))))
1421 :group 'ebnf-non-terminal)
1422
1423
1424 (defcustom ebnf-non-terminal-shape 'round
1425 "*Specify non-terminal box shape.
1426
1427 Valid values are:
1428
1429 `miter' +-------+
1430 | |
1431 +-------+
1432
1433 `round' -------
1434 ( )
1435 -------
1436
1437 `bevel' /-------\\
1438 | |
1439 \\-------/
1440
1441 Any other value is treated as `miter'."
1442 :type '(radio :tag "Non-Terminal Shape"
1443 (const miter) (const round) (const bevel))
1444 :group 'ebnf-non-terminal)
1445
1446
1447 (defcustom ebnf-non-terminal-shadow nil
1448 "*Non-nil means non-terminal box will have a shadow."
1449 :type 'boolean
1450 :group 'ebnf-non-terminal)
1451
1452
1453 (defcustom ebnf-non-terminal-border-width 1.0
1454 "*Specify border width for non-terminal box."
1455 :type 'number
1456 :group 'ebnf-non-terminal)
1457
1458
1459 (defcustom ebnf-non-terminal-border-color "Black"
1460 "*Specify border color for non-terminal box."
1461 :type 'string
1462 :group 'ebnf-non-terminal)
1463
1464
1465 (defcustom ebnf-arrow-shape 'hollow
1466 "*Specify the arrow shape.
1467
1468 Valid values are:
1469
1470 `none' ======
1471
1472 `semi-up' * `transparent' *
1473 * |*
1474 =====* | *
1475 ==+==*
1476 | *
1477 |*
1478 *
1479
1480 `semi-down' =====* `hollow' *
1481 * |*
1482 * | *
1483 ==+ *
1484 | *
1485 |*
1486 *
1487
1488 `simple' * `full' *
1489 * |*
1490 =====* |X*
1491 * ==+XX*
1492 * |X*
1493 |*
1494 *
1495
1496 `user' See also documentation for variable `ebnf-user-arrow'.
1497
1498 Any other value is treated as `none'."
1499 :type '(radio :tag "Arrow Shape"
1500 (const none) (const semi-up)
1501 (const semi-down) (const simple)
1502 (const transparent) (const hollow)
1503 (const full) (const user))
1504 :group 'ebnf-shape)
1505
1506
1507 (defcustom ebnf-chart-shape 'round
1508 "*Specify chart flow shape.
1509
1510 See documentation for `ebnf-non-terminal-shape'."
1511 :type '(radio :tag "Chart Flow Shape"
1512 (const miter) (const round) (const bevel))
1513 :group 'ebnf-shape)
1514
1515
1516 (defcustom ebnf-user-arrow nil
1517 "*Specify a user arrow shape (a PostScript code).
1518
1519 PostScript code should draw a right arrow.
1520
1521 The anatomy of a right arrow is:
1522
1523 ...... Initial position
1524 :
1525 : *.................
1526 : | * } }
1527 : | * } hT4 }
1528 v | * } }
1529 ======+======*... } hT2
1530 : | *: } }
1531 : | * : } hT4 }
1532 : | * : } }
1533 : *.................
1534 : : :
1535 : : :..........
1536 : : } hT2 }
1537 : :.......... } hT
1538 : } hT2 }
1539 :.......................
1540
1541 Where `hT', `hT2' and `hT4' are predefined PostScript variable names that can be
1542 used to generate your own arrow. As these variables are used along PostScript
1543 execution, *DON'T* modify the values of them. Instead, copy the values, if you
1544 need to modify them.
1545
1546 The relation between these variables is: hT = 2 * hT2 = 4 * hT4.
1547
1548 The variable `ebnf-user-arrow' is only used when `ebnf-arrow-shape' is set to
1549 symbol `user'.
1550
1551 See function `ebnf-user-arrow' for valid values and how values are processed."
1552 :type '(radio :tag "User Arrow Shape"
1553 (const nil)
1554 string
1555 symbol
1556 (repeat :tag "List"
1557 (radio string
1558 symbol
1559 sexp)))
1560 :group 'ebnf-shape)
1561
1562
1563 (defcustom ebnf-syntax 'ebnf
1564 "*Specify syntax to be recognized.
1565
1566 Valid values are:
1567
1568 `ebnf' ebnf2ps recognizes the syntax described above.
1569 The following variables *ONLY* have effect with this
1570 setting:
1571 `ebnf-terminal-regexp', `ebnf-case-fold-search',
1572 `ebnf-lex-comment-char' and `ebnf-lex-eop-char'.
1573
1574 `iso-ebnf' ebnf2ps recognizes the syntax described in the URL:
1575 `http://www.cl.cam.ac.uk/~mgk25/iso-ebnf.html'
1576 (\"International Standard of the ISO EBNF Notation\").
1577 The following variables *ONLY* have effect with this
1578 setting:
1579 `ebnf-iso-alternative-p' and `ebnf-iso-normalize-p'.
1580
1581 `yacc' ebnf2ps recognizes the Yacc/Bison syntax.
1582 The following variable *ONLY* has effect with this
1583 setting:
1584 `ebnf-yac-ignore-error-recovery'.
1585
1586 Any other value is treated as `ebnf'."
1587 :type '(radio :tag "Syntax"
1588 (const ebnf) (const iso-ebnf) (const yacc))
1589 :group 'ebnf-syntatic)
1590
1591
1592 (defcustom ebnf-lex-comment-char ?\;
1593 "*Specify the line comment character.
1594
1595 It's used only when `ebnf-syntax' is `ebnf'."
1596 :type 'character
1597 :group 'ebnf-syntatic)
1598
1599
1600 (defcustom ebnf-lex-eop-char ?.
1601 "*Specify the end of production character.
1602
1603 It's used only when `ebnf-syntax' is `ebnf'."
1604 :type 'character
1605 :group 'ebnf-syntatic)
1606
1607
1608 (defcustom ebnf-terminal-regexp nil
1609 "*Specify how it's a terminal name.
1610
1611 If it's nil, the terminal name must be enclosed by `\"'.
1612 If it's a string, it should be a regexp that it'll be used to determine a
1613 terminal name; terminal name may also be enclosed by `\"'.
1614
1615 It's used only when `ebnf-syntax' is `ebnf'."
1616 :type '(radio :tag "Terminal Name"
1617 (const nil) regexp)
1618 :group 'ebnf-syntatic)
1619
1620
1621 (defcustom ebnf-case-fold-search nil
1622 "*Non-nil means ignore case on matching.
1623
1624 It's only used when `ebnf-terminal-regexp' is non-nil and when `ebnf-syntax' is
1625 `ebnf'."
1626 :type 'boolean
1627 :group 'ebnf-syntatic)
1628
1629
1630 (defcustom ebnf-iso-alternative-p nil
1631 "*Non-nil means use alternative ISO EBNF.
1632
1633 It's only used when `ebnf-syntax' is `iso-ebnf'.
1634
1635 This variable affects the following symbol set:
1636
1637 STANDARD ALTERNATIVE
1638 | ==> / or !
1639 [ ==> (/
1640 ] ==> /)
1641 { ==> (:
1642 } ==> :)
1643 ; ==> ."
1644 :type 'boolean
1645 :group 'ebnf-syntatic)
1646
1647
1648 (defcustom ebnf-iso-normalize-p nil
1649 "*Non-nil means normalize ISO EBNF syntax names.
1650
1651 Normalize a name means that several contiguous spaces inside name become a
1652 single space, so \"A B C\" is normalized to \"A B C\".
1653
1654 It's only used when `ebnf-syntax' is `iso-ebnf'."
1655 :type 'boolean
1656 :group 'ebnf-syntatic)
1657
1658
1659 (defcustom ebnf-eps-prefix "ebnf--"
1660 "*Specify EPS prefix file name.
1661
1662 See `ebnf-eps-buffer' and `ebnf-eps-region' commands."
1663 :type 'string
1664 :group 'ebnf2ps)
1665
1666
1667 (defcustom ebnf-entry-percentage 0.5 ; middle
1668 "*Specify entry height on alternatives.
1669
1670 It must be a float between 0.0 (top) and 1.0 (bottom)."
1671 :type 'number
1672 :group 'ebnf2ps)
1673
1674
1675 (defcustom ebnf-default-width 0.6
1676 "*Specify additional border width over default terminal, non-terminal or
1677 special."
1678 :type 'number
1679 :group 'ebnf2ps)
1680
1681
1682 ;; Printing color requires x-color-values.
1683 (defcustom ebnf-color-p (or (fboundp 'x-color-values) ; Emacs
1684 (fboundp 'color-instance-rgb-components)) ; XEmacs
1685 "*Non-nil means use color."
1686 :type 'boolean
1687 :group 'ebnf2ps)
1688
1689
1690 (defcustom ebnf-line-width 1.0
1691 "*Specify flow line width."
1692 :type 'number
1693 :group 'ebnf2ps)
1694
1695
1696 (defcustom ebnf-line-color "Black"
1697 "*Specify flow line color."
1698 :type 'string
1699 :group 'ebnf2ps)
1700
1701
1702 (defcustom ebnf-debug-ps nil
1703 "*Non-nil means to generate PostScript debug procedures.
1704
1705 It is intended to help PostScript programmers in debugging."
1706 :type 'boolean
1707 :group 'ebnf2ps)
1708
1709
1710 (defcustom ebnf-use-float-format t
1711 "*Non-nil means use `%f' float format.
1712
1713 The advantage of using float format is that ebnf2ps generates a little short
1714 PostScript file.
1715
1716 If it occurs the error message:
1717
1718 Invalid format operation %f
1719
1720 when executing ebnf2ps, set `ebnf-use-float-format' to nil."
1721 :type 'boolean
1722 :group 'ebnf2ps)
1723
1724
1725 (defcustom ebnf-yac-ignore-error-recovery nil
1726 "*Non-nil means ignore error recovery.
1727
1728 It's only used when `ebnf-syntax' is `yacc'."
1729 :type 'boolean
1730 :group 'ebnf-syntatic)
1731
1732
1733 (defcustom ebnf-ignore-empty-rule nil
1734 "*Non-nil means ignore empty rules.
1735
1736 It's interesting to set this variable if your Yacc/Bison grammar has a lot of
1737 middle action rule."
1738 :type 'boolean
1739 :group 'ebnf-optimization)
1740
1741
1742 (defcustom ebnf-optimize nil
1743 "*Non-nil means optimize syntatic chart of rules.
1744
1745 The following optimizations are done:
1746
1747 left recursion:
1748 1. A = B | A C. ==> A = B {C}*.
1749 2. A = B | A B. ==> A = {B}+.
1750 3. A = | A B. ==> A = {B}*.
1751 4. A = B | A C B. ==> A = {B || C}+.
1752 5. A = B | D | A C | A E. ==> A = ( B | D ) { C | E }*.
1753
1754 optional:
1755 6. A = B | . ==> A = [B].
1756 7. A = | B . ==> A = [B].
1757
1758 factoration:
1759 8. A = B C | B D. ==> A = B (C | D).
1760 9. A = C B | D B. ==> A = (C | D) B.
1761 10. A = B C E | B D E. ==> A = B (C | D) E.
1762
1763 The above optimizations are specially useful when `ebnf-syntax' is `yacc'."
1764 :type 'boolean
1765 :group 'ebnf-optimization)
1766
1767
1768 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1769 ;; Customization
1770
1771
1772 ;;;###autoload
1773 (defun ebnf-customize ()
1774 "Customization for ebnf group."
1775 (interactive)
1776 (customize-group 'ebnf2ps))
1777
1778
1779 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1780 ;; User commands
1781
1782
1783 ;;;###autoload
1784 (defun ebnf-print-buffer (&optional filename)
1785 "Generate and print a PostScript syntatic chart image of the buffer.
1786
1787 When called with a numeric prefix argument (C-u), prompts the user for
1788 the name of a file to save the PostScript image in, instead of sending
1789 it to the printer.
1790
1791 More specifically, the FILENAME argument is treated as follows: if it
1792 is nil, send the image to the printer. If FILENAME is a string, save
1793 the PostScript image in a file with that name. If FILENAME is a
1794 number, prompt the user for the name of the file to save in."
1795 (interactive (list (ps-print-preprint current-prefix-arg)))
1796 (ebnf-print-region (point-min) (point-max) filename))
1797
1798
1799 ;;;###autoload
1800 (defun ebnf-print-region (from to &optional filename)
1801 "Generate and print a PostScript syntatic chart image of the region.
1802 Like `ebnf-print-buffer', but prints just the current region."
1803 (interactive (list (point) (mark) (ps-print-preprint current-prefix-arg)))
1804 (run-hooks 'ebnf-hook)
1805 (or (ebnf-spool-region from to)
1806 (ps-do-despool filename)))
1807
1808
1809 ;;;###autoload
1810 (defun ebnf-spool-buffer ()
1811 "Generate and spool a PostScript syntatic chart image of the buffer.
1812 Like `ebnf-print-buffer' except that the PostScript image is saved in a
1813 local buffer to be sent to the printer later.
1814
1815 Use the command `ebnf-despool' to send the spooled images to the printer."
1816 (interactive)
1817 (ebnf-spool-region (point-min) (point-max)))
1818
1819
1820 ;;;###autoload
1821 (defun ebnf-spool-region (from to)
1822 "Generate a PostScript syntatic chart image of the region and spool locally.
1823 Like `ebnf-spool-buffer', but spools just the current region.
1824
1825 Use the command `ebnf-despool' to send the spooled images to the printer."
1826 (interactive "r")
1827 (ebnf-generate-region from to 'ebnf-generate))
1828
1829
1830 ;;;###autoload
1831 (defun ebnf-eps-buffer ()
1832 "Generate a PostScript syntatic chart image of the buffer in a EPS file.
1833
1834 Indeed, for each production is generated a EPS file.
1835 The EPS file name has the following form:
1836
1837 <PREFIX><PRODUCTION>.eps
1838
1839 <PREFIX> is given by variable `ebnf-eps-prefix'.
1840 The default value is \"ebnf--\".
1841
1842 <PRODUCTION> is the production name.
1843 The production name is mapped to form a valid file name.
1844 For example, the production name \"A/B + C\" is mapped to
1845 \"A_B_+_C\" and the EPS file name used is \"ebnf--A_B_+_C.eps\".
1846
1847 WARNING: It's *NOT* asked any confirmation to override an existing file."
1848 (interactive)
1849 (ebnf-eps-region (point-min) (point-max)))
1850
1851
1852 ;;;###autoload
1853 (defun ebnf-eps-region (from to)
1854 "Generate a PostScript syntatic chart image of the region in a EPS file.
1855
1856 Indeed, for each production is generated a EPS file.
1857 The EPS file name has the following form:
1858
1859 <PREFIX><PRODUCTION>.eps
1860
1861 <PREFIX> is given by variable `ebnf-eps-prefix'.
1862 The default value is \"ebnf--\".
1863
1864 <PRODUCTION> is the production name.
1865 The production name is mapped to form a valid file name.
1866 For example, the production name \"A/B + C\" is mapped to
1867 \"A_B_+_C\" and the EPS file name used is \"ebnf--A_B_+_C.eps\".
1868
1869 WARNING: It's *NOT* asked any confirmation to override an existing file."
1870 (interactive "r")
1871 (let ((ebnf-eps-executing t))
1872 (ebnf-generate-region from to 'ebnf-generate-eps)))
1873
1874
1875 ;;;###autoload
1876 (defalias 'ebnf-despool 'ps-despool)
1877
1878
1879 ;;;###autoload
1880 (defun ebnf-syntax-buffer ()
1881 "Does a syntatic analysis of the current buffer."
1882 (interactive)
1883 (ebnf-syntax-region (point-min) (point-max)))
1884
1885
1886 ;;;###autoload
1887 (defun ebnf-syntax-region (from to)
1888 "Does a syntatic analysis of a region."
1889 (interactive "r")
1890 (ebnf-generate-region from to nil))
1891
1892
1893 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1894 ;; Utilities
1895
1896
1897 ;;;###autoload
1898 (defun ebnf-setup ()
1899 "Return the current ebnf2ps setup."
1900 (format
1901 "
1902 \(setq ebnf-special-font %s
1903 ebnf-special-shape %s
1904 ebnf-special-shadow %S
1905 ebnf-special-border-width %S
1906 ebnf-special-border-color %S
1907 ebnf-except-font %s
1908 ebnf-except-shape %s
1909 ebnf-except-shadow %S
1910 ebnf-except-border-width %S
1911 ebnf-except-border-color %S
1912 ebnf-repeat-font %s
1913 ebnf-repeat-shape %s
1914 ebnf-repeat-shadow %S
1915 ebnf-repeat-border-width %S
1916 ebnf-repeat-border-color %S
1917 ebnf-terminal-regexp %S
1918 ebnf-case-fold-search %S
1919 ebnf-terminal-font %s
1920 ebnf-terminal-shape %s
1921 ebnf-terminal-shadow %S
1922 ebnf-terminal-border-width %S
1923 ebnf-terminal-border-color %S
1924 ebnf-non-terminal-font %s
1925 ebnf-non-terminal-shape %s
1926 ebnf-non-terminal-shadow %S
1927 ebnf-non-terminal-border-width %S
1928 ebnf-non-terminal-border-color %S
1929 ebnf-sort-production %s
1930 ebnf-production-font %s
1931 ebnf-arrow-shape %s
1932 ebnf-chart-shape %s
1933 ebnf-user-arrow %s
1934 ebnf-horizontal-orientation %S
1935 ebnf-horizontal-max-height %S
1936 ebnf-production-horizontal-space %S
1937 ebnf-production-vertical-space %S
1938 ebnf-justify-sequence %s
1939 ebnf-lex-comment-char ?\\%03o
1940 ebnf-lex-eop-char ?\\%03o
1941 ebnf-syntax %s
1942 ebnf-iso-alternative-p %S
1943 ebnf-iso-normalize-p %S
1944 ebnf-eps-prefix %S
1945 ebnf-entry-percentage %S
1946 ebnf-color-p %S
1947 ebnf-line-width %S
1948 ebnf-line-color %S
1949 ebnf-debug-ps %S
1950 ebnf-use-float-format %S
1951 ebnf-yac-ignore-error-recovery %S
1952 ebnf-ignore-empty-rule %S
1953 ebnf-optimize %S)
1954 "
1955 (ps-print-quote ebnf-special-font)
1956 (ps-print-quote ebnf-special-shape)
1957 ebnf-special-shadow
1958 ebnf-special-border-width
1959 ebnf-special-border-color
1960 (ps-print-quote ebnf-except-font)
1961 (ps-print-quote ebnf-except-shape)
1962 ebnf-except-shadow
1963 ebnf-except-border-width
1964 ebnf-except-border-color
1965 (ps-print-quote ebnf-repeat-font)
1966 (ps-print-quote ebnf-repeat-shape)
1967 ebnf-repeat-shadow
1968 ebnf-repeat-border-width
1969 ebnf-repeat-border-color
1970 ebnf-terminal-regexp
1971 ebnf-case-fold-search
1972 (ps-print-quote ebnf-terminal-font)
1973 (ps-print-quote ebnf-terminal-shape)
1974 ebnf-terminal-shadow
1975 ebnf-terminal-border-width
1976 ebnf-terminal-border-color
1977 (ps-print-quote ebnf-non-terminal-font)
1978 (ps-print-quote ebnf-non-terminal-shape)
1979 ebnf-non-terminal-shadow
1980 ebnf-non-terminal-border-width
1981 ebnf-non-terminal-border-color
1982 (ps-print-quote ebnf-sort-production)
1983 (ps-print-quote ebnf-production-font)
1984 (ps-print-quote ebnf-arrow-shape)
1985 (ps-print-quote ebnf-chart-shape)
1986 (ps-print-quote ebnf-user-arrow)
1987 ebnf-horizontal-orientation
1988 ebnf-horizontal-max-height
1989 ebnf-production-horizontal-space
1990 ebnf-production-vertical-space
1991 (ps-print-quote ebnf-justify-sequence)
1992 ebnf-lex-comment-char
1993 ebnf-lex-eop-char
1994 (ps-print-quote ebnf-syntax)
1995 ebnf-iso-alternative-p
1996 ebnf-iso-normalize-p
1997 ebnf-eps-prefix
1998 ebnf-entry-percentage
1999 ebnf-color-p
2000 ebnf-line-width
2001 ebnf-line-color
2002 ebnf-debug-ps
2003 ebnf-use-float-format
2004 ebnf-yac-ignore-error-recovery
2005 ebnf-ignore-empty-rule
2006 ebnf-optimize))
2007
2008
2009 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2010 ;; Style variables
2011
2012
2013 (defvar ebnf-stack-style nil
2014 "Used in functions `ebnf-reset-style', `ebnf-push-style' and
2015 `ebnf-pop-style'.")
2016
2017
2018 (defvar ebnf-current-style 'default
2019 "Used in functions `ebnf-apply-style' and `ebnf-push-style'.")
2020
2021
2022 (defconst ebnf-style-custom-list
2023 '(ebnf-special-font
2024 ebnf-special-shape
2025 ebnf-special-shadow
2026 ebnf-special-border-width
2027 ebnf-special-border-color
2028 ebnf-except-font
2029 ebnf-except-shape
2030 ebnf-except-shadow
2031 ebnf-except-border-width
2032 ebnf-except-border-color
2033 ebnf-repeat-font
2034 ebnf-repeat-shape
2035 ebnf-repeat-shadow
2036 ebnf-repeat-border-width
2037 ebnf-repeat-border-color
2038 ebnf-terminal-regexp
2039 ebnf-case-fold-search
2040 ebnf-terminal-font
2041 ebnf-terminal-shape
2042 ebnf-terminal-shadow
2043 ebnf-terminal-border-width
2044 ebnf-terminal-border-color
2045 ebnf-non-terminal-font
2046 ebnf-non-terminal-shape
2047 ebnf-non-terminal-shadow
2048 ebnf-non-terminal-border-width
2049 ebnf-non-terminal-border-color
2050 ebnf-sort-production
2051 ebnf-production-font
2052 ebnf-arrow-shape
2053 ebnf-chart-shape
2054 ebnf-user-arrow
2055 ebnf-horizontal-orientation
2056 ebnf-horizontal-max-height
2057 ebnf-production-horizontal-space
2058 ebnf-production-vertical-space
2059 ebnf-justify-sequence
2060 ebnf-lex-comment-char
2061 ebnf-lex-eop-char
2062 ebnf-syntax
2063 ebnf-iso-alternative-p
2064 ebnf-iso-normalize-p
2065 ebnf-eps-prefix
2066 ebnf-entry-percentage
2067 ebnf-color-p
2068 ebnf-line-width
2069 ebnf-line-color
2070 ebnf-debug-ps
2071 ebnf-use-float-format
2072 ebnf-yac-ignore-error-recovery
2073 ebnf-ignore-empty-rule
2074 ebnf-optimize)
2075 "List of valid symbol custom variable.")
2076
2077
2078 (defvar ebnf-style-database
2079 '(;; EBNF default
2080 (default
2081 nil
2082 (ebnf-special-font . '(7 Courier "Black" "Gray95" bold italic))
2083 (ebnf-special-shape . 'bevel)
2084 (ebnf-special-shadow . nil)
2085 (ebnf-special-border-width . 0.5)
2086 (ebnf-special-border-color . "Black")
2087 (ebnf-except-font . '(7 Courier "Black" "Gray90" bold italic))
2088 (ebnf-except-shape . 'bevel)
2089 (ebnf-except-shadow . nil)
2090 (ebnf-except-border-width . 0.25)
2091 (ebnf-except-border-color . "Black")
2092 (ebnf-repeat-font . '(7 Courier "Black" "Gray85" bold italic))
2093 (ebnf-repeat-shape . 'bevel)
2094 (ebnf-repeat-shadow . nil)
2095 (ebnf-repeat-border-width . 0.0)
2096 (ebnf-repeat-border-color . "Black")
2097 (ebnf-terminal-regexp . nil)
2098 (ebnf-case-fold-search . nil)
2099 (ebnf-terminal-font . '(7 Courier "Black" "White"))
2100 (ebnf-terminal-shape . 'miter)
2101 (ebnf-terminal-shadow . nil)
2102 (ebnf-terminal-border-width . 1.0)
2103 (ebnf-terminal-border-color . "Black")
2104 (ebnf-non-terminal-font . '(7 Helvetica "Black" "White"))
2105 (ebnf-non-terminal-shape . 'round)
2106 (ebnf-non-terminal-shadow . nil)
2107 (ebnf-non-terminal-border-width . 1.0)
2108 (ebnf-non-terminal-border-color . "Black")
2109 (ebnf-sort-production . nil)
2110 (ebnf-production-font . '(10 Helvetica "Black" "White" bold))
2111 (ebnf-arrow-shape . 'hollow)
2112 (ebnf-chart-shape . 'round)
2113 (ebnf-user-arrow . nil)
2114 (ebnf-horizontal-orientation . nil)
2115 (ebnf-horizontal-max-height . nil)
2116 (ebnf-production-horizontal-space . 0.0)
2117 (ebnf-production-vertical-space . 0.0)
2118 (ebnf-justify-sequence . 'center)
2119 (ebnf-lex-comment-char . ?\;)
2120 (ebnf-lex-eop-char . ?.)
2121 (ebnf-syntax . 'ebnf)
2122 (ebnf-iso-alternative-p . nil)
2123 (ebnf-iso-normalize-p . nil)
2124 (ebnf-eps-prefix . "ebnf--")
2125 (ebnf-entry-percentage . 0.5)
2126 (ebnf-color-p . (or (fboundp 'x-color-values) ; Emacs
2127 (fboundp 'color-instance-rgb-components))) ; XEmacs
2128 (ebnf-line-width . 1.0)
2129 (ebnf-line-color . "Black")
2130 (ebnf-debug-ps . nil)
2131 (ebnf-use-float-format . t)
2132 (ebnf-yac-ignore-error-recovery . nil)
2133 (ebnf-ignore-empty-rule . nil)
2134 (ebnf-optimize . nil))
2135 ;; Happy EBNF default
2136 (happy
2137 default
2138 (ebnf-justify-sequence . 'left)
2139 (ebnf-lex-comment-char . ?\#)
2140 (ebnf-lex-eop-char . ?\;))
2141 ;; ISO EBNF default
2142 (iso-ebnf
2143 default
2144 (ebnf-syntax . 'iso-ebnf))
2145 ;; Yacc/Bison default
2146 (yacc
2147 default
2148 (ebnf-syntax . 'yacc))
2149 )
2150 "Style database.
2151
2152 Each element has the following form:
2153
2154 (CUSTOM INHERITS (VAR . VALUE)...)
2155
2156 CUSTOM is a symbol name style.
2157 INHERITS is a symbol name style from which the current style inherits the
2158 context. If INHERITS is nil, means that there is no inheritance.
2159 VAR is a valid ebnf2ps symbol custom variable. See `ebnf-style-custom-list' for
2160 valid symbol variable.
2161 VALUE is a sexp which it'll be evaluated to set the value to VAR. So, don't
2162 forget to quote symbols and constant lists. See `default' style for an
2163 example.
2164
2165 Don't handle this variable directly. Use functions `ebnf-insert-style' and
2166 `ebnf-merge-style'.")
2167
2168
2169 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2170 ;; Style commands
2171
2172
2173 ;;;###autoload
2174 (defun ebnf-insert-style (name inherits &rest values)
2175 "Insert a new style NAME with inheritance INHERITS and values VALUES."
2176 (interactive)
2177 (and (assoc name ebnf-style-database)
2178 (error "Style name already exists: %s" name))
2179 (or (assoc inherits ebnf-style-database)
2180 (error "Style inheritance name does'nt exist: %s" inherits))
2181 (setq ebnf-style-database
2182 (cons (cons name (cons inherits (ebnf-check-style-values values)))
2183 ebnf-style-database)))
2184
2185
2186 ;;;###autoload
2187 (defun ebnf-merge-style (name &rest values)
2188 "Merge values of style NAME with style VALUES."
2189 (interactive)
2190 (let ((style (or (assoc name ebnf-style-database)
2191 (error "Style name does'nt exist: %s" name)))
2192 (merge (ebnf-check-style-values values))
2193 val elt new check)
2194 ;; modify value of existing variables
2195 (setq val (nthcdr 2 style))
2196 (while merge
2197 (setq check (car merge)
2198 merge (cdr merge)
2199 elt (assoc (car check) val))
2200 (if elt
2201 (setcdr elt (cdr check))
2202 (setq new (cons check new))))
2203 ;; insert new variables
2204 (nconc style (nreverse new))))
2205
2206
2207 ;;;###autoload
2208 (defun ebnf-apply-style (style)
2209 "Set STYLE to current style.
2210
2211 It returns the old style symbol."
2212 (interactive)
2213 (prog1
2214 ebnf-current-style
2215 (and (ebnf-apply-style1 style)
2216 (setq ebnf-current-style style))))
2217
2218
2219 ;;;###autoload
2220 (defun ebnf-reset-style (&optional style)
2221 "Reset current style.
2222
2223 It returns the old style symbol."
2224 (interactive)
2225 (setq ebnf-stack-style nil)
2226 (ebnf-apply-style (or style 'default)))
2227
2228
2229 ;;;###autoload
2230 (defun ebnf-push-style (&optional style)
2231 "Push the current style and set STYLE to current style.
2232
2233 It returns the old style symbol."
2234 (interactive)
2235 (prog1
2236 ebnf-current-style
2237 (setq ebnf-stack-style (cons ebnf-current-style ebnf-stack-style))
2238 (and style
2239 (ebnf-apply-style style))))
2240
2241
2242 ;;;###autoload
2243 (defun ebnf-pop-style ()
2244 "Pop a style and set it to current style.
2245
2246 It returns the old style symbol."
2247 (interactive)
2248 (prog1
2249 (ebnf-apply-style (car ebnf-stack-style))
2250 (setq ebnf-stack-style (cdr ebnf-stack-style))))
2251
2252
2253 (defun ebnf-apply-style1 (style)
2254 (let ((value (cdr (assoc style ebnf-style-database))))
2255 (prog1
2256 value
2257 (and (car value) (ebnf-apply-style1 (car value)))
2258 (while (setq value (cdr value))
2259 (set (caar value) (eval (cdar value)))))))
2260
2261
2262 (defun ebnf-check-style-values (values)
2263 (let (style)
2264 (while values
2265 (and (memq (car values) ebnf-style-custom-list)
2266 (setq style (cons (car values) style)))
2267 (setq values (cdr values)))
2268 (nreverse style)))
2269
2270
2271 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2272 ;; Internal variables
2273
2274
2275 (make-local-hook 'ebnf-hook)
2276 (make-local-hook 'ebnf-production-hook)
2277 (make-local-hook 'ebnf-page-hook)
2278
2279
2280 (defvar ebnf-eps-buffer-name " *EPS*")
2281 (defvar ebnf-parser-func nil)
2282 (defvar ebnf-eps-executing nil)
2283 (defvar ebnf-eps-upper-x 0.0)
2284 (make-variable-buffer-local 'ebnf-eps-upper-x)
2285 (defvar ebnf-eps-upper-y 0.0)
2286 (make-variable-buffer-local 'ebnf-eps-upper-y)
2287 (defvar ebnf-eps-prod-width 0.0)
2288 (make-variable-buffer-local 'ebnf-eps-prod-width)
2289 (defvar ebnf-eps-max-height 0.0)
2290 (make-variable-buffer-local 'ebnf-eps-max-height)
2291 (defvar ebnf-eps-max-width 0.0)
2292 (make-variable-buffer-local 'ebnf-eps-max-width)
2293
2294
2295 (defvar ebnf-eps-context nil
2296 "List of EPS file name during parsing.
2297
2298 See section \"Actions in Comments\" in ebnf2ps documentation.")
2299
2300
2301 (defvar ebnf-eps-production-list nil
2302 "Alist associating production name with EPS file name list.
2303
2304 Each element has the following form:
2305
2306 (PRODUCTION EPS-FILENAME...)
2307
2308 PRODUCTION is the production name.
2309 EPS-FILENAME is the EPS file name.
2310
2311 It's generated during parsing and used during EPS generation.
2312
2313 See `ebnf-eps-context' and section \"Actions in Comments\" in ebnf2ps
2314 documentation.")
2315
2316
2317 (defconst ebnf-arrow-shape-alist
2318 '((none . 0)
2319 (semi-up . 1)
2320 (semi-down . 2)
2321 (simple . 3)
2322 (transparent . 4)
2323 (hollow . 5)
2324 (full . 6)
2325 (user . 7))
2326 "Alist associating values for `ebnf-arrow-shape'.
2327
2328 See documentation for `ebnf-arrow-shape'.")
2329
2330
2331 (defconst ebnf-terminal-shape-alist
2332 '((miter . 0)
2333 (round . 1)
2334 (bevel . 2))
2335 "Alist associating values from `ebnf-terminal-shape' to a bit vector.
2336
2337 See documentation for `ebnf-terminal-shape', `ebnf-non-terminal-shape' and
2338 `ebnf-chart-shape'.")
2339
2340
2341 (defvar ebnf-limit nil)
2342 (defvar ebnf-action nil)
2343 (defvar ebnf-action-list nil)
2344
2345
2346 (defvar ebnf-default-p nil)
2347
2348
2349 (defvar ebnf-font-height-P 0)
2350 (defvar ebnf-font-height-T 0)
2351 (defvar ebnf-font-height-NT 0)
2352 (defvar ebnf-font-height-S 0)
2353 (defvar ebnf-font-height-E 0)
2354 (defvar ebnf-font-height-R 0)
2355 (defvar ebnf-font-width-P 0)
2356 (defvar ebnf-font-width-T 0)
2357 (defvar ebnf-font-width-NT 0)
2358 (defvar ebnf-font-width-S 0)
2359 (defvar ebnf-font-width-E 0)
2360 (defvar ebnf-font-width-R 0)
2361 (defvar ebnf-space-T 0)
2362 (defvar ebnf-space-NT 0)
2363 (defvar ebnf-space-S 0)
2364 (defvar ebnf-space-E 0)
2365 (defvar ebnf-space-R 0)
2366
2367
2368 (defvar ebnf-basic-width 0)
2369 (defvar ebnf-basic-height 0)
2370 (defvar ebnf-vertical-space 0)
2371 (defvar ebnf-horizontal-space 0)
2372
2373
2374 (defvar ebnf-settings nil)
2375 (defvar ebnf-fonts-required nil)
2376
2377
2378 (defconst ebnf-debug
2379 "
2380 % === begin EBNF procedures to help debugging
2381
2382 % Mark visually current point: string debug
2383 /debug
2384 {/-s- exch def
2385 currentpoint
2386 gsave -s- show grestore
2387 gsave
2388 20 20 rlineto
2389 0 -40 rlineto
2390 -40 40 rlineto
2391 0 -40 rlineto
2392 20 20 rlineto
2393 stroke
2394 grestore
2395 moveto
2396 }def
2397
2398 % Show number value: number string debug-number
2399 /debug-number
2400 {gsave
2401 20 0 rmoveto show ([) show 60 string cvs show (]) show
2402 grestore
2403 }def
2404
2405 % === end EBNF procedures to help debugging
2406
2407 "
2408 "This is intended to help debugging PostScript programming.")
2409
2410
2411 (defconst ebnf-prologue
2412 "
2413 % === begin EBNF engine
2414
2415 % --- Basic Definitions
2416
2417 /fS F
2418 /SpaceS FontHeight 0.5 mul def
2419 /HeightS FontHeight FontHeight add def
2420
2421 /fE F
2422 /SpaceE FontHeight 0.5 mul def
2423 /HeightE FontHeight FontHeight add def
2424
2425 /fR F
2426 /SpaceR FontHeight 0.5 mul def
2427 /HeightR FontHeight FontHeight add def
2428
2429 /fT F
2430 /SpaceT FontHeight 0.5 mul def
2431 /HeightT FontHeight FontHeight add def
2432
2433 /fNT F
2434 /SpaceNT FontHeight 0.5 mul def
2435 /HeightNT FontHeight FontHeight add def
2436
2437 /T HeightT HeightNT add 0.5 mul def
2438 /hT T 0.5 mul def
2439 /hT2 hT 0.5 mul def
2440 /hT4 hT 0.25 mul def
2441
2442 /Er 0.1 def % Error factor
2443
2444
2445 /c{currentpoint}bind def
2446 /xyi{/xi c /yi exch def def}bind def
2447 /xyo{/xo c /yo exch def def}bind def
2448 /xyp{/xp c /yp exch def def}bind def
2449 /xyt{/xt c /yt exch def def}bind def
2450
2451 % vertical movement: x y height vm
2452 /vm{add moveto}bind def
2453
2454 % horizontal movement: x y width hm
2455 /hm{3 -1 roll exch add exch moveto}bind def
2456
2457 % set color: [R G B] SetRGB
2458 /SetRGB{aload pop setrgbcolor}bind def
2459
2460 % filling gray area: gray-scale FillGray
2461 /FillGray{gsave setgray fill grestore}bind def
2462
2463 % filling color area: [R G B] FillRGB
2464 /FillRGB{gsave SetRGB fill grestore}bind def
2465
2466 /Stroke{LineWidth setlinewidth LineColor SetRGB stroke}bind def
2467 /StrokeShape{borderwidth setlinewidth bordercolor SetRGB stroke}bind def
2468 /Gstroke{gsave Stroke grestore}bind def
2469
2470 % Empty Line: width EL
2471 /EL{0 rlineto Gstroke}bind def
2472
2473 % --- Arrows
2474
2475 /Down{hT2 neg hT4 neg rlineto}bind def
2476
2477 /Arrow
2478 {hT2 neg hT4 rmoveto
2479 hT2 hT4 neg rlineto
2480 Down
2481 }bind def
2482
2483 /ArrowPath{c newpath moveto Arrow closepath}bind def
2484
2485 %>Right Arrow: RA
2486 % \\
2487 % *---+
2488 % /
2489 /RA-vector
2490 [{} % 0 - none
2491 {hT2 neg hT4 rlineto} % 1 - semi-up
2492 {Down} % 2 - semi-down
2493 {Arrow} % 3 - simple
2494 {Gstroke ArrowPath} % 4 - transparent
2495 {Gstroke ArrowPath 1 FillGray} % 5 - hollow
2496 {Gstroke ArrowPath LineColor FillRGB} % 6 - full
2497 {Gstroke gsave UserArrow grestore} % 7 - user
2498 ]def
2499
2500 /RA
2501 {hT 0 rlineto
2502 c
2503 RA-vector ArrowShape get exec
2504 Gstroke
2505 moveto
2506 }def
2507
2508 % rotation DrawArrow
2509 /DrawArrow
2510 {gsave
2511 0 0 translate
2512 rotate
2513 RA
2514 c
2515 grestore
2516 rmoveto
2517 }def
2518
2519 %>Left Arrow: LA
2520 % /
2521 % +---*
2522 % \\
2523 /LA{180 DrawArrow}def
2524
2525 %>Up Arrow: UA
2526 % +
2527 % /|\\
2528 % |
2529 % *
2530 /UA{90 DrawArrow}def
2531
2532 %>Down Arrow: DA
2533 % *
2534 % |
2535 % \\|/
2536 % +
2537 /DA{270 DrawArrow}def
2538
2539 % --- Corners
2540
2541 %>corner Right Descendent: height arrow corner_RD
2542 % _ | arrow
2543 % / height > 0 | 0 - none
2544 % | | 1 - right
2545 % * ---------- | 2 - left
2546 % | | 3 - vertical
2547 % \\ height < 0 |
2548 % - |
2549 /cRD0-vector
2550 [% 0 - none
2551 {0 h rlineto
2552 hT 0 rlineto}
2553 % 1 - right
2554 {0 h rlineto
2555 RA}
2556 % 2 - left
2557 {hT 0 rmoveto xyi
2558 LA
2559 0 h neg rlineto
2560 xi yi moveto}
2561 % 3 - vertical
2562 {hT h rmoveto xyi
2563 hT neg 0 rlineto
2564 h 0 gt{DA}{UA}ifelse
2565 xi yi moveto}
2566 ]def
2567
2568 /cRD-vector
2569 [{cRD0-vector arrow get exec} % 0 - miter
2570 {0 0 0 h hT h rcurveto} % 1 - rounded
2571 {hT h rlineto} % 2 - bevel
2572 ]def
2573
2574 /corner_RD
2575 {/arrow exch def /h exch def
2576 cRD-vector ChartShape get exec
2577 Gstroke
2578 }def
2579
2580 %>corner Right Ascendent: height arrow corner_RA
2581 % | arrow
2582 % | height > 0 | 0 - none
2583 % / | 1 - right
2584 % *- ---------- | 2 - left
2585 % \\ | 3 - vertical
2586 % | height < 0 |
2587 % |
2588 /cRA0-vector
2589 [% 0 - none
2590 {hT 0 rlineto
2591 0 h rlineto}
2592 % 1 - right
2593 {RA
2594 0 h rlineto}
2595 % 2 - left
2596 {hT h rmoveto xyi
2597 0 h neg rlineto
2598 LA
2599 xi yi moveto}
2600 % 3 - vertical
2601 {hT h rmoveto xyi
2602 h 0 gt{DA}{UA}ifelse
2603 hT neg 0 rlineto
2604 xi yi moveto}
2605 ]def
2606
2607 /cRA-vector
2608 [{cRA0-vector arrow get exec} % 0 - miter
2609 {0 0 hT 0 hT h rcurveto} % 1 - rounded
2610 {hT h rlineto} % 2 - bevel
2611 ]def
2612
2613 /corner_RA
2614 {/arrow exch def /h exch def
2615 cRA-vector ChartShape get exec
2616 Gstroke
2617 }def
2618
2619 %>corner Left Descendent: height arrow corner_LD
2620 % _ | arrow
2621 % \\ height > 0 | 0 - none
2622 % | | 1 - right
2623 % * ---------- | 2 - left
2624 % | | 3 - vertical
2625 % / height < 0 |
2626 % - |
2627 /cLD0-vector
2628 [% 0 - none
2629 {0 h rlineto
2630 hT neg 0 rlineto}
2631 % 1 - right
2632 {hT neg h rmoveto xyi
2633 RA
2634 0 h neg rlineto
2635 xi yi moveto}
2636 % 2 - left
2637 {0 h rlineto
2638 LA}
2639 % 3 - vertical
2640 {hT neg h rmoveto xyi
2641 hT 0 rlineto
2642 h 0 gt{DA}{UA}ifelse
2643 xi yi moveto}
2644 ]def
2645
2646 /cLD-vector
2647 [{cLD0-vector arrow get exec} % 0 - miter
2648 {0 0 0 h hT neg h rcurveto} % 1 - rounded
2649 {hT neg h rlineto} % 2 - bevel
2650 ]def
2651
2652 /corner_LD
2653 {/arrow exch def /h exch def
2654 cLD-vector ChartShape get exec
2655 Gstroke
2656 }def
2657
2658 %>corner Left Ascendent: height arrow corner_LA
2659 % | arrow
2660 % | height > 0 | 0 - none
2661 % \\ | 1 - right
2662 % -* ---------- | 2 - left
2663 % / | 3 - vertical
2664 % | height < 0 |
2665 % |
2666 /cLA0-vector
2667 [% 0 - none
2668 {hT neg 0 rlineto
2669 0 h rlineto}
2670 % 1 - right
2671 {hT neg h rmoveto xyi
2672 0 h neg rlineto
2673 RA
2674 xi yi moveto}
2675 % 2 - left
2676 {LA
2677 0 h rlineto}
2678 % 3 - vertical
2679 {hT neg h rmoveto xyi
2680 h 0 gt{DA}{UA}ifelse
2681 hT 0 rlineto
2682 xi yi moveto}
2683 ]def
2684
2685 /cLA-vector
2686 [{cLA0-vector arrow get exec} % 0 - miter
2687 {0 0 hT neg 0 hT neg h rcurveto} % 1 - rounded
2688 {hT neg h rlineto} % 2 - bevel
2689 ]def
2690
2691 /corner_LA
2692 {/arrow exch def /h exch def
2693 cLA-vector ChartShape get exec
2694 Gstroke
2695 }def
2696
2697 % --- Flow Stuff
2698
2699 % height prepare_height |- line_height corner_height corner_height
2700 /prepare_height
2701 {dup 0 gt
2702 {T sub hT}
2703 {T add hT neg}ifelse
2704 dup
2705 }def
2706
2707 %>Left Alternative: height LAlt
2708 % _
2709 % /
2710 % | height > 0
2711 % |
2712 % /
2713 % *- ----------
2714 % \\
2715 % |
2716 % | height < 0
2717 % \\
2718 % -
2719 /LAlt
2720 {dup 0 eq
2721 {T exch rlineto}
2722 {dup abs T lt
2723 {0.5 mul dup
2724 1 corner_RA
2725 0 corner_RD}
2726 {prepare_height
2727 1 corner_RA
2728 exch 0 exch rlineto
2729 0 corner_RD
2730 }ifelse
2731 }ifelse
2732 }def
2733
2734 %>Left Loop: height LLoop
2735 % _
2736 % /
2737 % | height > 0
2738 % |
2739 % \\
2740 % -* ----------
2741 % /
2742 % |
2743 % | height < 0
2744 % \\
2745 % -
2746 /LLoop
2747 {prepare_height
2748 3 corner_LA
2749 exch 0 exch rlineto
2750 0 corner_RD
2751 }def
2752
2753 %>Right Alternative: height RAlt
2754 % _
2755 % \\
2756 % | height > 0
2757 % |
2758 % \\
2759 % -* ----------
2760 % /
2761 % |
2762 % | height < 0
2763 % /
2764 % -
2765 /RAlt
2766 {dup 0 eq
2767 {T neg exch rlineto}
2768 {dup abs T lt
2769 {0.5 mul dup
2770 1 corner_LA
2771 0 corner_LD}
2772 {prepare_height
2773 1 corner_LA
2774 exch 0 exch rlineto
2775 0 corner_LD
2776 }ifelse
2777 }ifelse
2778 }def
2779
2780 %>Right Loop: height RLoop
2781 % _
2782 % \\
2783 % | height > 0
2784 % |
2785 % /
2786 % *- ----------
2787 % \\
2788 % |
2789 % | height < 0
2790 % /
2791 % -
2792 /RLoop
2793 {prepare_height
2794 1 corner_RA
2795 exch 0 exch rlineto
2796 0 corner_LD
2797 }def
2798
2799 % --- Terminal, Non-terminal and Special Basics
2800
2801 % string width prepare-width |- string
2802 /prepare-width
2803 {/width exch def
2804 dup stringwidth pop space add space add width exch sub 0.5 mul
2805 /w exch def
2806 }def
2807
2808 % string width begin-right
2809 /begin-right
2810 {xyo
2811 prepare-width
2812 w hT sub EL
2813 RA
2814 }def
2815
2816 % end-right
2817 /end-right
2818 {xo width add Er add yo moveto
2819 w Er add neg EL
2820 xo yo moveto
2821 }def
2822
2823 % string width begin-left
2824 /begin-left
2825 {xyo
2826 prepare-width
2827 w EL
2828 }def
2829
2830 % end-left
2831 /end-left
2832 {xo width add Er add yo moveto
2833 hT w sub Er add EL
2834 LA
2835 xo yo moveto
2836 }def
2837
2838 /ShapePath-vector
2839 [% 0 - miter
2840 {xx yy moveto
2841 xx YY lineto
2842 XX YY lineto
2843 XX yy lineto}
2844 % 1 - rounded
2845 {/half YY yy sub 0.5 mul abs def
2846 xx half add YY moveto
2847 0 0 half neg 0 half neg half neg rcurveto
2848 0 0 0 half neg half half neg rcurveto
2849 XX xx sub abs half sub half sub 0 rlineto
2850 0 0 half 0 half half rcurveto
2851 0 0 0 half half neg half rcurveto}
2852 % 2 - bevel
2853 {/quarter YY yy sub 0.25 mul abs def
2854 xx quarter add YY moveto
2855 quarter neg quarter neg rlineto
2856 0 quarter quarter add neg rlineto
2857 quarter quarter neg rlineto
2858 XX xx sub abs quarter sub quarter sub 0 rlineto
2859 quarter quarter rlineto
2860 0 quarter quarter add rlineto
2861 quarter neg quarter rlineto}
2862 ]def
2863
2864 /doShapePath
2865 {newpath
2866 ShapePath-vector shape get exec
2867 closepath
2868 }def
2869
2870 /doShapeShadow
2871 {gsave
2872 Xshadow Xshadow add Xshadow add
2873 Yshadow Yshadow add Yshadow add translate
2874 doShapePath
2875 0.9 FillGray
2876 grestore
2877 }def
2878
2879 /doShape
2880 {gsave
2881 doShapePath
2882 shapecolor FillRGB
2883 StrokeShape
2884 grestore
2885 }def
2886
2887 % string SBound |- string
2888 /SBound
2889 {/xx c dup /yy exch def
2890 FontHeight add /YY exch def def
2891 dup stringwidth pop xx add /XX exch def
2892 Effect 8 and 0 ne
2893 {/yy yy YShadow add def
2894 /XX XX XShadow add def
2895 }if
2896 }def
2897
2898 % string SBox
2899 /SBox
2900 {gsave
2901 c space sub moveto
2902 SBound
2903 /XX XX space add space add def
2904 /YY YY space add def
2905 /yy yy space sub def
2906 shadow{doShapeShadow}if
2907 doShape
2908 space Descent abs rmoveto
2909 foreground SetRGB S
2910 grestore
2911 }def
2912
2913 % --- Terminal
2914
2915 % TeRminal: string TR
2916 /TR
2917 {/Effect EffectT def
2918 /shape ShapeT def
2919 /shapecolor BackgroundT def
2920 /borderwidth BorderWidthT def
2921 /bordercolor BorderColorT def
2922 /foreground ForegroundT def
2923 /shadow ShadowT def
2924 SBox
2925 }def
2926
2927 %>Right Terminal: string width RT |- x y
2928 /RT
2929 {xyt
2930 /fT F
2931 /space SpaceT def
2932 begin-right
2933 TR
2934 end-right
2935 xt yt
2936 }def
2937
2938 %>Left Terminal: string width LT |- x y
2939 /LT
2940 {xyt
2941 /fT F
2942 /space SpaceT def
2943 begin-left
2944 TR
2945 end-left
2946 xt yt
2947 }def
2948
2949 %>Right Terminal Default: string width RTD |- x y
2950 /RTD
2951 {/-save- BorderWidthT def
2952 /BorderWidthT BorderWidthT DefaultWidth add def
2953 RT
2954 /BorderWidthT -save- def
2955 }def
2956
2957 %>Left Terminal Default: string width LTD |- x y
2958 /LTD
2959 {/-save- BorderWidthT def
2960 /BorderWidthT BorderWidthT DefaultWidth add def
2961 LT
2962 /BorderWidthT -save- def
2963 }def
2964
2965 % --- Non-Terminal
2966
2967 % Non-Terminal: string NT
2968 /NT
2969 {/Effect EffectNT def
2970 /shape ShapeNT def
2971 /shapecolor BackgroundNT def
2972 /borderwidth BorderWidthNT def
2973 /bordercolor BorderColorNT def
2974 /foreground ForegroundNT def
2975 /shadow ShadowNT def
2976 SBox
2977 }def
2978
2979 %>Right Non-Terminal: string width RNT |- x y
2980 /RNT
2981 {xyt
2982 /fNT F
2983 /space SpaceNT def
2984 begin-right
2985 NT
2986 end-right
2987 xt yt
2988 }def
2989
2990 %>Left Non-Terminal: string width LNT |- x y
2991 /LNT
2992 {xyt
2993 /fNT F
2994 /space SpaceNT def
2995 begin-left
2996 NT
2997 end-left
2998 xt yt
2999 }def
3000
3001 %>Right Non-Terminal Default: string width RNTD |- x y
3002 /RNTD
3003 {/-save- BorderWidthNT def
3004 /BorderWidthNT BorderWidthNT DefaultWidth add def
3005 RNT
3006 /BorderWidthNT -save- def
3007 }def
3008
3009 %>Left Non-Terminal Default: string width LNTD |- x y
3010 /LNTD
3011 {/-save- BorderWidthNT def
3012 /BorderWidthNT BorderWidthNT DefaultWidth add def
3013 LNT
3014 /BorderWidthNT -save- def
3015 }def
3016
3017 % --- Special
3018
3019 % SPecial: string SP
3020 /SP
3021 {/Effect EffectS def
3022 /shape ShapeS def
3023 /shapecolor BackgroundS def
3024 /borderwidth BorderWidthS def
3025 /bordercolor BorderColorS def
3026 /foreground ForegroundS def
3027 /shadow ShadowS def
3028 SBox
3029 }def
3030
3031 %>Right SPecial: string width RSP |- x y
3032 /RSP
3033 {xyt
3034 /fS F
3035 /space SpaceS def
3036 begin-right
3037 SP
3038 end-right
3039 xt yt
3040 }def
3041
3042 %>Left SPecial: string width LSP |- x y
3043 /LSP
3044 {xyt
3045 /fS F
3046 /space SpaceS def
3047 begin-left
3048 SP
3049 end-left
3050 xt yt
3051 }def
3052
3053 %>Right SPecial Default: string width RSPD |- x y
3054 /RSPD
3055 {/-save- BorderWidthS def
3056 /BorderWidthS BorderWidthS DefaultWidth add def
3057 RSP
3058 /BorderWidthS -save- def
3059 }def
3060
3061 %>Left SPecial Default: string width LSPD |- x y
3062 /LSPD
3063 {/-save- BorderWidthS def
3064 /BorderWidthS BorderWidthS DefaultWidth add def
3065 LSP
3066 /BorderWidthS -save- def
3067 }def
3068
3069 % --- Repeat and Except basics
3070
3071 /begin-direction
3072 {/w width rwidth sub 0.5 mul def
3073 width 0 rmoveto}def
3074
3075 /end-direction
3076 {gsave
3077 /xx c entry add /YY exch def def
3078 /yy YY height sub def
3079 /XX xx rwidth add def
3080 shadow{doShapeShadow}if
3081 doShape
3082 grestore
3083 }def
3084
3085 /right-direction
3086 {begin-direction
3087 w neg EL
3088 xt yt moveto
3089 w hT sub EL RA
3090 end-direction
3091 }def
3092
3093 /left-direction
3094 {begin-direction
3095 hT w sub EL LA
3096 xt yt moveto
3097 w EL
3098 end-direction
3099 }def
3100
3101 % --- Repeat
3102
3103 % entry height width rwidth begin-repeat
3104 /begin-repeat
3105 {/rwidth exch def
3106 /width exch def
3107 /height exch def
3108 /entry exch def
3109 /fR F
3110 /space SpaceR def
3111 /Effect EffectR def
3112 /shape ShapeR def
3113 /shapecolor BackgroundR def
3114 /borderwidth BorderWidthR def
3115 /bordercolor BorderColorR def
3116 /foreground ForegroundR def
3117 /shadow ShadowR def
3118 xyt
3119 }def
3120
3121 % string end-repeat |- x y
3122 /end-repeat
3123 {gsave
3124 space Descent rmoveto
3125 foreground SetRGB S
3126 c Descent sub
3127 grestore
3128 exch space add exch moveto
3129 xt yt
3130 }def
3131
3132 %>Right RePeat: string entry height width rwidth RRP |- x y
3133 /RRP{begin-repeat right-direction end-repeat}def
3134
3135 %>Left RePeat: string entry height width rwidth LRP |- x y
3136 /LRP{begin-repeat left-direction end-repeat}def
3137
3138 % --- Except
3139
3140 % entry height width rwidth begin-except
3141 /begin-except
3142 {/rwidth exch def
3143 /width exch def
3144 /height exch def
3145 /entry exch def
3146 /fE F
3147 /space SpaceE def
3148 /Effect EffectE def
3149 /shape ShapeE def
3150 /shapecolor BackgroundE def
3151 /borderwidth BorderWidthE def
3152 /bordercolor BorderColorE def
3153 /foreground ForegroundE def
3154 /shadow ShadowE def
3155 xyt
3156 }def
3157
3158 % x-width end-except |- x y
3159 /end-except
3160 {gsave
3161 space space add add Descent rmoveto
3162 (-) foreground SetRGB S
3163 grestore
3164 space 0 rmoveto
3165 xt yt
3166 }def
3167
3168 %>Right EXcept: x-width entry height width rwidth REX |- x y
3169 /REX{begin-except right-direction end-except}def
3170
3171 %>Left EXcept: x-width entry height width rwidth LEX |- x y
3172 /LEX{begin-except left-direction end-except}def
3173
3174 % --- Sequence
3175
3176 %>Beginning Of Sequence: BOS |- x y
3177 /BOS{currentpoint}bind def
3178
3179 %>End Of Sequence: x y x1 y1 EOS |- x y
3180 /EOS{pop pop}bind def
3181
3182 % --- Production
3183
3184 %>Beginning Of Production: string width height BOP |- y x
3185 /BOP
3186 {xyp
3187 neg yp add /yw exch def
3188 xp add T sub /xw exch def
3189 /Effect EffectP def
3190 /fP F ForegroundP SetRGB BackgroundP aload pop true BG S
3191 /Effect 0 def
3192 ( :) S false BG
3193 xw yw moveto
3194 hT EL RA
3195 xp yw moveto
3196 T EL
3197 yp xp
3198 }def
3199
3200 %>End Of Production: y x delta EOP
3201 /EOPH{add exch moveto}bind def % horizontal
3202 /EOPV{exch pop sub 0 exch moveto}bind def % vertical
3203
3204 % --- Empty Alternative
3205
3206 %>Empty Alternative: width EA |- x y
3207 /EA
3208 {gsave
3209 Er add 0 rlineto
3210 Stroke
3211 grestore
3212 c
3213 }def
3214
3215 % --- Alternative
3216
3217 %>AlTernative: h1 h2 ... hn n width AT |- x y
3218 /AT
3219 {xyo xo add /xw exch def
3220 xw yo moveto
3221 Er EL
3222 {xw yo moveto
3223 dup RAlt
3224 xo yo moveto
3225 LAlt}repeat
3226 xo yo
3227 }def
3228
3229 % --- Optional
3230
3231 %>OPtional: height width OP |- x y
3232 /OP
3233 {xyo
3234 T sub /ow exch def
3235 ow Er sub 0 rmoveto
3236 T Er add EL
3237 neg dup RAlt
3238 ow T sub neg EL
3239 xo yo moveto
3240 LAlt
3241 xo yo moveto
3242 T EL
3243 xo yo
3244 }def
3245
3246 % --- List Flow
3247
3248 %>One or More: height width OM |- x y
3249 /OM
3250 {xyo
3251 /ow exch def
3252 ow Er add 0 rmoveto
3253 T Er add neg EL
3254 dup RLoop
3255 xo T add yo moveto
3256 LLoop
3257 xo yo moveto
3258 T EL
3259 xo yo
3260 }def
3261
3262 %>Zero or More: h2 h1 width ZM |- x y
3263 /ZM
3264 {xyo
3265 Er add EL
3266 Er neg 0 rmoveto
3267 dup RAlt
3268 exch dup RLoop
3269 xo yo moveto
3270 exch dup LAlt
3271 exch LLoop
3272 yo add xo T add exch moveto
3273 xo yo
3274 }def
3275
3276 % === end EBNF engine
3277
3278 "
3279 "EBNF PostScript prologue")
3280
3281
3282 (defconst ebnf-eps-prologue
3283 "
3284 /#ebnf2ps#dict 230 dict def
3285 #ebnf2ps#dict begin
3286
3287 % Initiliaze variables to avoid name-conflicting with document variables.
3288 % This is the case when using `bind' operator.
3289 /-fillp- 0 def /h 0 def
3290 /-ox- 0 def /half 0 def
3291 /-oy- 0 def /height 0 def
3292 /-save- 0 def /ow 0 def
3293 /Ascent 0 def /quarter 0 def
3294 /Descent 0 def /rXX 0 def
3295 /Effect 0 def /rYY 0 def
3296 /FontHeight 0 def /rwidth 0 def
3297 /LineThickness 0 def /rxx 0 def
3298 /OverlinePosition 0 def /ryy 0 def
3299 /SpaceBackground 0 def /shadow 0 def
3300 /StrikeoutPosition 0 def /shape 0 def
3301 /UnderlinePosition 0 def /shapecolor 0 def
3302 /XBox 0 def /space 0 def
3303 /XX 0 def /st 1 string def
3304 /Xshadow 0 def /w 0 def
3305 /YBox 0 def /width 0 def
3306 /YY 0 def /xi 0 def
3307 /Yshadow 0 def /xo 0 def
3308 /arrow 0 def /xp 0 def
3309 /bg false def /xt 0 def
3310 /bgcolor 0 def /xw 0 def
3311 /bordercolor 0 def /xx 0 def
3312 /borderwidth 0 def /yi 0 def
3313 /dd 0 def /yo 0 def
3314 /entry 0 def /yp 0 def
3315 /foreground 0 def /yt 0 def
3316 /yy 0 def
3317
3318
3319 % ISOLatin1Encoding stolen from ps_init.ps in GhostScript 2.6.1.4:
3320 /ISOLatin1Encoding where
3321 {pop}
3322 {% -- The ISO Latin-1 encoding vector isn't known, so define it.
3323 % -- The first half is the same as the standard encoding,
3324 % -- except for minus instead of hyphen at code 055.
3325 /ISOLatin1Encoding
3326 StandardEncoding 0 45 getinterval aload pop
3327 /minus
3328 StandardEncoding 46 82 getinterval aload pop
3329 %*** NOTE: the following are missing in the Adobe documentation,
3330 %*** but appear in the displayed table:
3331 %*** macron at 0225, dieresis at 0230, cedilla at 0233, space at 0240.
3332 % 0200 (128)
3333 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
3334 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
3335 /dotlessi /grave /acute /circumflex /tilde /macron /breve /dotaccent
3336 /dieresis /.notdef /ring /cedilla /.notdef /hungarumlaut /ogonek /caron
3337 % 0240 (160)
3338 /space /exclamdown /cent /sterling
3339 /currency /yen /brokenbar /section
3340 /dieresis /copyright /ordfeminine /guillemotleft
3341 /logicalnot /hyphen /registered /macron
3342 /degree /plusminus /twosuperior /threesuperior
3343 /acute /mu /paragraph /periodcentered
3344 /cedilla /onesuperior /ordmasculine /guillemotright
3345 /onequarter /onehalf /threequarters /questiondown
3346 % 0300 (192)
3347 /Agrave /Aacute /Acircumflex /Atilde
3348 /Adieresis /Aring /AE /Ccedilla
3349 /Egrave /Eacute /Ecircumflex /Edieresis
3350 /Igrave /Iacute /Icircumflex /Idieresis
3351 /Eth /Ntilde /Ograve /Oacute
3352 /Ocircumflex /Otilde /Odieresis /multiply
3353 /Oslash /Ugrave /Uacute /Ucircumflex
3354 /Udieresis /Yacute /Thorn /germandbls
3355 % 0340 (224)
3356 /agrave /aacute /acircumflex /atilde
3357 /adieresis /aring /ae /ccedilla
3358 /egrave /eacute /ecircumflex /edieresis
3359 /igrave /iacute /icircumflex /idieresis
3360 /eth /ntilde /ograve /oacute
3361 /ocircumflex /otilde /odieresis /divide
3362 /oslash /ugrave /uacute /ucircumflex
3363 /udieresis /yacute /thorn /ydieresis
3364 256 packedarray def
3365 }ifelse
3366
3367 /reencodeFontISO %def
3368 {dup
3369 length 12 add dict % Make a new font (a new dict the same size
3370 % as the old one) with room for our new symbols.
3371
3372 begin % Make the new font the current dictionary.
3373 {1 index /FID ne
3374 {def}{pop pop}ifelse
3375 }forall % Copy each of the symbols from the old dictionary
3376 % to the new one except for the font ID.
3377
3378 currentdict /FontType get 0 ne
3379 {/Encoding ISOLatin1Encoding def}if % Override the encoding with
3380 % the ISOLatin1 encoding.
3381
3382 % Use the font's bounding box to determine the ascent, descent,
3383 % and overall height; don't forget that these values have to be
3384 % transformed using the font's matrix.
3385
3386 % ^ (x2 y2)
3387 % | |
3388 % | v
3389 % | +----+ - -
3390 % | | | ^
3391 % | | | | Ascent (usually > 0)
3392 % | | | |
3393 % (0 0) -> +--+----+-------->
3394 % | | |
3395 % | | v Descent (usually < 0)
3396 % (x1 y1) --> +----+ - -
3397
3398 currentdict /FontType get 0 ne
3399 {/FontBBox load aload pop % -- x1 y1 x2 y2
3400 FontMatrix transform /Ascent exch def pop
3401 FontMatrix transform /Descent exch def pop}
3402 {/PrimaryFont FDepVector 0 get def
3403 PrimaryFont /FontBBox get aload pop
3404 PrimaryFont /FontMatrix get transform /Ascent exch def pop
3405 PrimaryFont /FontMatrix get transform /Descent exch def pop
3406 }ifelse
3407
3408 /FontHeight Ascent Descent sub def % use `sub' because descent < 0
3409
3410 % Define these in case they're not in the FontInfo
3411 % (also, here they're easier to get to).
3412 /UnderlinePosition Descent 0.70 mul def
3413 /OverlinePosition Descent UnderlinePosition sub Ascent add def
3414 /StrikeoutPosition Ascent 0.30 mul def
3415 /LineThickness FontHeight 0.05 mul def
3416 /Xshadow FontHeight 0.08 mul def
3417 /Yshadow FontHeight -0.09 mul def
3418 /SpaceBackground Descent neg UnderlinePosition add def
3419 /XBox Descent neg def
3420 /YBox LineThickness 0.7 mul def
3421
3422 currentdict % Leave the new font on the stack
3423 end % Stop using the font as the current dictionary
3424 definefont % Put the font into the font dictionary
3425 pop % Discard the returned font
3426 }bind def
3427
3428 % Font definition
3429 /DefFont{findfont exch scalefont reencodeFontISO}def
3430
3431 % Font selection
3432 /F
3433 {findfont
3434 dup /Ascent get /Ascent exch def
3435 dup /Descent get /Descent exch def
3436 dup /FontHeight get /FontHeight exch def
3437 dup /UnderlinePosition get /UnderlinePosition exch def
3438 dup /OverlinePosition get /OverlinePosition exch def
3439 dup /StrikeoutPosition get /StrikeoutPosition exch def
3440 dup /LineThickness get /LineThickness exch def
3441 dup /Xshadow get /Xshadow exch def
3442 dup /Yshadow get /Yshadow exch def
3443 dup /SpaceBackground get /SpaceBackground exch def
3444 dup /XBox get /XBox exch def
3445 dup /YBox get /YBox exch def
3446 setfont
3447 }def
3448
3449 /BG
3450 {dup /bg exch def
3451 {mark 4 1 roll ]}
3452 {[ 1.0 1.0 1.0 ]}
3453 ifelse
3454 /bgcolor exch def
3455 }def
3456
3457 % stack: --
3458 /FillBgColor{bgcolor aload pop setrgbcolor fill}bind def
3459
3460 % stack: fill-or-not lower-x lower-y upper-x upper-y |- --
3461 /doRect
3462 {/rYY exch def
3463 /rXX exch def
3464 /ryy exch def
3465 /rxx exch def
3466 gsave
3467 newpath
3468 rXX rYY moveto
3469 rxx rYY lineto
3470 rxx ryy lineto
3471 rXX ryy lineto
3472 closepath
3473 % top of stack: fill-or-not
3474 {FillBgColor}
3475 {LineThickness setlinewidth stroke}
3476 ifelse
3477 grestore
3478 }bind def
3479
3480 % stack: string fill-or-not |- --
3481 /doOutline
3482 {/-fillp- exch def
3483 /-ox- currentpoint /-oy- exch def def
3484 gsave
3485 LineThickness setlinewidth
3486 {st 0 3 -1 roll put
3487 st dup true charpath
3488 -fillp- {gsave FillBgColor grestore}if
3489 stroke stringwidth
3490 -oy- add /-oy- exch def
3491 -ox- add /-ox- exch def
3492 -ox- -oy- moveto
3493 }forall
3494 grestore
3495 -ox- -oy- moveto
3496 }bind def
3497
3498 % stack: fill-or-not delta |- --
3499 /doBox
3500 {/dd exch def
3501 xx XBox sub dd sub yy YBox sub dd sub
3502 XX XBox add dd add YY YBox add dd add
3503 doRect
3504 }bind def
3505
3506 % stack: string |- --
3507 /doShadow
3508 {gsave
3509 Xshadow Yshadow rmoveto
3510 false doOutline
3511 grestore
3512 }bind def
3513
3514 % stack: position |- --
3515 /Hline
3516 {currentpoint exch pop add dup
3517 gsave
3518 newpath
3519 xx exch moveto
3520 XX exch lineto
3521 closepath
3522 LineThickness setlinewidth stroke
3523 grestore
3524 }bind def
3525
3526 % stack: string |- --
3527 % effect: 1 - underline 2 - strikeout 4 - overline
3528 % 8 - shadow 16 - box 32 - outline
3529 /S
3530 {/xx currentpoint dup Descent add /yy exch def
3531 Ascent add /YY exch def def
3532 dup stringwidth pop xx add /XX exch def
3533 Effect 8 and 0 ne
3534 {/yy yy Yshadow add def
3535 /XX XX Xshadow add def
3536 }if
3537 bg
3538 {true
3539 Effect 16 and 0 ne
3540 {SpaceBackground doBox}
3541 {xx yy XX YY doRect}
3542 ifelse
3543 }if % background
3544 Effect 16 and 0 ne{false 0 doBox}if % box
3545 Effect 8 and 0 ne{dup doShadow}if % shadow
3546 Effect 32 and 0 ne
3547 {true doOutline} % outline
3548 {show} % normal text
3549 ifelse
3550 Effect 1 and 0 ne{UnderlinePosition Hline}if % underline
3551 Effect 2 and 0 ne{StrikeoutPosition Hline}if % strikeout
3552 Effect 4 and 0 ne{OverlinePosition Hline}if % overline
3553 }bind def
3554
3555 "
3556 "EBNF EPS prologue")
3557
3558
3559 (defconst ebnf-eps-begin
3560 "
3561 end
3562
3563 % x y #ebnf2ps#begin
3564 /#ebnf2ps#begin
3565 {#ebnf2ps#dict begin /#ebnf2ps#save save def
3566 moveto false BG 0.0 0.0 0.0 setrgbcolor}def
3567
3568 /#ebnf2ps#end{showpage #ebnf2ps#save restore end}def
3569
3570 %%EndPrologue
3571 "
3572 "EBNF EPS begin")
3573
3574
3575 (defconst ebnf-eps-end
3576 "#ebnf2ps#end
3577 %%EOF
3578 "
3579 "EBNF EPS end")
3580
3581
3582 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3583 ;; Formatting
3584
3585
3586 (defvar ebnf-format-float "%1.3f")
3587
3588
3589 (defun ebnf-format-float (&rest floats)
3590 (mapconcat
3591 #'(lambda (float)
3592 (format ebnf-format-float float))
3593 floats
3594 " "))
3595
3596
3597 (defun ebnf-format-color (format-str color default)
3598 (let* ((the-color (or color default))
3599 (rgb (mapcar 'ps-color-value (ps-color-values the-color))))
3600 (format format-str
3601 (concat "["
3602 (ebnf-format-float (nth 0 rgb) (nth 1 rgb) (nth 2 rgb))
3603 "]")
3604 the-color)))
3605
3606
3607 (defvar ebnf-message-float "%3.2f")
3608
3609
3610 (defsubst ebnf-message-float (format-str value)
3611 (message format-str
3612 (format ebnf-message-float value)))
3613
3614
3615 (defsubst ebnf-message-info (messag)
3616 (message "%s...%3d%%"
3617 messag
3618 (round (/ (* (setq ebnf-nprod (1+ ebnf-nprod)) 100.0) ebnf-total))))
3619
3620
3621 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3622 ;; Macros
3623
3624
3625 (defmacro ebnf-node-kind (vec &optional value)
3626 (if value
3627 `(aset ,vec 0 ,value)
3628 `(aref ,vec 0)))
3629
3630
3631 (defmacro ebnf-node-width-func (node width)
3632 `(funcall (aref ,node 1) ,node ,width))
3633
3634
3635 (defmacro ebnf-node-dimension-func (node &optional value)
3636 (if value
3637 `(aset ,node 2 ,value)
3638 `(funcall (aref ,node 2) ,node)))
3639
3640
3641 (defmacro ebnf-node-entry (vec &optional value)
3642 (if value
3643 `(aset ,vec 3 ,value)
3644 `(aref ,vec 3)))
3645
3646
3647 (defmacro ebnf-node-height (vec &optional value)
3648 (if value
3649 `(aset ,vec 4 ,value)
3650 `(aref ,vec 4)))
3651
3652
3653 (defmacro ebnf-node-width (vec &optional value)
3654 (if value
3655 `(aset ,vec 5 ,value)
3656 `(aref ,vec 5)))
3657
3658
3659 (defmacro ebnf-node-name (vec)
3660 `(aref ,vec 6))
3661
3662
3663 (defmacro ebnf-node-list (vec &optional value)
3664 (if value
3665 `(aset ,vec 6 ,value)
3666 `(aref ,vec 6)))
3667
3668
3669 (defmacro ebnf-node-default (vec)
3670 `(aref ,vec 7))
3671
3672
3673 (defmacro ebnf-node-production (vec &optional value)
3674 (if value
3675 `(aset ,vec 7 ,value)
3676 `(aref ,vec 7)))
3677
3678
3679 (defmacro ebnf-node-separator (vec &optional value)
3680 (if value
3681 `(aset ,vec 7 ,value)
3682 `(aref ,vec 7)))
3683
3684
3685 (defmacro ebnf-node-action (vec &optional value)
3686 (if value
3687 `(aset ,vec 8 ,value)
3688 `(aref ,vec 8)))
3689
3690
3691 (defmacro ebnf-node-generation (node)
3692 `(funcall (ebnf-node-kind ,node) ,node))
3693
3694
3695 (defmacro ebnf-max-width (prod)
3696 `(max (ebnf-node-width ,prod)
3697 (+ (* (length (ebnf-node-name ,prod))
3698 ebnf-font-width-P)
3699 ebnf-production-horizontal-space)))
3700
3701
3702 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3703 ;; PostScript generation
3704
3705
3706 (defun ebnf-generate-eps (ebnf-tree)
3707 (let* ((ps-color-p (and ebnf-color-p (ps-color-device)))
3708 (ps-print-color-scale (if ps-color-p
3709 (float (car (ps-color-values "white")))
3710 1.0))
3711 (ebnf-total (length ebnf-tree))
3712 (ebnf-nprod 0)
3713 (old-ps-output (symbol-function 'ps-output))
3714 (old-ps-output-string (symbol-function 'ps-output-string))
3715 (eps-buffer (get-buffer-create ebnf-eps-buffer-name))
3716 ebnf-debug-ps error-msg horizontal
3717 prod prod-name prod-width prod-height prod-list file-list)
3718 ;; redefines `ps-output' and `ps-output-string'
3719 (defalias 'ps-output 'ebnf-eps-output)
3720 (defalias 'ps-output-string 'ps-output-string-prim)
3721 ;; generate EPS file
3722 (save-excursion
3723 (condition-case data
3724 (progn
3725 (while ebnf-tree
3726 (setq prod (car ebnf-tree)
3727 prod-name (ebnf-node-name prod)
3728 prod-width (ebnf-max-width prod)
3729 prod-height (ebnf-node-height prod)
3730 horizontal (memq (ebnf-node-action prod) ebnf-action-list))
3731 ;; generate production in EPS buffer
3732 (save-excursion
3733 (set-buffer eps-buffer)
3734 (setq ebnf-eps-upper-x 0.0
3735 ebnf-eps-upper-y 0.0
3736 ebnf-eps-max-width prod-width
3737 ebnf-eps-max-height prod-height)
3738 (ebnf-generate-production prod))
3739 (if (setq prod-list (cdr (assoc prod-name
3740 ebnf-eps-production-list)))
3741 ;; insert EPS buffer in all buffer associated with production
3742 (ebnf-eps-production-list prod-list 'file-list horizontal
3743 prod-width prod-height eps-buffer)
3744 ;; write EPS file for production
3745 (ebnf-eps-finish-and-write eps-buffer
3746 (ebnf-eps-filename prod-name)))
3747 ;; prepare for next loop
3748 (save-excursion
3749 (set-buffer eps-buffer)
3750 (erase-buffer))
3751 (setq ebnf-tree (cdr ebnf-tree)))
3752 ;; write and kill temporary buffers
3753 (ebnf-eps-write-kill-temp file-list t)
3754 (setq file-list nil))
3755 ;; handler
3756 ((quit error)
3757 (setq error-msg (error-message-string data)))))
3758 ;; restore `ps-output' and `ps-output-string'
3759 (defalias 'ps-output old-ps-output)
3760 (defalias 'ps-output-string old-ps-output-string)
3761 ;; kill temporary buffers
3762 (kill-buffer eps-buffer)
3763 (ebnf-eps-write-kill-temp file-list nil)
3764 (and error-msg (error error-msg))
3765 (message " ")))
3766
3767
3768 ;; write and kill temporary buffers
3769 (defun ebnf-eps-write-kill-temp (file-list write-p)
3770 (while file-list
3771 (let ((buffer (get-buffer (concat " *" (car file-list) "*"))))
3772 (when buffer
3773 (and write-p
3774 (ebnf-eps-finish-and-write buffer (car file-list)))
3775 (kill-buffer buffer)))
3776 (setq file-list (cdr file-list))))
3777
3778
3779 ;; insert EPS buffer in all buffer associated with production
3780 (defun ebnf-eps-production-list (prod-list file-list-sym horizontal
3781 prod-width prod-height eps-buffer)
3782 (while prod-list
3783 (add-to-list file-list-sym (car prod-list))
3784 (save-excursion
3785 (set-buffer (get-buffer-create (concat " *" (car prod-list) "*")))
3786 (goto-char (point-max))
3787 (cond
3788 ;; first production
3789 ((zerop (buffer-size))
3790 (setq ebnf-eps-upper-x 0.0
3791 ebnf-eps-upper-y 0.0
3792 ebnf-eps-max-width prod-width
3793 ebnf-eps-max-height prod-height))
3794 ;; horizontal
3795 (horizontal
3796 (ebnf-eop-horizontal ebnf-eps-prod-width)
3797 (setq ebnf-eps-max-width (+ ebnf-eps-max-width
3798 ebnf-production-horizontal-space
3799 prod-width)
3800 ebnf-eps-max-height (max ebnf-eps-max-height prod-height)))
3801 ;; vertical
3802 (t
3803 (ebnf-eop-vertical ebnf-eps-max-height)
3804 (setq ebnf-eps-upper-x (max ebnf-eps-upper-x ebnf-eps-max-width)
3805 ebnf-eps-upper-y (if (zerop ebnf-eps-upper-y)
3806 ebnf-eps-max-height
3807 (+ ebnf-eps-upper-y
3808 ebnf-production-vertical-space
3809 ebnf-eps-max-height))
3810 ebnf-eps-max-width prod-width
3811 ebnf-eps-max-height prod-height))
3812 )
3813 (setq ebnf-eps-prod-width prod-width)
3814 (insert-buffer eps-buffer))
3815 (setq prod-list (cdr prod-list))))
3816
3817
3818 (defun ebnf-generate (ebnf-tree)
3819 (let* ((ps-color-p (and ebnf-color-p (ps-color-device)))
3820 (ps-print-color-scale (if ps-color-p
3821 (float (car (ps-color-values "white")))
3822 1.0))
3823 ps-zebra-stripes ps-line-number ps-razzle-dazzle
3824 ps-print-hook
3825 ps-print-begin-sheet-hook
3826 ps-print-begin-page-hook
3827 ps-print-begin-column-hook)
3828 (ps-generate (current-buffer) (point-min) (point-max)
3829 'ebnf-generate-postscript)))
3830
3831
3832 (defvar ebnf-tree nil)
3833 (defvar ebnf-direction "R")
3834 (defvar ebnf-total 0)
3835 (defvar ebnf-nprod 0)
3836
3837
3838 (defun ebnf-generate-postscript (from to)
3839 (ebnf-begin-file)
3840 (if ebnf-horizontal-max-height
3841 (ebnf-generate-with-max-height)
3842 (ebnf-generate-without-max-height))
3843 (message " "))
3844
3845
3846 (defun ebnf-generate-with-max-height ()
3847 (let ((ebnf-total (length ebnf-tree))
3848 (ebnf-nprod 0)
3849 next-line max-height prod the-width)
3850 (while ebnf-tree
3851 ;; find next line point
3852 (setq next-line ebnf-tree
3853 prod (car ebnf-tree)
3854 max-height (ebnf-node-height prod))
3855 (ebnf-begin-line prod (ebnf-max-width prod))
3856 (while (and (setq next-line (cdr next-line))
3857 (setq prod (car next-line))
3858 (memq (ebnf-node-action prod) ebnf-action-list)
3859 (setq the-width (ebnf-max-width prod))
3860 (<= the-width ps-width-remaining))
3861 (setq max-height (max max-height (ebnf-node-height prod))
3862 ps-width-remaining (- ps-width-remaining
3863 (+ the-width
3864 ebnf-production-horizontal-space))))
3865 ;; generate current line
3866 (ebnf-newline max-height)
3867 (setq prod (car ebnf-tree))
3868 (ebnf-generate-production prod)
3869 (while (not (eq (setq ebnf-tree (cdr ebnf-tree)) next-line))
3870 (ebnf-eop-horizontal (ebnf-max-width prod))
3871 (setq prod (car ebnf-tree))
3872 (ebnf-generate-production prod))
3873 (ebnf-eop-vertical max-height))))
3874
3875
3876 (defun ebnf-generate-without-max-height ()
3877 (let ((ebnf-total (length ebnf-tree))
3878 (ebnf-nprod 0)
3879 max-height prod bef-width cur-width)
3880 (while ebnf-tree
3881 ;; generate current line
3882 (setq prod (car ebnf-tree)
3883 max-height (ebnf-node-height prod)
3884 bef-width (ebnf-max-width prod))
3885 (ebnf-begin-line prod bef-width)
3886 (ebnf-generate-production prod)
3887 (while (and (setq ebnf-tree (cdr ebnf-tree))
3888 (setq prod (car ebnf-tree))
3889 (memq (ebnf-node-action prod) ebnf-action-list)
3890 (setq cur-width (ebnf-max-width prod))
3891 (<= cur-width ps-width-remaining)
3892 (<= (ebnf-node-height prod) ps-height-remaining))
3893 (ebnf-eop-horizontal bef-width)
3894 (ebnf-generate-production prod)
3895 (setq bef-width cur-width
3896 max-height (max max-height (ebnf-node-height prod))
3897 ps-width-remaining (- ps-width-remaining
3898 (+ cur-width
3899 ebnf-production-horizontal-space))))
3900 (ebnf-eop-vertical max-height)
3901 ;; prepare next line
3902 (ebnf-newline max-height))))
3903
3904
3905 (defun ebnf-begin-line (prod width)
3906 (and (or (eq (ebnf-node-action prod) 'form-feed)
3907 (> (ebnf-node-height prod) ps-height-remaining))
3908 (ebnf-new-page))
3909 (setq ps-width-remaining (- ps-width-remaining
3910 (+ width
3911 ebnf-production-horizontal-space))))
3912
3913
3914 (defun ebnf-newline (height)
3915 (and (> height ps-height-remaining)
3916 (ebnf-new-page))
3917 (setq ps-width-remaining ps-print-width
3918 ps-height-remaining (- ps-height-remaining
3919 (+ height
3920 ebnf-production-vertical-space))))
3921
3922
3923 ;; [production width-fun dim-fun entry height width name production action]
3924 (defun ebnf-generate-production (production)
3925 (ebnf-message-info "Generating")
3926 (run-hooks 'ebnf-production-hook)
3927 (ps-output-string (ebnf-node-name production))
3928 (ps-output " "
3929 (ebnf-format-float
3930 (ebnf-node-width production)
3931 (+ ebnf-basic-height
3932 (ebnf-node-entry (ebnf-node-production production))))
3933 " BOP\n")
3934 (ebnf-node-generation (ebnf-node-production production))
3935 (ps-output "EOS\n"))
3936
3937
3938 ;; [alternative width-fun dim-fun entry height width list]
3939 (defun ebnf-generate-alternative (alternative)
3940 (let ((alt (ebnf-node-list alternative))
3941 (entry (ebnf-node-entry alternative))
3942 (nlist 0)
3943 alt-height alt-entry)
3944 (while alt
3945 (ps-output (ebnf-format-float (- entry (ebnf-node-entry (car alt))))
3946 " ")
3947 (setq entry (- entry (ebnf-node-height (car alt)) ebnf-vertical-space)
3948 nlist (1+ nlist)
3949 alt (cdr alt)))
3950 (ps-output (format "%d " nlist)
3951 (ebnf-format-float (ebnf-node-width alternative))
3952 " AT\n")
3953 (setq alt (ebnf-node-list alternative))
3954 (when alt
3955 (ebnf-node-generation (car alt))
3956 (setq alt-height (- (ebnf-node-height (car alt))
3957 (ebnf-node-entry (car alt)))))
3958 (while (setq alt (cdr alt))
3959 (setq alt-entry (ebnf-node-entry (car alt)))
3960 (ebnf-vertical-movement
3961 (- (+ alt-height ebnf-vertical-space alt-entry)))
3962 (ebnf-node-generation (car alt))
3963 (setq alt-height (- (ebnf-node-height (car alt)) alt-entry))))
3964 (ps-output "EOS\n"))
3965
3966
3967 ;; [sequence width-fun dim-fun entry height width list]
3968 (defun ebnf-generate-sequence (sequence)
3969 (ps-output "BOS\n")
3970 (let ((seq (ebnf-node-list sequence))
3971 seq-width)
3972 (when seq
3973 (ebnf-node-generation (car seq))
3974 (setq seq-width (ebnf-node-width (car seq))))
3975 (while (setq seq (cdr seq))
3976 (ebnf-horizontal-movement seq-width)
3977 (ebnf-node-generation (car seq))
3978 (setq seq-width (ebnf-node-width (car seq)))))
3979 (ps-output "EOS\n"))
3980
3981
3982 ;; [terminal width-fun dim-fun entry height width name]
3983 (defun ebnf-generate-terminal (terminal)
3984 (ebnf-gen-terminal terminal "T"))
3985
3986
3987 ;; [non-terminal width-fun dim-fun entry height width name]
3988 (defun ebnf-generate-non-terminal (non-terminal)
3989 (ebnf-gen-terminal non-terminal "NT"))
3990
3991
3992 ;; [empty width-fun dim-fun entry height width]
3993 (defun ebnf-generate-empty (empty)
3994 (ebnf-empty-alternative (ebnf-node-width empty)))
3995
3996
3997 ;; [optional width-fun dim-fun entry height width element]
3998 (defun ebnf-generate-optional (optional)
3999 (let ((the-optional (ebnf-node-list optional)))
4000 (ps-output (ebnf-format-float
4001 (+ (- (ebnf-node-height the-optional)
4002 (ebnf-node-entry optional))
4003 ebnf-vertical-space)
4004 (ebnf-node-width optional))
4005 " OP\n")
4006 (ebnf-node-generation the-optional)
4007 (ps-output "EOS\n")))
4008
4009
4010 ;; [one-or-more width-fun dim-fun entry height width element separator]
4011 (defun ebnf-generate-one-or-more (one-or-more)
4012 (let* ((width (ebnf-node-width one-or-more))
4013 (sep (ebnf-node-separator one-or-more))
4014 (entry (- (ebnf-node-entry one-or-more)
4015 (if sep
4016 (ebnf-node-entry sep)
4017 0))))
4018 (ps-output (ebnf-format-float entry width)
4019 " OM\n")
4020 (ebnf-node-generation (ebnf-node-list one-or-more))
4021 (ebnf-vertical-movement entry)
4022 (if sep
4023 (let ((ebnf-direction "L"))
4024 (ebnf-node-generation sep))
4025 (ebnf-empty-alternative (- width ebnf-horizontal-space))))
4026 (ps-output "EOS\n"))
4027
4028
4029 ;; [zero-or-more width-fun dim-fun entry height width element separator]
4030 (defun ebnf-generate-zero-or-more (zero-or-more)
4031 (let* ((width (ebnf-node-width zero-or-more))
4032 (node-list (ebnf-node-list zero-or-more))
4033 (list-entry (ebnf-node-entry node-list))
4034 (node-sep (ebnf-node-separator zero-or-more))
4035 (entry (+ list-entry
4036 ebnf-vertical-space
4037 (if node-sep
4038 (- (ebnf-node-height node-sep)
4039 (ebnf-node-entry node-sep))
4040 0))))
4041 (ps-output (ebnf-format-float entry
4042 (+ (- (ebnf-node-height node-list)
4043 list-entry)
4044 ebnf-vertical-space)
4045 width)
4046 " ZM\n")
4047 (ebnf-node-generation (ebnf-node-list zero-or-more))
4048 (ebnf-vertical-movement entry)
4049 (if (ebnf-node-separator zero-or-more)
4050 (let ((ebnf-direction "L"))
4051 (ebnf-node-generation (ebnf-node-separator zero-or-more)))
4052 (ebnf-empty-alternative (- width ebnf-horizontal-space))))
4053 (ps-output "EOS\n"))
4054
4055
4056 ;; [special width-fun dim-fun entry height width name]
4057 (defun ebnf-generate-special (special)
4058 (ebnf-gen-terminal special "SP"))
4059
4060
4061 ;; [repeat width-fun dim-fun entry height width times element]
4062 (defun ebnf-generate-repeat (repeat)
4063 (let ((times (ebnf-node-name repeat))
4064 (element (ebnf-node-separator repeat)))
4065 (ps-output-string times)
4066 (ps-output " "
4067 (ebnf-format-float
4068 (ebnf-node-entry repeat)
4069 (ebnf-node-height repeat)
4070 (ebnf-node-width repeat)
4071 (if element
4072 (+ (ebnf-node-width element)
4073 ebnf-space-R ebnf-space-R ebnf-space-R
4074 (* (length times) ebnf-font-width-R))
4075 0.0))
4076 " " ebnf-direction "RP\n")
4077 (and element
4078 (ebnf-node-generation element)))
4079 (ps-output "EOS\n"))
4080
4081
4082 ;; [except width-fun dim-fun entry height width element element]
4083 (defun ebnf-generate-except (except)
4084 (let* ((element (ebnf-node-list except))
4085 (exception (ebnf-node-separator except))
4086 (width (ebnf-node-width element)))
4087 (ps-output (ebnf-format-float
4088 width
4089 (ebnf-node-entry except)
4090 (ebnf-node-height except)
4091 (ebnf-node-width except)
4092 (+ width
4093 ebnf-space-E ebnf-space-E ebnf-space-E
4094 ebnf-font-width-E
4095 (if exception
4096 (+ (ebnf-node-width exception) ebnf-space-E)
4097 0.0)))
4098 " " ebnf-direction "EX\n")
4099 (ebnf-node-generation (ebnf-node-list except))
4100 (when exception
4101 (ebnf-horizontal-movement (+ width ebnf-space-E
4102 ebnf-font-width-E ebnf-space-E))
4103 (ebnf-node-generation exception)))
4104 (ps-output "EOS\n"))
4105
4106
4107 (defun ebnf-gen-terminal (node code)
4108 (ps-output-string (ebnf-node-name node))
4109 (ps-output " " (ebnf-format-float (ebnf-node-width node))
4110 " " ebnf-direction code
4111 (if (ebnf-node-default node)
4112 "D\n"
4113 "\n")))
4114
4115
4116 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4117 ;; Internal functions
4118
4119
4120 (defvar ebnf-map-name
4121 (let ((map (make-vector 256 ?\_)))
4122 (mapcar #'(lambda (char)
4123 (aset map char char))
4124 (concat "#$%&+-.0123456789=?@~"
4125 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
4126 "abcdefghijklmnopqrstuvwxyz"))
4127 map))
4128
4129
4130 (defun ebnf-eps-filename (str)
4131 (let* ((len (length str))
4132 (stri 0)
4133 (new (make-string len ?\ )))
4134 (while (< stri len)
4135 (aset new stri (aref ebnf-map-name (aref str stri)))
4136 (setq stri (1+ stri)))
4137 (concat ebnf-eps-prefix new ".eps")))
4138
4139
4140 (defun ebnf-eps-output (&rest args)
4141 (while args
4142 (insert (car args))
4143 (setq args (cdr args))))
4144
4145
4146 (defun ebnf-generate-region (from to gen-func)
4147 (run-hooks 'ebnf-hook)
4148 (let ((ebnf-limit (max from to))
4149 the-point)
4150 (save-excursion
4151 (save-restriction
4152 (save-match-data
4153 (condition-case data
4154 (let ((tree (ebnf-parse-and-sort (min from to))))
4155 (when gen-func
4156 (funcall gen-func
4157 (ebnf-dimensions
4158 (ebnf-optimize
4159 (ebnf-eliminate-empty-rules tree))))))
4160 ;; handler
4161 ((quit error)
4162 (ding)
4163 (setq the-point (max (1- (point)) (point-min)))
4164 (message (error-message-string data)))))))
4165 (cond
4166 (the-point
4167 (goto-char the-point))
4168 (gen-func
4169 nil)
4170 (t
4171 (message "EBNF syntatic analysis: NO ERRORS.")))))
4172
4173
4174 (defun ebnf-parse-and-sort (start)
4175 (ebnf-begin-job)
4176 (let ((tree (funcall ebnf-parser-func start)))
4177 (if ebnf-sort-production
4178 (progn
4179 (message "Sorting...")
4180 (sort tree
4181 (if (eq ebnf-sort-production 'ascending)
4182 'ebnf-sorter-ascending
4183 'ebnf-sorter-descending)))
4184 (nreverse tree))))
4185
4186
4187 (defun ebnf-sorter-ascending (first second)
4188 (string< (ebnf-node-name first)
4189 (ebnf-node-name second)))
4190
4191
4192 (defun ebnf-sorter-descending (first second)
4193 (string< (ebnf-node-name second)
4194 (ebnf-node-name first)))
4195
4196
4197 (defun ebnf-empty-alternative (width)
4198 (ps-output (ebnf-format-float width) " EA\n"))
4199
4200
4201 (defun ebnf-vertical-movement (height)
4202 (ps-output (ebnf-format-float height) " vm\n"))
4203
4204
4205 (defun ebnf-horizontal-movement (width)
4206 (ps-output (ebnf-format-float width) " hm\n"))
4207
4208
4209 (defun ebnf-entry (height)
4210 (* height ebnf-entry-percentage))
4211
4212
4213 (defun ebnf-eop-vertical (height)
4214 (ps-output (ebnf-format-float (+ height ebnf-production-vertical-space))
4215 " EOPV\n\n"))
4216
4217
4218 (defun ebnf-eop-horizontal (width)
4219 (ps-output (ebnf-format-float (+ width ebnf-production-horizontal-space))
4220 " EOPH\n\n"))
4221
4222
4223 (defun ebnf-new-page ()
4224 (when (< ps-height-remaining ps-print-height)
4225 (run-hooks 'ebnf-page-hook)
4226 (ps-next-page)
4227 (ps-output "\n")))
4228
4229
4230 (defsubst ebnf-font-size (font) (nth 0 font))
4231 (defsubst ebnf-font-name (font) (nth 1 font))
4232 (defsubst ebnf-font-foreground (font) (nth 2 font))
4233 (defsubst ebnf-font-background (font) (nth 3 font))
4234 (defsubst ebnf-font-list (font) (nthcdr 4 font))
4235 (defsubst ebnf-font-attributes (font)
4236 (lsh (ps-extension-bit (cdr font)) -2))
4237
4238
4239 (defconst ebnf-font-name-select
4240 (vector 'normal 'bold 'italic 'bold-italic))
4241
4242
4243 (defun ebnf-font-name-select (font)
4244 (let* ((font-list (ebnf-font-list font))
4245 (font-index (+ (if (memq 'bold font-list) 1 0)
4246 (if (memq 'italic font-list) 2 0)))
4247 (name (ebnf-font-name font))
4248 (database (cdr (assoc name ps-font-info-database)))
4249 (info-list (or (cdr (assoc 'fonts database))
4250 (error "Invalid font: %s" name))))
4251 (or (cdr (assoc (aref ebnf-font-name-select font-index)
4252 info-list))
4253 (error "Invalid attributes for font %s" name))))
4254
4255
4256 (defun ebnf-font-select (font select)
4257 (let* ((name (ebnf-font-name font))
4258 (database (cdr (assoc name ps-font-info-database)))
4259 (size (cdr (assoc 'size database)))
4260 (base (cdr (assoc select database))))
4261 (if (and size base)
4262 (/ (* (ebnf-font-size font) base)
4263 size)
4264 (error "Invalid font: %s" name))))
4265
4266
4267 (defsubst ebnf-font-width (font)
4268 (ebnf-font-select font 'avg-char-width))
4269 (defsubst ebnf-font-height (font)
4270 (ebnf-font-select font 'line-height))
4271
4272
4273 (defun ebnf-begin-job ()
4274 (ps-printing-region nil)
4275 (if ebnf-use-float-format
4276 (setq ebnf-format-float "%1.3f"
4277 ebnf-message-float "%3.2f")
4278 (setq ebnf-format-float "%s"
4279 ebnf-message-float "%s"))
4280 (ebnf-otz-initialize)
4281 ;; to avoid compilation gripes when calling autoloaded functions
4282 (funcall (cond ((eq ebnf-syntax 'iso-ebnf)
4283 (setq ebnf-parser-func 'ebnf-iso-parser)
4284 'ebnf-iso-initialize)
4285 ((eq ebnf-syntax 'yacc)
4286 (setq ebnf-parser-func 'ebnf-yac-parser)
4287 'ebnf-yac-initialize)
4288 (t
4289 (setq ebnf-parser-func 'ebnf-bnf-parser)
4290 'ebnf-bnf-initialize)))
4291 (and ebnf-terminal-regexp ; ensures that it's a string or nil
4292 (not (stringp ebnf-terminal-regexp))
4293 (setq ebnf-terminal-regexp nil))
4294 (or (and ebnf-eps-prefix ; ensures that it's a string
4295 (stringp ebnf-eps-prefix))
4296 (setq ebnf-eps-prefix "ebnf--"))
4297 (setq ebnf-entry-percentage ; ensures value between 0.0 and 1.0
4298 (min (max ebnf-entry-percentage 0.0) 1.0)
4299 ebnf-action-list (if ebnf-horizontal-orientation
4300 '(nil keep-line)
4301 '(keep-line))
4302 ebnf-settings nil
4303 ebnf-fonts-required nil
4304 ebnf-action nil
4305 ebnf-default-p nil
4306 ebnf-eps-context nil
4307 ebnf-eps-production-list nil
4308 ebnf-eps-upper-x 0.0
4309 ebnf-eps-upper-y 0.0
4310 ebnf-font-height-P (ebnf-font-height ebnf-production-font)
4311 ebnf-font-height-T (ebnf-font-height ebnf-terminal-font)
4312 ebnf-font-height-NT (ebnf-font-height ebnf-non-terminal-font)
4313 ebnf-font-height-S (ebnf-font-height ebnf-special-font)
4314 ebnf-font-height-E (ebnf-font-height ebnf-except-font)
4315 ebnf-font-height-R (ebnf-font-height ebnf-repeat-font)
4316 ebnf-font-width-P (ebnf-font-width ebnf-production-font)
4317 ebnf-font-width-T (ebnf-font-width ebnf-terminal-font)
4318 ebnf-font-width-NT (ebnf-font-width ebnf-non-terminal-font)
4319 ebnf-font-width-S (ebnf-font-width ebnf-special-font)
4320 ebnf-font-width-E (ebnf-font-width ebnf-except-font)
4321 ebnf-font-width-R (ebnf-font-width ebnf-repeat-font)
4322 ebnf-space-T (* ebnf-font-height-T 0.5)
4323 ebnf-space-NT (* ebnf-font-height-NT 0.5)
4324 ebnf-space-S (* ebnf-font-height-S 0.5)
4325 ebnf-space-E (* ebnf-font-height-E 0.5)
4326 ebnf-space-R (* ebnf-font-height-R 0.5))
4327 (let ((basic (+ ebnf-font-height-T ebnf-font-height-NT)))
4328 (setq ebnf-basic-width (* basic 0.5)
4329 ebnf-horizontal-space (+ basic basic)
4330 ebnf-basic-height ebnf-basic-width
4331 ebnf-vertical-space ebnf-basic-width)
4332 ;; ensures value is greater than zero
4333 (or (and (numberp ebnf-production-horizontal-space)
4334 (> ebnf-production-horizontal-space 0.0))
4335 (setq ebnf-production-horizontal-space basic))
4336 ;; ensures value is greater than zero
4337 (or (and (numberp ebnf-production-vertical-space)
4338 (> ebnf-production-vertical-space 0.0))
4339 (setq ebnf-production-vertical-space basic))))
4340
4341
4342 (defsubst ebnf-shape-value (sym alist)
4343 (or (cdr (assq sym alist)) 0))
4344
4345
4346 (defsubst ebnf-boolean (value)
4347 (if value "true" "false"))
4348
4349
4350 (defun ebnf-begin-file ()
4351 (ps-flush-output)
4352 (save-excursion
4353 (set-buffer ps-spool-buffer)
4354 (goto-char (point-min))
4355 (and (search-forward "%%Creator: " nil t)
4356 (not (search-forward "& ebnf2ps v"
4357 (save-excursion (end-of-line) (point))
4358 t))
4359 (progn
4360 ;; adjust creator comment
4361 (end-of-line)
4362 (backward-char)
4363 (insert " & ebnf2ps v" ebnf-version)
4364 ;; insert ebnf settings & engine
4365 (goto-char (point-max))
4366 (search-backward "\n%%EndPrologue\n")
4367 (ebnf-insert-ebnf-prologue)
4368 (ps-output "\n")))))
4369
4370
4371 (defun ebnf-eps-finish-and-write (buffer filename)
4372 (save-excursion
4373 (set-buffer buffer)
4374 (setq ebnf-eps-upper-x (max ebnf-eps-upper-x ebnf-eps-max-width)
4375 ebnf-eps-upper-y (if (zerop ebnf-eps-upper-y)
4376 ebnf-eps-max-height
4377 (+ ebnf-eps-upper-y
4378 ebnf-production-vertical-space
4379 ebnf-eps-max-height)))
4380 ;; prologue
4381 (goto-char (point-min))
4382 (insert
4383 "%!PS-Adobe-3.0 EPSF-3.0"
4384 "\n%%BoundingBox: 0 0 "
4385 (format "%d %d" (1+ ebnf-eps-upper-x) (1+ ebnf-eps-upper-y))
4386 "\n%%Title: " filename
4387 "\n%%CreationDate: " (time-stamp-hh:mm:ss) " " (time-stamp-mon-dd-yyyy)
4388 "\n%%Creator: " (user-full-name) " (using ebnf2ps v" ebnf-version ")"
4389 "\n%%DocumentNeededResources: font "
4390 (or ebnf-fonts-required
4391 (setq ebnf-fonts-required
4392 (let ((fonts (ps-remove-duplicates
4393 (mapcar 'ebnf-font-name-select
4394 (list ebnf-production-font
4395 ebnf-terminal-font
4396 ebnf-non-terminal-font
4397 ebnf-special-font
4398 ebnf-except-font
4399 ebnf-repeat-font)))))
4400 (concat (car fonts)
4401 (and (cdr fonts) "\n%%+ font ")
4402 (mapconcat 'identity (cdr fonts) "\n%%+ font ")))))
4403 "\n%%Pages: 0\n%%EndComments\n\n%%BeginPrologue\n"
4404 ebnf-eps-prologue)
4405 (ebnf-insert-ebnf-prologue)
4406 (insert ebnf-eps-begin
4407 "\n0 " (ebnf-format-float
4408 (- ebnf-eps-upper-y (* ebnf-font-height-P 0.7)))
4409 " #ebnf2ps#begin\n")
4410 ;; epilogue
4411 (goto-char (point-max))
4412 (insert ebnf-eps-end)
4413 ;; write file
4414 (message "Saving...")
4415 (setq filename (expand-file-name filename))
4416 (let ((coding-system-for-write 'raw-text-unix))
4417 (write-region (point-min) (point-max) filename))
4418 (message "Wrote %s" filename)))
4419
4420
4421 (defun ebnf-insert-ebnf-prologue ()
4422 (insert
4423 (or ebnf-settings
4424 (setq ebnf-settings
4425 (concat
4426 "\n\n% === begin EBNF settings\n\n"
4427 ;; production
4428 (format "/fP %s /%s DefFont\n"
4429 (ebnf-format-float (ebnf-font-size ebnf-production-font))
4430 (ebnf-font-name-select ebnf-production-font))
4431 (ebnf-format-color "/ForegroundP %s def %% %s\n"
4432 (ebnf-font-foreground ebnf-production-font)
4433 "Black")
4434 (ebnf-format-color "/BackgroundP %s def %% %s\n"
4435 (ebnf-font-background ebnf-production-font)
4436 "White")
4437 (format "/EffectP %d def\n"
4438 (ebnf-font-attributes ebnf-production-font))
4439 ;; terminal
4440 (format "/fT %s /%s DefFont\n"
4441 (ebnf-format-float (ebnf-font-size ebnf-terminal-font))
4442 (ebnf-font-name-select ebnf-terminal-font))
4443 (ebnf-format-color "/ForegroundT %s def %% %s\n"
4444 (ebnf-font-foreground ebnf-terminal-font)
4445 "Black")
4446 (ebnf-format-color "/BackgroundT %s def %% %s\n"
4447 (ebnf-font-background ebnf-terminal-font)
4448 "White")
4449 (format "/EffectT %d def\n"
4450 (ebnf-font-attributes ebnf-terminal-font))
4451 (format "/BorderWidthT %s def\n"
4452 (ebnf-format-float ebnf-terminal-border-width))
4453 (ebnf-format-color "/BorderColorT %s def %% %s\n"
4454 ebnf-terminal-border-color
4455 "Black")
4456 (format "/ShapeT %d def\n"
4457 (ebnf-shape-value ebnf-terminal-shape
4458 ebnf-terminal-shape-alist))
4459 (format "/ShadowT %s def\n"
4460 (ebnf-boolean ebnf-terminal-shadow))
4461 ;; non-terminal
4462 (format "/fNT %s /%s DefFont\n"
4463 (ebnf-format-float
4464 (ebnf-font-size ebnf-non-terminal-font))
4465 (ebnf-font-name-select ebnf-non-terminal-font))
4466 (ebnf-format-color "/ForegroundNT %s def %% %s\n"
4467 (ebnf-font-foreground ebnf-non-terminal-font)
4468 "Black")
4469 (ebnf-format-color "/BackgroundNT %s def %% %s\n"
4470 (ebnf-font-background ebnf-non-terminal-font)
4471 "White")
4472 (format "/EffectNT %d def\n"
4473 (ebnf-font-attributes ebnf-non-terminal-font))
4474 (format "/BorderWidthNT %s def\n"
4475 (ebnf-format-float ebnf-non-terminal-border-width))
4476 (ebnf-format-color "/BorderColorNT %s def %% %s\n"
4477 ebnf-non-terminal-border-color
4478 "Black")
4479 (format "/ShapeNT %d def\n"
4480 (ebnf-shape-value ebnf-non-terminal-shape
4481 ebnf-terminal-shape-alist))
4482 (format "/ShadowNT %s def\n"
4483 (ebnf-boolean ebnf-non-terminal-shadow))
4484 ;; special
4485 (format "/fS %s /%s DefFont\n"
4486 (ebnf-format-float (ebnf-font-size ebnf-special-font))
4487 (ebnf-font-name-select ebnf-special-font))
4488 (ebnf-format-color "/ForegroundS %s def %% %s\n"
4489 (ebnf-font-foreground ebnf-special-font)
4490 "Black")
4491 (ebnf-format-color "/BackgroundS %s def %% %s\n"
4492 (ebnf-font-background ebnf-special-font)
4493 "Gray95")
4494 (format "/EffectS %d def\n"
4495 (ebnf-font-attributes ebnf-special-font))
4496 (format "/BorderWidthS %s def\n"
4497 (ebnf-format-float ebnf-special-border-width))
4498 (ebnf-format-color "/BorderColorS %s def %% %s\n"
4499 ebnf-special-border-color
4500 "Black")
4501 (format "/ShapeS %d def\n"
4502 (ebnf-shape-value ebnf-special-shape
4503 ebnf-terminal-shape-alist))
4504 (format "/ShadowS %s def\n"
4505 (ebnf-boolean ebnf-special-shadow))
4506 ;; except
4507 (format "/fE %s /%s DefFont\n"
4508 (ebnf-format-float (ebnf-font-size ebnf-except-font))
4509 (ebnf-font-name-select ebnf-except-font))
4510 (ebnf-format-color "/ForegroundE %s def %% %s\n"
4511 (ebnf-font-foreground ebnf-except-font)
4512 "Black")
4513 (ebnf-format-color "/BackgroundE %s def %% %s\n"
4514 (ebnf-font-background ebnf-except-font)
4515 "Gray90")
4516 (format "/EffectE %d def\n"
4517 (ebnf-font-attributes ebnf-except-font))
4518 (format "/BorderWidthE %s def\n"
4519 (ebnf-format-float ebnf-except-border-width))
4520 (ebnf-format-color "/BorderColorE %s def %% %s\n"
4521 ebnf-except-border-color
4522 "Black")
4523 (format "/ShapeE %d def\n"
4524 (ebnf-shape-value ebnf-except-shape
4525 ebnf-terminal-shape-alist))
4526 (format "/ShadowE %s def\n"
4527 (ebnf-boolean ebnf-except-shadow))
4528 ;; repeat
4529 (format "/fR %s /%s DefFont\n"
4530 (ebnf-format-float (ebnf-font-size ebnf-repeat-font))
4531 (ebnf-font-name-select ebnf-repeat-font))
4532 (ebnf-format-color "/ForegroundR %s def %% %s\n"
4533 (ebnf-font-foreground ebnf-repeat-font)
4534 "Black")
4535 (ebnf-format-color "/BackgroundR %s def %% %s\n"
4536 (ebnf-font-background ebnf-repeat-font)
4537 "Gray85")
4538 (format "/EffectR %d def\n"
4539 (ebnf-font-attributes ebnf-repeat-font))
4540 (format "/BorderWidthR %s def\n"
4541 (ebnf-format-float ebnf-repeat-border-width))
4542 (ebnf-format-color "/BorderColorR %s def %% %s\n"
4543 ebnf-repeat-border-color
4544 "Black")
4545 (format "/ShapeR %d def\n"
4546 (ebnf-shape-value ebnf-repeat-shape
4547 ebnf-terminal-shape-alist))
4548 (format "/ShadowR %s def\n"
4549 (ebnf-boolean ebnf-repeat-shadow))
4550 ;; miscellaneous
4551 (format "/DefaultWidth %s def\n"
4552 (ebnf-format-float ebnf-default-width))
4553 (format "/LineWidth %s def\n"
4554 (ebnf-format-float ebnf-line-width))
4555 (ebnf-format-color "/LineColor %s def %% %s\n"
4556 ebnf-line-color
4557 "Black")
4558 (format "/ArrowShape %d def\n"
4559 (ebnf-shape-value ebnf-arrow-shape
4560 ebnf-arrow-shape-alist))
4561 (format "/ChartShape %d def\n"
4562 (ebnf-shape-value ebnf-chart-shape
4563 ebnf-terminal-shape-alist))
4564 (format "/UserArrow{%s}def\n"
4565 (ebnf-user-arrow ebnf-user-arrow))
4566 "\n% === end EBNF settings\n\n"
4567 (and ebnf-debug-ps ebnf-debug))))
4568 ebnf-prologue))
4569
4570
4571 (defun ebnf-user-arrow (user-arrow)
4572 "Return a user arrow shape from USER-ARROW (a PostScript code).
4573
4574 This function is only called when `ebnf-arrow-shape' is set to symbol `user'.
4575
4576 If is a string, should be a PostScript procedure body.
4577 If is a variable symbol, should contain a string.
4578 If is a function symbol, it is called and the result is applied recursively.
4579 If is a cons and car is a function symbol, it is called as:
4580 (funcall (car cons) (cdr cons))
4581 and the result is applied recursively.
4582 If is a cons and car is not a function symbol, it is applied recursively on
4583 car and cdr, and the results are concatened as:
4584 (concat RESULT-FROM-CAR \" \" RESULT-FROM-CDR)
4585 If is a list and car is a function symbol, it is called as:
4586 (apply (car list) (cdr list))
4587 and the result is applied recursively.
4588 If is a list and car is not a function symbol, it is applied recursively on
4589 each element and the resulting list is concatened as:
4590 (mapconcat 'identity RESULTING-LIST \" \")
4591 Otherwise, it is treated as an empty string."
4592 (cond
4593 ((null user-arrow)
4594 "")
4595 ((stringp user-arrow)
4596 user-arrow)
4597 ((and (symbolp user-arrow) (fboundp user-arrow))
4598 (ebnf-user-arrow (funcall user-arrow)))
4599 ((and (symbolp user-arrow) (boundp user-arrow))
4600 (ebnf-user-arrow (symbol-value user-arrow)))
4601 ((consp user-arrow)
4602 (if (and (symbolp (car user-arrow)) (fboundp (car user-arrow)))
4603 (ebnf-user-arrow (funcall (car user-arrow) (cdr user-arrow)))
4604 (concat (ebnf-user-arrow (car user-arrow))
4605 " "
4606 (ebnf-user-arrow (cdr user-arrow)))))
4607 ((listp user-arrow)
4608 (if (and (symbolp (car user-arrow))
4609 (fboundp (car user-arrow)))
4610 (ebnf-user-arrow (apply (car user-arrow) (cdr user-arrow)))
4611 (mapconcat 'ebnf-user-arrow user-arrow " ")))
4612 (t
4613 "")
4614 ))
4615
4616
4617 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4618 ;; Adjusting dimensions
4619
4620
4621 (defun ebnf-dimensions (tree)
4622 (let ((ebnf-total (length tree))
4623 (ebnf-nprod 0))
4624 (mapcar 'ebnf-production-dimension tree))
4625 tree)
4626
4627
4628 ;; [empty width-fun dim-fun entry height width]
4629 ;;(defun ebnf-empty-dimension (empty)
4630 ;; )
4631
4632
4633 ;; [production width-fun dim-fun entry height width name production action]
4634 (defun ebnf-production-dimension (production)
4635 (ebnf-message-info "Calculating dimensions")
4636 (ebnf-node-dimension-func (ebnf-node-production production))
4637 (let* ((prod (ebnf-node-production production))
4638 (height (+ ebnf-font-height-P
4639 ebnf-basic-height
4640 (ebnf-node-height prod))))
4641 (ebnf-node-entry production height)
4642 (ebnf-node-height production height)
4643 (ebnf-node-width production (+ (ebnf-node-width prod)
4644 ebnf-horizontal-space))))
4645
4646
4647 ;; [terminal width-fun dim-fun entry height width name]
4648 (defun ebnf-terminal-dimension (terminal)
4649 (ebnf-terminal-dimension1 terminal
4650 ebnf-font-height-T
4651 ebnf-font-width-T
4652 ebnf-space-T))
4653
4654
4655 ;; [non-terminal width-fun dim-fun entry height width name]
4656 (defun ebnf-non-terminal-dimension (non-terminal)
4657 (ebnf-terminal-dimension1 non-terminal
4658 ebnf-font-height-NT
4659 ebnf-font-width-NT
4660 ebnf-space-NT))
4661
4662
4663 ;; [special width-fun dim-fun entry height width name]
4664 (defun ebnf-special-dimension (special)
4665 (ebnf-terminal-dimension1 special
4666 ebnf-font-height-S
4667 ebnf-font-width-S
4668 ebnf-space-S))
4669
4670
4671 (defun ebnf-terminal-dimension1 (node font-height font-width space)
4672 (let ((height (+ space font-height space))
4673 (len (length (ebnf-node-name node))))
4674 (ebnf-node-entry node (* height 0.5))
4675 (ebnf-node-height node height)
4676 (ebnf-node-width node (+ ebnf-basic-width space
4677 (* len font-width)
4678 space ebnf-basic-width))))
4679
4680
4681 (defconst ebnf-null-vector (vector t t t 0.0 0.0 0.0))
4682
4683
4684 ;; [repeat width-fun dim-fun entry height width times element]
4685 (defun ebnf-repeat-dimension (repeat)
4686 (let ((times (ebnf-node-name repeat))
4687 (element (ebnf-node-separator repeat)))
4688 (if element
4689 (ebnf-node-dimension-func element)
4690 (setq element ebnf-null-vector))
4691 (ebnf-node-entry repeat (+ (ebnf-node-entry element)
4692 ebnf-space-R))
4693 (ebnf-node-height repeat (+ (max (ebnf-node-height element)
4694 ebnf-font-height-S)
4695 ebnf-space-R ebnf-space-R))
4696 (ebnf-node-width repeat (+ (ebnf-node-width element)
4697 ebnf-space-R ebnf-space-R ebnf-space-R
4698 ebnf-horizontal-space
4699 (* (length times) ebnf-font-width-R)))))
4700
4701
4702 ;; [except width-fun dim-fun entry height width element element]
4703 (defun ebnf-except-dimension (except)
4704 (let ((factor (ebnf-node-list except))
4705 (element (ebnf-node-separator except)))
4706 (ebnf-node-dimension-func factor)
4707 (if element
4708 (ebnf-node-dimension-func element)
4709 (setq element ebnf-null-vector))
4710 (ebnf-node-entry except (+ (max (ebnf-node-entry factor)
4711 (ebnf-node-entry element))
4712 ebnf-space-E))
4713 (ebnf-node-height except (+ (max (ebnf-node-height factor)
4714 (ebnf-node-height element))
4715 ebnf-space-E ebnf-space-E))
4716 (ebnf-node-width except (+ (ebnf-node-width factor)
4717 (ebnf-node-width element)
4718 ebnf-space-E ebnf-space-E
4719 ebnf-space-E ebnf-space-E
4720 ebnf-font-width-E
4721 ebnf-horizontal-space))))
4722
4723
4724 ;; [alternative width-fun dim-fun entry height width list]
4725 (defun ebnf-alternative-dimension (alternative)
4726 (let ((body (ebnf-node-list alternative))
4727 (lis (ebnf-node-list alternative)))
4728 (while lis
4729 (ebnf-node-dimension-func (car lis))
4730 (setq lis (cdr lis)))
4731 (let ((height 0.0)
4732 (width 0.0)
4733 (alt body)
4734 (tail (car (last body)))
4735 (entry (ebnf-node-entry (car body)))
4736 node)
4737 (while alt
4738 (setq node (car alt)
4739 alt (cdr alt)
4740 height (+ (ebnf-node-height node) height)
4741 width (max (ebnf-node-width node) width)))
4742 (ebnf-adjust-width body width)
4743 (setq height (+ height (* (1- (length body)) ebnf-vertical-space)))
4744 (ebnf-node-entry alternative (+ entry
4745 (ebnf-entry
4746 (- height entry
4747 (- (ebnf-node-height tail)
4748 (ebnf-node-entry tail))))))
4749 (ebnf-node-height alternative height)
4750 (ebnf-node-width alternative (+ width ebnf-horizontal-space))
4751 (ebnf-node-list alternative body))))
4752
4753
4754 ;; [optional width-fun dim-fun entry height width element]
4755 (defun ebnf-optional-dimension (optional)
4756 (let ((body (ebnf-node-list optional)))
4757 (ebnf-node-dimension-func body)
4758 (ebnf-node-entry optional (ebnf-node-entry body))
4759 (ebnf-node-height optional (+ (ebnf-node-height body)
4760 ebnf-vertical-space))
4761 (ebnf-node-width optional (+ (ebnf-node-width body)
4762 ebnf-horizontal-space))))
4763
4764
4765 ;; [one-or-more width-fun dim-fun entry height width element separator]
4766 (defun ebnf-one-or-more-dimension (or-more)
4767 (let ((list-part (ebnf-node-list or-more))
4768 (sep-part (ebnf-node-separator or-more)))
4769 (ebnf-node-dimension-func list-part)
4770 (and sep-part
4771 (ebnf-node-dimension-func sep-part))
4772 (let ((height (+ (if sep-part
4773 (ebnf-node-height sep-part)
4774 0.0)
4775 ebnf-vertical-space
4776 (ebnf-node-height list-part)))
4777 (width (max (if sep-part
4778 (ebnf-node-width sep-part)
4779 0.0)
4780 (ebnf-node-width list-part))))
4781 (when sep-part
4782 (ebnf-adjust-width list-part width)
4783 (ebnf-adjust-width sep-part width))
4784 (ebnf-node-entry or-more (+ (- height (ebnf-node-height list-part))
4785 (ebnf-node-entry list-part)))
4786 (ebnf-node-height or-more height)
4787 (ebnf-node-width or-more (+ width ebnf-horizontal-space)))))
4788
4789
4790 ;; [zero-or-more width-fun dim-fun entry height width element separator]
4791 (defun ebnf-zero-or-more-dimension (or-more)
4792 (let ((list-part (ebnf-node-list or-more))
4793 (sep-part (ebnf-node-separator or-more)))
4794 (ebnf-node-dimension-func list-part)
4795 (and sep-part
4796 (ebnf-node-dimension-func sep-part))
4797 (let ((height (+ (if sep-part
4798 (ebnf-node-height sep-part)
4799 0.0)
4800 ebnf-vertical-space
4801 (ebnf-node-height list-part)
4802 ebnf-vertical-space))
4803 (width (max (if sep-part
4804 (ebnf-node-width sep-part)
4805 0.0)
4806 (ebnf-node-width list-part))))
4807 (when sep-part
4808 (ebnf-adjust-width list-part width)
4809 (ebnf-adjust-width sep-part width))
4810 (ebnf-node-entry or-more height)
4811 (ebnf-node-height or-more height)
4812 (ebnf-node-width or-more (+ width ebnf-horizontal-space)))))
4813
4814
4815 ;; [sequence width-fun dim-fun entry height width list]
4816 (defun ebnf-sequence-dimension (sequence)
4817 (let ((above 0.0)
4818 (below 0.0)
4819 (width 0.0)
4820 (lis (ebnf-node-list sequence))
4821 entry node)
4822 (while lis
4823 (setq node (car lis)
4824 lis (cdr lis))
4825 (ebnf-node-dimension-func node)
4826 (setq entry (ebnf-node-entry node)
4827 above (max above entry)
4828 below (max below (- (ebnf-node-height node) entry))
4829 width (+ width (ebnf-node-width node))))
4830 (ebnf-node-entry sequence above)
4831 (ebnf-node-height sequence (+ above below))
4832 (ebnf-node-width sequence width)))
4833
4834
4835 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4836 ;; Adjusting width
4837
4838
4839 (defun ebnf-adjust-width (node width)
4840 (cond
4841 ((listp node)
4842 (prog1
4843 node
4844 (while node
4845 (setcar node (ebnf-adjust-width (car node) width))
4846 (setq node (cdr node)))))
4847 ((vectorp node)
4848 (cond
4849 ;; nothing to be done
4850 ((= width (ebnf-node-width node))
4851 node)
4852 ;; left justify term
4853 ((eq ebnf-justify-sequence 'left)
4854 (ebnf-adjust-empty node width nil))
4855 ;; right justify terms
4856 ((eq ebnf-justify-sequence 'right)
4857 (ebnf-adjust-empty node width t))
4858 ;; centralize terms
4859 (t
4860 (ebnf-node-width-func node width)
4861 (ebnf-node-width node width)
4862 node)
4863 ))
4864 (t
4865 node)
4866 ))
4867
4868
4869 (defun ebnf-adjust-empty (node width last-p)
4870 (if (eq (ebnf-node-kind node) 'ebnf-generate-empty)
4871 (progn
4872 (ebnf-node-width node width)
4873 node)
4874 (let ((empty (ebnf-make-empty (- width (ebnf-node-width node)))))
4875 (ebnf-make-dup-sequence node
4876 (if last-p
4877 (list empty node)
4878 (list node empty))))))
4879
4880
4881 ;; [terminal width-fun dim-fun entry height width name]
4882 ;; [non-terminal width-fun dim-fun entry height width name]
4883 ;; [empty width-fun dim-fun entry height width]
4884 ;; [special width-fun dim-fun entry height width name]
4885 ;; [repeat width-fun dim-fun entry height width times element]
4886 ;; [except width-fun dim-fun entry height width element element]
4887 ;;(defun ebnf-terminal-width (terminal width)
4888 ;; )
4889
4890
4891 ;; [alternative width-fun dim-fun entry height width list]
4892 ;; [optional width-fun dim-fun entry height width element]
4893 (defun ebnf-alternative-width (alternative width)
4894 (ebnf-adjust-width (ebnf-node-list alternative)
4895 (- width ebnf-horizontal-space)))
4896
4897
4898 ;; [one-or-more width-fun dim-fun entry height width element separator]
4899 ;; [zero-or-more width-fun dim-fun entry height width element separator]
4900 (defun ebnf-list-width (or-more width)
4901 (setq width (- width ebnf-horizontal-space))
4902 (ebnf-node-list or-more
4903 (ebnf-justify-list or-more
4904 (ebnf-node-list or-more)
4905 width))
4906 (ebnf-node-separator or-more
4907 (ebnf-justify-list or-more
4908 (ebnf-node-separator or-more)
4909 width)))
4910
4911
4912 ;; [sequence width-fun dim-fun entry height width list]
4913 (defun ebnf-sequence-width (sequence width)
4914 (ebnf-node-list sequence
4915 (ebnf-justify-list sequence (ebnf-node-list sequence) width)))
4916
4917
4918 (defun ebnf-justify-list (node seq width)
4919 (let ((seq-width (ebnf-node-width node)))
4920 (if (= width seq-width)
4921 seq
4922 (cond
4923 ;; left justify terms
4924 ((eq ebnf-justify-sequence 'left)
4925 (ebnf-justify node seq seq-width width t))
4926 ;; right justify terms
4927 ((eq ebnf-justify-sequence 'right)
4928 (ebnf-justify node seq seq-width width nil))
4929 ;; centralize terms
4930 (t
4931 (let ((the-width (/ (- width seq-width) (length seq)))
4932 (lis seq))
4933 (while lis
4934 (ebnf-adjust-width (car lis)
4935 (+ (ebnf-node-width (car lis))
4936 the-width))
4937 (setq lis (cdr lis)))
4938 seq))
4939 ))))
4940
4941
4942 (defun ebnf-justify (node seq seq-width width last-p)
4943 (let ((term (car (if last-p (last seq) seq))))
4944 (cond
4945 ;; adjust empty term
4946 ((eq (ebnf-node-kind term) 'ebnf-generate-empty)
4947 (ebnf-node-width term (+ (- width seq-width)
4948 (ebnf-node-width term)))
4949 seq)
4950 ;; insert empty at end ==> left justify
4951 (last-p
4952 (nconc seq
4953 (list (ebnf-make-empty (- width seq-width)))))
4954 ;; insert empty at beginning ==> right justify
4955 (t
4956 (cons (ebnf-make-empty (- width seq-width))
4957 seq))
4958 )))
4959
4960
4961 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4962 ;; Functions used by parsers
4963
4964
4965 (defun ebnf-eps-add-context (name)
4966 (let ((filename (ebnf-eps-filename name)))
4967 (if (member filename ebnf-eps-context)
4968 (error "Try to open an already opened EPS file: %s" filename)
4969 (setq ebnf-eps-context (cons filename ebnf-eps-context)))))
4970
4971
4972 (defun ebnf-eps-remove-context (name)
4973 (let ((filename (ebnf-eps-filename name)))
4974 (if (member filename ebnf-eps-context)
4975 (setq ebnf-eps-context (delete filename ebnf-eps-context))
4976 (error "Try to close a not opened EPS file: %s" filename))))
4977
4978
4979 (defun ebnf-eps-add-production (header)
4980 (and ebnf-eps-executing
4981 ebnf-eps-context
4982 (let ((prod (assoc header ebnf-eps-production-list)))
4983 (if prod
4984 (setcdr prod (append ebnf-eps-context (cdr prod)))
4985 (setq ebnf-eps-production-list
4986 (cons (cons header (ebnf-dup-list ebnf-eps-context))
4987 ebnf-eps-production-list))))))
4988
4989
4990 (defun ebnf-dup-list (old)
4991 (let (new)
4992 (while old
4993 (setq new (cons (car old) new)
4994 old (cdr old)))
4995 (nreverse new)))
4996
4997
4998 (defun ebnf-buffer-substring (chars)
4999 (buffer-substring-no-properties
5000 (point)
5001 (progn
5002 (skip-chars-forward chars ebnf-limit)
5003 (point))))
5004
5005
5006 (defun ebnf-string (chars eos-char kind)
5007 (forward-char)
5008 (buffer-substring-no-properties
5009 (point)
5010 (progn
5011 (skip-chars-forward (concat chars "\240-\377") ebnf-limit)
5012 (if (or (eobp) (/= (following-char) eos-char))
5013 (error "Illegal %s: missing `%c'." kind eos-char)
5014 (forward-char)
5015 (1- (point))))))
5016
5017
5018 (defun ebnf-get-string ()
5019 (forward-char)
5020 (buffer-substring-no-properties (point) (ebnf-end-of-string)))
5021
5022
5023 (defun ebnf-end-of-string ()
5024 (let ((n 1))
5025 (while (> (logand n 1) 0)
5026 (skip-chars-forward "^\"" ebnf-limit)
5027 (setq n (- (skip-chars-backward "\\\\")))
5028 (goto-char (+ (point) n 1))))
5029 (if (= (preceding-char) ?\")
5030 (1- (point))
5031 (error "Missing `\"'.")))
5032
5033
5034 (defun ebnf-trim-right (str)
5035 (let* ((len (1- (length str)))
5036 (index len))
5037 (while (and (> index 0) (= (aref str index) ?\ ))
5038 (setq index (1- index)))
5039 (if (= index len)
5040 str
5041 (substring str 0 (1+ index)))))
5042
5043
5044 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5045 ;; Vector creation
5046
5047
5048 (defun ebnf-make-empty (&optional width)
5049 (vector 'ebnf-generate-empty
5050 'ignore
5051 'ignore
5052 0.0
5053 0.0
5054 (or width ebnf-horizontal-space)))
5055
5056
5057 (defun ebnf-make-terminal (name)
5058 (ebnf-make-terminal1 name
5059 'ebnf-generate-terminal
5060 'ebnf-terminal-dimension))
5061
5062
5063 (defun ebnf-make-non-terminal (name)
5064 (ebnf-make-terminal1 name
5065 'ebnf-generate-non-terminal
5066 'ebnf-non-terminal-dimension))
5067
5068
5069 (defun ebnf-make-special (name)
5070 (ebnf-make-terminal1 name
5071 'ebnf-generate-special
5072 'ebnf-special-dimension))
5073
5074
5075 (defun ebnf-make-terminal1 (name gen-func dim-func)
5076 (vector gen-func
5077 'ignore
5078 dim-func
5079 0.0
5080 0.0
5081 0.0
5082 (let ((len (length name)))
5083 (cond ((> len 2) name)
5084 ((= len 2) (concat " " name))
5085 ((= len 1) (concat " " name " "))
5086 (t " ")))
5087 ebnf-default-p))
5088
5089
5090 (defun ebnf-make-one-or-more (list-part &optional sep-part)
5091 (ebnf-make-or-more1 'ebnf-generate-one-or-more
5092 'ebnf-one-or-more-dimension
5093 list-part
5094 sep-part))
5095
5096
5097 (defun ebnf-make-zero-or-more (list-part &optional sep-part)
5098 (ebnf-make-or-more1 'ebnf-generate-zero-or-more
5099 'ebnf-zero-or-more-dimension
5100 list-part
5101 sep-part))
5102
5103
5104 (defun ebnf-make-or-more1 (gen-func dim-func list-part sep-part)
5105 (vector gen-func
5106 'ebnf-list-width
5107 dim-func
5108 0.0
5109 0.0
5110 0.0
5111 (if (listp list-part)
5112 (ebnf-make-sequence list-part)
5113 list-part)
5114 (if (and sep-part (listp sep-part))
5115 (ebnf-make-sequence sep-part)
5116 sep-part)))
5117
5118
5119 (defun ebnf-make-production (name prod action)
5120 (vector 'ebnf-generate-production
5121 'ignore
5122 'ebnf-production-dimension
5123 0.0
5124 0.0
5125 0.0
5126 name
5127 prod
5128 action))
5129
5130
5131 (defun ebnf-make-alternative (body)
5132 (vector 'ebnf-generate-alternative
5133 'ebnf-alternative-width
5134 'ebnf-alternative-dimension
5135 0.0
5136 0.0
5137 0.0
5138 body))
5139
5140
5141 (defun ebnf-make-optional (body)
5142 (vector 'ebnf-generate-optional
5143 'ebnf-alternative-width
5144 'ebnf-optional-dimension
5145 0.0
5146 0.0
5147 0.0
5148 body))
5149
5150
5151 (defun ebnf-make-except (factor exception)
5152 (vector 'ebnf-generate-except
5153 'ignore
5154 'ebnf-except-dimension
5155 0.0
5156 0.0
5157 0.0
5158 factor
5159 exception))
5160
5161
5162 (defun ebnf-make-repeat (times primary)
5163 (vector 'ebnf-generate-repeat
5164 'ignore
5165 'ebnf-repeat-dimension
5166 0.0
5167 0.0
5168 0.0
5169 (concat times " *")
5170 primary))
5171
5172
5173 (defun ebnf-make-sequence (seq)
5174 (vector 'ebnf-generate-sequence
5175 'ebnf-sequence-width
5176 'ebnf-sequence-dimension
5177 0.0
5178 0.0
5179 0.0
5180 seq))
5181
5182
5183 (defun ebnf-make-dup-sequence (node seq)
5184 (vector 'ebnf-generate-sequence
5185 'ebnf-sequence-width
5186 'ebnf-sequence-dimension
5187 (ebnf-node-entry node)
5188 (ebnf-node-height node)
5189 (ebnf-node-width node)
5190 seq))
5191
5192
5193 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5194 ;; Optimizers used by parsers
5195
5196
5197 (defun ebnf-token-except (element exception)
5198 (cons (prog1
5199 (car exception)
5200 (setq exception (cdr exception)))
5201 (and element ; EMPTY - A ==> EMPTY
5202 (let ((kind (ebnf-node-kind element)))
5203 (cond
5204 ;; [ A ]- ==> A
5205 ((and (null exception)
5206 (eq kind 'ebnf-generate-optional))
5207 (ebnf-node-list element))
5208 ;; { A }- ==> { A }+
5209 ((and (null exception)
5210 (eq kind 'ebnf-generate-zero-or-more))
5211 (ebnf-node-kind element 'ebnf-generate-one-or-more)
5212 (ebnf-node-dimension-func element 'ebnf-one-or-more-dimension)
5213 element)
5214 ;; ( A | EMPTY )- ==> A
5215 ;; ( A | B | EMPTY )- ==> A | B
5216 ((and (null exception)
5217 (eq kind 'ebnf-generate-alternative)
5218 (eq (ebnf-node-kind (car (last (ebnf-node-list element))))
5219 'ebnf-generate-empty))
5220 (let ((elt (ebnf-node-list element))
5221 bef)
5222 (while (cdr elt)
5223 (setq bef elt
5224 elt (cdr elt)))
5225 (if (null bef)
5226 ;; this should not happen!!?!
5227 (setq element (ebnf-make-empty
5228 (ebnf-node-width element)))
5229 (setcdr bef nil)
5230 (setq elt (ebnf-node-list element))
5231 (and (= (length elt) 1)
5232 (setq element (car elt))))
5233 element))
5234 ;; A - B
5235 (t
5236 (ebnf-make-except element exception))
5237 )))))
5238
5239
5240 (defun ebnf-token-repeat (times repeat)
5241 (if (null (cdr repeat))
5242 ;; n * EMPTY ==> EMPTY
5243 repeat
5244 ;; n * term
5245 (cons (car repeat)
5246 (ebnf-make-repeat times (cdr repeat)))))
5247
5248
5249 (defun ebnf-token-optional (body)
5250 (let ((kind (ebnf-node-kind body)))
5251 (cond
5252 ;; [ EMPTY ] ==> EMPTY
5253 ((eq kind 'ebnf-generate-empty)
5254 nil)
5255 ;; [ { A }* ] ==> { A }*
5256 ((eq kind 'ebnf-generate-zero-or-more)
5257 body)
5258 ;; [ { A }+ ] ==> { A }*
5259 ((eq kind 'ebnf-generate-one-or-more)
5260 (ebnf-node-kind body 'ebnf-generate-zero-or-more)
5261 body)
5262 ;; [ A | B ] ==> A | B | EMPTY
5263 ((eq kind 'ebnf-generate-alternative)
5264 (ebnf-node-list body (nconc (ebnf-node-list body)
5265 (list (ebnf-make-empty))))
5266 body)
5267 ;; [ A ]
5268 (t
5269 (ebnf-make-optional body))
5270 )))
5271
5272
5273 (defun ebnf-token-alternative (body sequence)
5274 (if (null body)
5275 (if (cdr sequence)
5276 sequence
5277 (cons (car sequence)
5278 (ebnf-make-empty)))
5279 (cons (car sequence)
5280 (let ((seq (cdr sequence)))
5281 (if (and (= (length body) 1) (null seq))
5282 (car body)
5283 (ebnf-make-alternative (nreverse (if seq
5284 (cons seq body)
5285 body))))))))
5286
5287
5288 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5289 ;; Variables used by parsers
5290
5291
5292 (defconst ebnf-comment-table
5293 (let ((table (make-vector 256 nil)))
5294 ;; Override special comment character:
5295 (aset table ?< 'newline)
5296 (aset table ?> 'keep-line)
5297 table)
5298 "Vector used to map characters to a special comment token.")
5299
5300
5301 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5302 ;; To make this file smaller, some commands go in a separate file.
5303 ;; But autoload them here to make the separation invisible.
5304
5305 (autoload 'ebnf-bnf-parser "ebnf-bnf"
5306 "EBNF parser.")
5307
5308 (autoload 'ebnf-bnf-initialize "ebnf-bnf"
5309 "Initialize EBNF token table.")
5310
5311 (autoload 'ebnf-iso-parser "ebnf-iso"
5312 "ISO EBNF parser.")
5313
5314 (autoload 'ebnf-iso-initialize "ebnf-iso"
5315 "Initialize ISO EBNF token table.")
5316
5317 (autoload 'ebnf-yac-parser "ebnf-yac"
5318 "Yacc/Bison parser.")
5319
5320 (autoload 'ebnf-yac-initialize "ebnf-yac"
5321 "Initializations for Yacc/Bison parser.")
5322
5323 (autoload 'ebnf-eliminate-empty-rules "ebnf-otz"
5324 "Eliminate empty rules.")
5325
5326 (autoload 'ebnf-optimize "ebnf-otz"
5327 "Syntatic chart optimizer.")
5328
5329 (autoload 'ebnf-otz-initialize "ebnf-otz"
5330 "Initialize optimizer.")
5331
5332
5333 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5334
5335
5336 (provide 'ebnf2ps)
5337
5338
5339 ;;; ebnf2ps.el ends here