1 ;;; ebnf2ps.el --- translate an EBNF to a syntactic chart on PostScript
3 ;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
4 ;; Free Software Foundation, Inc.
6 ;; Author: Vinicius Jose Latorre <viniciusjl@ig.com.br>
7 ;; Maintainer: Vinicius Jose Latorre <viniciusjl@ig.com.br>
8 ;; Keywords: wp, ebnf, PostScript
10 ;; X-URL: http://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre
12 ;; This file is part of GNU Emacs.
14 ;; GNU Emacs is free software; you can redistribute it and/or modify
15 ;; it under the terms of the GNU General Public License as published by
16 ;; the Free Software Foundation; either version 3, or (at your option)
19 ;; GNU Emacs is distributed in the hope that it will be useful,
20 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 ;; GNU General Public License for more details.
24 ;; You should have received a copy of the GNU General Public License
25 ;; along with GNU Emacs; see the file COPYING. If not, write to the
26 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
27 ;; Boston, MA 02110-1301, USA.
29 (defconst ebnf-version
"4.3"
30 "ebnf2ps.el, v 4.3 <2006/09/26 vinicius>
32 Vinicius's last change version. When reporting bugs, please also
33 report the version of Emacs, if any, that ebnf2ps was running with.
35 Please send all bug fixes and enhancements to
36 Vinicius Jose Latorre <viniciusjl@ig.com.br>.
42 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
47 ;; This package translates an EBNF to a syntactic chart on PostScript.
49 ;; To use ebnf2ps, insert in your ~/.emacs:
53 ;; ebnf2ps uses ps-print package (version 5.2.3 or later), so see ps-print to
54 ;; know how to set options like landscape printing, page headings, margins,
57 ;; NOTE: ps-print zebra stripes and line number options doesn't have effect on
58 ;; ebnf2ps, they behave as it's turned off.
60 ;; For good performance, be sure to byte-compile ebnf2ps.el, e.g.
62 ;; M-x byte-compile-file <give the path to ebnf2ps.el when prompted>
64 ;; This will generate ebnf2ps.elc, which will be loaded instead of ebnf2ps.el.
66 ;; ebnf2ps was tested with GNU Emacs 20.4.1.
72 ;; ebnf2ps provides the following commands for generating PostScript syntactic
73 ;; chart images of Emacs buffers:
75 ;; ebnf-print-directory
79 ;; ebnf-spool-directory
88 ;; These commands all perform essentially the same function: they generate
89 ;; PostScript syntactic chart images suitable for printing on a PostScript
90 ;; printer or displaying with GhostScript. These commands are collectively
91 ;; referred to as "ebnf- commands".
93 ;; The word "print", "spool" and "eps" in the command name determines when the
94 ;; PostScript image is sent to the printer (or file):
96 ;; print - The PostScript image is immediately sent to the printer;
98 ;; spool - The PostScript image is saved temporarily in an Emacs buffer.
99 ;; Many images may be spooled locally before printing them. To
100 ;; send the spooled images to the printer, use the command
103 ;; eps - The PostScript image is immediately sent to an EPS file.
105 ;; The spooling mechanism is the same as used by ps-print and was designed for
106 ;; printing lots of small files to save paper that would otherwise be wasted on
107 ;; banner pages, and to make it easier to find your output at the printer (it's
108 ;; easier to pick up one 50-page printout than to find 50 single-page
109 ;; printouts). As ebnf2ps and ps-print use the same Emacs buffer to spool
110 ;; images, you can intermix the spooling of ebnf2ps and ps-print images.
112 ;; ebnf2ps use the same hook of ps-print in the `kill-emacs-hook' so that you
113 ;; won't accidentally quit from Emacs while you have unprinted PostScript
114 ;; waiting in the spool buffer. If you do attempt to exit with spooled
115 ;; PostScript, you'll be asked if you want to print it, and if you decline,
116 ;; you'll be asked to confirm the exit; this is modeled on the confirmation
117 ;; that Emacs uses for modified buffers.
119 ;; The word "directory", "file", "buffer" or "region" in the command name
120 ;; determines how much of the buffer is printed:
122 ;; directory - Read files in the directory and print them.
124 ;; file - Read file and print it.
126 ;; buffer - Print the entire buffer.
128 ;; region - Print just the current region.
130 ;; Two ebnf- command examples:
132 ;; ebnf-print-buffer - translate and print the entire buffer, and send it
133 ;; immediately to the printer.
135 ;; ebnf-spool-region - translate and print just the current region, and
136 ;; spool the image in Emacs to send to the printer
139 ;; Note that `ebnf-eps-directory', `ebnf-eps-file', `ebnf-eps-buffer' and
140 ;; `ebnf-eps-region' never spool the EPS image, so they don't use the ps-print
141 ;; spooling mechanism. See section "Actions in Comments" for an explanation
142 ;; about EPS file generation.
148 ;; To translate and print your buffer, type
150 ;; M-x ebnf-print-buffer
152 ;; or substitute one of the other four ebnf- commands. The command will
153 ;; generate the PostScript image and print or spool it as specified. By giving
154 ;; the command a prefix argument
156 ;; C-u M-x ebnf-print-buffer
158 ;; it will save the PostScript image to a file instead of sending it to the
159 ;; printer; you will be prompted for the name of the file to save the image to.
160 ;; The prefix argument is ignored by the commands that spool their images, but
161 ;; you may save the spooled images to a file by giving a prefix argument to
164 ;; C-u M-x ebnf-despool
166 ;; When invoked this way, `ebnf-despool' will prompt you for the name of the
169 ;; The prefix argument is also ignored by `ebnf-eps-buffer' and
170 ;; `ebnf-eps-region'.
172 ;; Any of the `ebnf-' commands can be bound to keys. Here are some examples:
174 ;; (global-set-key 'f22 'ebnf-print-buffer) ;f22 is prsc
175 ;; (global-set-key '(shift f22) 'ebnf-print-region)
176 ;; (global-set-key '(control f22) 'ebnf-despool)
179 ;; Invoking Ebnf2ps in Batch
180 ;; -------------------------
182 ;; It's possible also to run ebnf2ps in batch, this is useful when, for
183 ;; example, you have a directory with a lot of files containing the EBNF to be
184 ;; translated to PostScript.
186 ;; To run ebnf2ps in batch type, for example:
188 ;; emacs -batch -l setup-ebnf2ps.el -f ebnf-eps-directory
190 ;; Where setup-ebnf2ps.el should be a file containing:
192 ;; ;; set load-path if ebnf2ps isn't installed in your Emacs environment
193 ;; (setq load-path (append (list "/dir/of/ebnf2ps") load-path))
194 ;; (require 'ebnf2ps)
195 ;; ;; insert here your ebnf2ps settings
196 ;; (setq ebnf-terminal-shape 'bevel)
203 ;; BNF (Backus Naur Form) notation is defined like languages, and like
204 ;; languages there are rules about name formation and syntax. In this section
205 ;; it's defined a BNF syntax that it's called simply EBNF (Extended BNF).
206 ;; ebnf2ps package also deal with other BNF notation. Please, see the variable
207 ;; `ebnf-syntax' documentation below in this section.
209 ;; The current EBNF that ebnf2ps accepts has the following constructions:
211 ;; ; comment (until end of line)
215 ;; $A default non-terminal (see text below)
216 ;; $"C" default terminal (see text below)
217 ;; $?C? default special (see text below)
218 ;; A = B. production (A is the header and B the body)
219 ;; C D sequence (C occurs before D)
220 ;; C | D alternative (C or D occurs)
221 ;; A - B exception (A excluding B, B without any non-terminal)
222 ;; n * A repetition (A repeats at least n (integer) times)
223 ;; n * n A repetition (A repeats exactly n (integer) times)
224 ;; n * m A repetition (A repeats at least n (integer) and at most
225 ;; m (integer) times)
226 ;; (C) group (expression C is grouped together)
227 ;; [C] optional (C may or not occurs)
228 ;; C+ one or more occurrences of C
229 ;; {C}+ one or more occurrences of C
230 ;; {C}* zero or more occurrences of C
231 ;; {C} zero or more occurrences of C
232 ;; C / D equivalent to: C {D C}*
233 ;; {C || D}+ equivalent to: C {D C}*
234 ;; {C || D}* equivalent to: [C {D C}*]
235 ;; {C || D} equivalent to: [C {D C}*]
237 ;; The EBNF syntax written using the notation above is:
239 ;; EBNF = {production}+.
241 ;; production = non_terminal "=" body ".". ;; production
243 ;; body = {sequence || "|"}*. ;; alternative
245 ;; sequence = {exception}*. ;; sequence
247 ;; exception = repeat [ "-" repeat]. ;; exception
249 ;; repeat = [ integer "*" [ integer ]] term. ;; repetition
252 ;; | [factor] "+" ;; one-or-more
253 ;; | [factor] "/" [factor] ;; one-or-more
256 ;; factor = [ "$" ] "\"" terminal "\"" ;; terminal
257 ;; | [ "$" ] non_terminal ;; non-terminal
258 ;; | [ "$" ] "?" special "?" ;; special
259 ;; | "(" body ")" ;; group
260 ;; | "[" body "]" ;; zero-or-one
261 ;; | "{" body [ "||" body ] "}+" ;; one-or-more
262 ;; | "{" body [ "||" body ] "}*" ;; zero-or-more
263 ;; | "{" body [ "||" body ] "}" ;; zero-or-more
266 ;; non_terminal = "[!#%&'*-,0-:<>@-Z\\\\^-z~\\240-\\377]+".
267 ;; ;; that is, a valid non_terminal accepts decimal digits, letters (upper
268 ;; ;; and lower), 8-bit accentuated characters,
269 ;; ;; "!", "#", "%", "&", "'", "*", "+", ",", ":",
270 ;; ;; "<", ">", "@", "\", "^", "_", "`" and "~".
272 ;; terminal = "\\([^\"\\]\\|\\\\[ -~\\240-\\377]\\)+".
273 ;; ;; that is, a valid terminal accepts any printable character (including
274 ;; ;; 8-bit accentuated characters) except `"', as `"' is used to delimit a
275 ;; ;; terminal. Also, accepts escaped characters, that is, a character
276 ;; ;; pair starting with `\' followed by a printable character, for
277 ;; ;; example: \", \\.
279 ;; special = "[^?\\000-\\010\\012-\\037\\177-\\237]*".
280 ;; ;; that is, a valid special accepts any printable character (including
281 ;; ;; 8-bit accentuated characters) and tabs except `?', as `?' is used to
282 ;; ;; delimit a special.
284 ;; integer = "[0-9]+".
285 ;; ;; that is, an integer is a sequence of one or more decimal digits.
287 ;; comment = ";" "[^\\n\\000-\\010\\016-\\037\\177-\\237]*" "\\n".
288 ;; ;; that is, a comment starts with the character `;' and terminates at end
289 ;; ;; of line. Also, it only accepts printable characters (including 8-bit
290 ;; ;; accentuated characters) and tabs.
292 ;; Try to use the above EBNF to test ebnf2ps.
294 ;; The `default' terminal, non-terminal and special is a way to indicate a
295 ;; default path in a production. For example, the production:
297 ;; X = [ $A ( B | $C ) | D ].
299 ;; Indicates that the default meaning for "X" is "A C" if "X" is empty.
301 ;; The terminal name is controlled by `ebnf-terminal-regexp' and
302 ;; `ebnf-case-fold-search', so it's possible to match other kind of terminal
303 ;; name besides that enclosed by `"'.
305 ;; Let's see an example:
307 ;; (setq ebnf-terminal-regexp "[A-Z][_A-Z]*") ; upper case name
308 ;; (setq ebnf-case-fold-search nil) ; exact matching
310 ;; If you have the production:
312 ;; Logical = "(" Expression ( OR | AND | "XOR" ) Expression ")".
314 ;; The names are classified as:
316 ;; Logical Expression non-terminal
317 ;; "(" OR AND "XOR" ")" terminal
319 ;; The line comment is controlled by `ebnf-lex-comment-char'. The default
320 ;; value is ?\; (character `;').
322 ;; The end of production is controlled by `ebnf-lex-eop-char'. The default
323 ;; value is ?. (character `.').
325 ;; The variable `ebnf-syntax' specifies which syntax to recognize:
327 ;; `ebnf' ebnf2ps recognizes the syntax described above.
328 ;; The following variables *ONLY* have effect with this
330 ;; `ebnf-terminal-regexp', `ebnf-case-fold-search',
331 ;; `ebnf-lex-comment-char' and `ebnf-lex-eop-char'.
333 ;; `abnf' ebnf2ps recognizes the syntax described in the URL:
334 ;; `http://www.ietf.org/rfc/rfc2234.txt'
335 ;; ("Augmented BNF for Syntax Specifications: ABNF").
337 ;; `iso-ebnf' ebnf2ps recognizes the syntax described in the URL:
338 ;; `http://www.cl.cam.ac.uk/~mgk25/iso-ebnf.html'
339 ;; ("International Standard of the ISO EBNF Notation").
340 ;; The following variables *ONLY* have effect with this
342 ;; `ebnf-iso-alternative-p' and `ebnf-iso-normalize-p'.
344 ;; `yacc' ebnf2ps recognizes the Yacc/Bison syntax.
345 ;; The following variable *ONLY* has effect with this
347 ;; `ebnf-yac-ignore-error-recovery'.
349 ;; `ebnfx' ebnf2ps recognizes the syntax described in the URL:
350 ;; `http://www.w3.org/TR/2004/REC-xml-20040204/#sec-notation'
351 ;; ("Extensible Markup Language (XML) 1.0 (Third Edition)")
353 ;; `dtd' ebnf2ps recognizes the syntax described in the URL:
354 ;; `http://www.w3.org/TR/2004/REC-xml-20040204/'
355 ;; ("Extensible Markup Language (XML) 1.0 (Third Edition)")
357 ;; Any other value is treated as `ebnf'.
359 ;; The default value is `ebnf'.
365 ;; The following EBNF optimizations are done:
367 ;; [ { A }* ] ==> { A }*
368 ;; [ { A }+ ] ==> { A }*
369 ;; [ A ] + ==> { A }*
370 ;; { A }* + ==> { A }*
371 ;; { A }+ + ==> { A }+
374 ;; ( A | EMPTY )- ==> A
375 ;; ( A | B | EMPTY )- ==> A | B
376 ;; [ A | B ] ==> A | B | EMPTY
377 ;; n * EMPTY ==> EMPTY
379 ;; EMPTY / EMPTY ==> EMPTY
380 ;; EMPTY - A ==> EMPTY
382 ;; The following optimizations are done when `ebnf-optimize' is non-nil:
385 ;; 1. A = B | A C. ==> A = B {C}*.
386 ;; 2. A = B | A B. ==> A = {B}+.
387 ;; 3. A = | A B. ==> A = {B}*.
388 ;; 4. A = B | A C B. ==> A = {B || C}+.
389 ;; 5. A = B | D | A C | A E. ==> A = ( B | D ) { C | E }*.
392 ;; 6. A = B | . ==> A = [B].
393 ;; 7. A = | B . ==> A = [B].
396 ;; 8. A = B C | B D. ==> A = B (C | D).
397 ;; 9. A = C B | D B. ==> A = (C | D) B.
398 ;; 10. A = B C E | B D E. ==> A = B (C | D) E.
400 ;; The above optimizations are specially useful when `ebnf-syntax' is `yacc'.
406 ;; You may use form feed (^L \014) to force a production to start on a new
407 ;; page, for example:
416 ;; c) A = B ^L^L^L | C.^L
420 ;; In all examples above, only the production X will start on a new page.
423 ;; Actions in Comments
424 ;; -------------------
426 ;; ebnf2ps accepts the following actions in comments:
428 ;; ;^ same as form feed. See section Form Feed above.
430 ;; ;> the next production starts in the same line as the current one.
431 ;; It is useful when `ebnf-horizontal-orientation' is nil.
433 ;; ;< the next production starts in the next line.
434 ;; It is useful when `ebnf-horizontal-orientation' is non-nil.
436 ;; ;[EPS open a new EPS file. The EPS file name has the form:
437 ;; <PREFIX><NAME>.eps
438 ;; where <PREFIX> is given by variable `ebnf-eps-prefix' and
439 ;; <NAME> is the string given by ;[ action comment, this string is
440 ;; mapped to form a valid file name (see documentation for
441 ;; `ebnf-eps-buffer' or `ebnf-eps-region').
442 ;; It has effect only during `ebnf-eps-buffer' or
443 ;; `ebnf-eps-region' execution.
444 ;; It's an error to try to open an already opened EPS file.
446 ;; ;]EPS close an opened EPS file.
447 ;; It has effect only during `ebnf-eps-buffer' or
448 ;; `ebnf-eps-region' execution.
449 ;; It's an error to try to close a not opened EPS file.
453 ;; (setq ebnf-horizontal-orientation nil)
457 ;; ;> C and B are drawn in the same line
461 ;; The graphical result is:
467 ;; +---------+ +-----+
479 ;; Note that if ascending production sort is used, the productions A and B will
480 ;; be drawn in the same line instead of C and B.
482 ;; If consecutive actions occur, only the last one takes effect, so if you
491 ;; Only the ;> will take effect, that is, A and B will be drawn in the same
494 ;; In ISO EBNF the above actions are specified as (*^*), (*>*), (*<*), (*[EPS*)
495 ;; and (*]EPS*). The first example above should be written:
499 ;; (*> C and B are drawn in the same line *)
503 ;; For an example of EPS action when executing `ebnf-eps-buffer' or
504 ;; `ebnf-eps-region':
523 ;; The following table summarizes the results:
525 ;; EPS FILE NAME NO SORT ASCENDING SORT DESCENDING SORT
526 ;; ebnf--AA.eps A C A C C A
527 ;; ebnf--BB.eps C B B C C B
528 ;; ebnf--CC.eps A C B F A B C F F C B A
534 ;; As you can see if EPS actions is not used, each single production is
535 ;; generated per EPS file. To avoid overriding EPS files, use names in ;[ that
536 ;; it's not an existing production name.
538 ;; In the following case:
546 ;; The production A is generated in both files ebnf--AA.eps and ebnf--BB.eps.
552 ;; Some tools are provided to help you.
554 ;; `ebnf-setup' returns the current setup.
556 ;; `ebnf-syntax-directory' does a syntactic analysis of your EBNF files in the
559 ;; `ebnf-syntax-file' does a syntactic analysis of your EBNF in the given
562 ;; `ebnf-syntax-buffer' does a syntactic analysis of your EBNF in the current
565 ;; `ebnf-syntax-region' does a syntactic analysis of your EBNF in the current
568 ;; `ebnf-customize' activates a customization buffer for ebnf2ps options.
570 ;; `ebnf-syntax-directory', `ebnf-syntax-file', `ebnf-syntax-buffer',
571 ;; `ebnf-syntax-region' and `ebnf-customize' can be bound to keys in the same
572 ;; way as `ebnf-' commands.
578 ;; ebn2ps has the following hook variables:
581 ;; It is evaluated once before any ebnf2ps process.
583 ;; `ebnf-production-hook'
584 ;; It is evaluated on each beginning of production.
587 ;; It is evaluated on each beginning of page.
593 ;; Below it's shown a brief description of ebnf2ps options, please, see the
594 ;; options declaration in the code for a long documentation.
596 ;; `ebnf-horizontal-orientation' Non-nil means productions are drawn
599 ;; `ebnf-horizontal-max-height' Non-nil means to use maximum production
600 ;; height in horizontal orientation.
602 ;; `ebnf-production-horizontal-space' Specify horizontal space in points
603 ;; between productions.
605 ;; `ebnf-production-vertical-space' Specify vertical space in points
606 ;; between productions.
608 ;; `ebnf-justify-sequence' Specify justification of terms in a
609 ;; sequence inside alternatives.
611 ;; `ebnf-terminal-regexp' Specify how it's a terminal name.
613 ;; `ebnf-case-fold-search' Non-nil means ignore case on matching.
615 ;; `ebnf-terminal-font' Specify terminal font.
617 ;; `ebnf-terminal-shape' Specify terminal box shape.
619 ;; `ebnf-terminal-shadow' Non-nil means terminal box will have a
622 ;; `ebnf-terminal-border-width' Specify border width for terminal box.
624 ;; `ebnf-terminal-border-color' Specify border color for terminal box.
626 ;; `ebnf-production-name-p' Non-nil means production name will be
629 ;; `ebnf-sort-production' Specify how productions are sorted.
631 ;; `ebnf-production-font' Specify production font.
633 ;; `ebnf-non-terminal-font' Specify non-terminal font.
635 ;; `ebnf-non-terminal-shape' Specify non-terminal box shape.
637 ;; `ebnf-non-terminal-shadow' Non-nil means non-terminal box will
640 ;; `ebnf-non-terminal-border-width' Specify border width for non-terminal
643 ;; `ebnf-non-terminal-border-color' Specify border color for non-terminal
646 ;; `ebnf-special-show-delimiter' Non-nil means special delimiter
647 ;; (character `?') is shown.
649 ;; `ebnf-special-font' Specify special font.
651 ;; `ebnf-special-shape' Specify special box shape.
653 ;; `ebnf-special-shadow' Non-nil means special box will have a
656 ;; `ebnf-special-border-width' Specify border width for special box.
658 ;; `ebnf-special-border-color' Specify border color for special box.
660 ;; `ebnf-except-font' Specify except font.
662 ;; `ebnf-except-shape' Specify except box shape.
664 ;; `ebnf-except-shadow' Non-nil means except box will have a
667 ;; `ebnf-except-border-width' Specify border width for except box.
669 ;; `ebnf-except-border-color' Specify border color for except box.
671 ;; `ebnf-repeat-font' Specify repeat font.
673 ;; `ebnf-repeat-shape' Specify repeat box shape.
675 ;; `ebnf-repeat-shadow' Non-nil means repeat box will have a
678 ;; `ebnf-repeat-border-width' Specify border width for repeat box.
680 ;; `ebnf-repeat-border-color' Specify border color for repeat box.
682 ;; `ebnf-entry-percentage' Specify entry height on alternatives.
684 ;; `ebnf-arrow-shape' Specify the arrow shape.
686 ;; `ebnf-chart-shape' Specify chart flow shape.
688 ;; `ebnf-color-p' Non-nil means use color.
690 ;; `ebnf-line-width' Specify flow line width.
692 ;; `ebnf-line-color' Specify flow line color.
694 ;; `ebnf-arrow-extra-width' Specify extra width for arrow shape
697 ;; `ebnf-arrow-scale' Specify the arrow scale.
699 ;; `ebnf-user-arrow' Specify a sexp for user arrow shape (a
702 ;; `ebnf-debug-ps' Non-nil means to generate PostScript
705 ;; `ebnf-lex-comment-char' Specify the line comment character.
707 ;; `ebnf-lex-eop-char' Specify the end of production
710 ;; `ebnf-syntax' Specify syntax to be recognized.
712 ;; `ebnf-iso-alternative-p' Non-nil means use alternative ISO EBNF.
714 ;; `ebnf-iso-normalize-p' Non-nil means normalize ISO EBNF syntax
717 ;; `ebnf-default-width' Specify additional border width over
718 ;; default terminal, non-terminal or
721 ;; `ebnf-file-suffix-regexp' Specify file name suffix that contains
724 ;; `ebnf-eps-prefix' Specify EPS prefix file name.
726 ;; `ebnf-use-float-format' Non-nil means use `%f' float format.
728 ;; `ebnf-stop-on-error' Non-nil means signal error and stop.
729 ;; Nil means signal error and continue.
731 ;; `ebnf-yac-ignore-error-recovery' Non-nil means ignore error recovery.
733 ;; `ebnf-ignore-empty-rule' Non-nil means ignore empty rules.
735 ;; `ebnf-optimize' Non-nil means optimize syntactic chart
738 ;; To set the above options you may:
740 ;; a) insert the code in your ~/.emacs, like:
742 ;; (setq ebnf-terminal-shape 'bevel)
744 ;; This way always keep your default settings when you enter a new Emacs
747 ;; b) or use `set-variable' in your Emacs session, like:
749 ;; M-x set-variable RET ebnf-terminal-shape RET bevel RET
751 ;; This way keep your settings only during the current Emacs session.
753 ;; c) or use customization, for example:
754 ;; click on menu-bar *Help* option,
755 ;; then click on *Customize*,
756 ;; then click on *Browse Customization Groups*,
757 ;; expand *PostScript* group,
758 ;; expand *Ebnf2ps* group
759 ;; and then customize ebnf2ps options.
760 ;; Through this way, you may choose if the settings are kept or not when
761 ;; you leave out the current Emacs session.
763 ;; d) or see the option value:
765 ;; C-h v ebnf-terminal-shape RET
767 ;; and click the *customize* hypertext button.
768 ;; Through this way, you may choose if the settings are kept or not when
769 ;; you leave out the current Emacs session.
773 ;; M-x ebnf-customize RET
775 ;; and then customize ebnf2ps options.
776 ;; Through this way, you may choose if the settings are kept or not when
777 ;; you leave out the current Emacs session.
783 ;; Sometimes you need to change the EBNF style you are using, for example,
784 ;; change the shapes and colors. These changes may force you to set some
785 ;; variables and after use, set back the variables to the old values.
787 ;; To help to handle this situation, ebnf2ps has the following commands to
790 ;; `ebnf-insert-style' Insert a new style NAME with inheritance INHERITS and
793 ;; `ebnf-delete-style' Delete style NAME.
795 ;; `ebnf-merge-style' Merge values of style NAME with style VALUES.
797 ;; `ebnf-apply-style' Set STYLE as the current style.
799 ;; `ebnf-reset-style' Reset current style.
801 ;; `ebnf-push-style' Push the current style and set STYLE as the current
804 ;; `ebnf-pop-style' Pop a style and set it as the current style.
806 ;; These commands help to put together a lot of variable settings in a group
807 ;; and name this group. So when you wish to apply these settings it's only
808 ;; needed to give the name.
810 ;; There is also a notion of simple inheritance of style: if you declare that
811 ;; style A inherits from style B, all settings of B are applied first and then
812 ;; the settings of A are applied. This is useful when you wish to modify some
813 ;; aspects of an existing style, but at same time wish to keep it unmodified.
815 ;; See documentation for `ebnf-style-database'.
821 ;; Below it is the layout of minimum area to draw each element, and it's used
822 ;; the following terms:
824 ;; font height is given by:
825 ;; (terminal font height + non-terminal font height) / 2
827 ;; entry is the vertical position used to know where it should
828 ;; be drawn the flow line in the current element.
830 ;; extra is given by `ebnf-arrow-extra-width'.
833 ;; * SPECIAL, TERMINAL and NON-TERMINAL
835 ;; +==============+...................................
836 ;; | | } font height / 2 } entry }
837 ;; | XXXXXXXX...|....... } }
838 ;; ====+ XXXXXXXX +==== } text height ...... } height
839 ;; : | XXXXXXXX...|...:... }
840 ;; : | : : | : } font height / 2 }
841 ;; : +==============+...:...............................
843 ;; : : : : : :.........................
844 ;; : : : : : } font height }
845 ;; : : : : :....... }
846 ;; : : : : } font height / 2 }
847 ;; : : : :........... }
848 ;; : : : } text width } width
849 ;; : : :.................. }
850 ;; : : } font height / 2 }
851 ;; : :...................... }
852 ;; : } font height + extra }
853 ;; :.................................................
858 ;; +==========+.....................................
862 ;; ===+===+ +===+===... } element height } height
865 ;; : | +==========+.|................. }
866 ;; : | : : | : } font height }
867 ;; : +==============+...................................
869 ;; : : : :......................
870 ;; : : : } font height * 2 }
872 ;; : : } element width } width
873 ;; : :..................... }
874 ;; : } font height * 2 }
875 ;; :...............................................
880 ;; +===+...................................
881 ;; +==+ A +==+ } A height } }
882 ;; | +===+..|........ } entry }
883 ;; + + } font height } }
884 ;; / +===+...\....... } }
885 ;; ===+====+ B +====+=== } B height ..... } height
886 ;; : \ +===+.../....... }
887 ;; : + + : } font height }
888 ;; : | +===+..|........ }
889 ;; : +==+ C +==+ : } C height }
890 ;; : : +===+...................................
892 ;; : : : :......................
893 ;; : : : } font height * 2 }
895 ;; : : } max width } width
896 ;; : :................. }
897 ;; : } font height * 2 }
898 ;; :..........................................
901 ;; 1. An empty alternative has zero of height.
903 ;; 2. The variable `ebnf-entry-percentage' is used to determine the
909 ;; +===========+...............................
910 ;; +=+ separator +=+ } separator height }
911 ;; / +===========+..\........ }
913 ;; | | } font height }
915 ;; \ +===========+../........ } height = entry
916 ;; +=+ element +=+ } element height }
917 ;; /: +===========+..\........ }
919 ;; + : : + } font height }
921 ;; ==+=======================+==.......................
923 ;; : : : :.......................
924 ;; : : : } font height * 2 }
926 ;; : : } max width } width
927 ;; : :......................... }
928 ;; : } font height * 2 }
929 ;; :...................................................
934 ;; +===========+......................................
935 ;; +=+ separator +=+ } separator height } }
936 ;; / +===========+..\...... } }
938 ;; | | } font height } } height
940 ;; \ +===========+../...... } }
941 ;; ===+=+ element +=+=== } element height .... }
942 ;; : : +===========+......................................
944 ;; : : : :........................
945 ;; : : : } font height * 2 }
947 ;; : : } max width } width
948 ;; : :....................... }
949 ;; : } font height * 2 }
950 ;; :..............................................
955 ;; XXXXXX:......................................
956 ;; XXXXXX: } production font height }
957 ;; XXXXXX:............ }
959 ;; +======+....... } height = entry
961 ;; ====+ +==== } element height }
963 ;; : +======+.................................
965 ;; : : : :......................
966 ;; : : : } font height * 2 }
968 ;; : : } element width } width
969 ;; : :.............. }
970 ;; : } font height * 2 }
971 ;; :.....................................
976 ;; +================+...................................
977 ;; | | } font height / 2 } entry }
978 ;; | +===+...|....... } }
979 ;; ====+ N * | X | +==== } X height ......... } height
980 ;; : | : : +===+...|...:... }
981 ;; : | : : : : | : } font height / 2 }
982 ;; : +================+...:...............................
984 ;; : : : : : : : :..........................
985 ;; : : : : : : : } font height }
986 ;; : : : : : : :....... }
987 ;; : : : : : : } font height / 2 }
988 ;; : : : : : :........... }
989 ;; : : : : : } X width }
990 ;; : : : : :............... }
991 ;; : : : : } font height / 2 } width
992 ;; : : : :.................. }
993 ;; : : : } text width }
994 ;; : : :..................... }
995 ;; : : } font height / 2 }
996 ;; : :........................ }
997 ;; : } font height + extra }
998 ;; :...................................................
1003 ;; +==================+...................................
1004 ;; | | } font height / 2 } entry }
1005 ;; | +===+ +===+...|....... } }
1006 ;; ====+ | X | - | y | +==== } max height ....... } height
1007 ;; : | +===+ +===+...|...:... }
1008 ;; : | : : : : | : } font height / 2 }
1009 ;; : +==================+...:...............................
1011 ;; : : : : : : : :..........................
1012 ;; : : : : : : : } font height }
1013 ;; : : : : : : :....... }
1014 ;; : : : : : : } font height / 2 }
1015 ;; : : : : : :........... }
1016 ;; : : : : : } Y width }
1017 ;; : : : : :............... }
1018 ;; : : : : } font height } width
1019 ;; : : : :................... }
1020 ;; : : : } X width }
1021 ;; : : :....................... }
1022 ;; : : } font height / 2 }
1023 ;; : :.......................... }
1024 ;; : } font height + extra }
1025 ;; :.....................................................
1027 ;; NOTE: If Y element is empty, it's draw nothing at Y place.
1030 ;; Internal Structures
1031 ;; -------------------
1033 ;; ebnf2ps has two passes. The first pass does a lexical and syntactic analysis
1034 ;; of current buffer and generates an intermediate representation. The second
1035 ;; pass uses the intermediate representation to generate the PostScript
1038 ;; The intermediate representation is a list of vectors, the vector element
1039 ;; represents a syntactic chart element. Below is a vector representation for
1040 ;; each syntactic chart element.
1042 ;; [production WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH NAME PRODUCTION ACTION]
1043 ;; [alternative WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH LIST]
1044 ;; [sequence WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH LIST]
1045 ;; [terminal WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH NAME DEFAULT]
1046 ;; [non-terminal WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH NAME DEFAULT]
1047 ;; [special WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH NAME DEFAULT]
1048 ;; [empty WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH]
1049 ;; [optional WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH ELEMENT]
1050 ;; [one-or-more WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH ELEMENT SEPARATOR]
1051 ;; [zero-or-more WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH ELEMENT SEPARATOR]
1052 ;; [repeat WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH TIMES ELEMENT]
1053 ;; [except WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH ELEMENT ELEMENT]
1055 ;; The first vector position is a function symbol used to generate PostScript
1056 ;; for this element.
1057 ;; WIDTH-FUN is a function symbol called to adjust the element width.
1058 ;; DIM-FUN is a function symbol called to set the element dimensions.
1059 ;; ENTRY is the element entry point.
1060 ;; HEIGHT and WIDTH are the element height and width, respectively.
1061 ;; NAME is a string that it's the element name.
1062 ;; DEFAULT is a boolean that indicates if it's a `default' element.
1063 ;; PRODUCTION and ELEMENT are vectors that represents sub-elements of current
1065 ;; LIST is a list of vector that represents the list part for alternatives and
1067 ;; SEPARATOR is a vector that represents the sub-element used to separate the
1069 ;; TIMES is a string representing the number of times that ELEMENT is repeated
1070 ;; on a repeat construction.
1071 ;; ACTION indicates some action that should be done before production is
1072 ;; generated. The current actions are:
1076 ;; form-feed current production starts on a new page.
1078 ;; newline current production starts on next line, this is useful
1079 ;; when `ebnf-horizontal-orientation' is non-nil.
1081 ;; keep-line current production continues on the current line, this
1082 ;; is useful when `ebnf-horizontal-orientation' is nil.
1088 ;; . Handle situations when syntactic chart is out of paper.
1089 ;; . Use other alphabet than ascii.
1090 ;; . Optimizations...
1096 ;; Thanks to Eli Zaretskii <eliz@gnu.org> for some doc fixes.
1098 ;; Thanks to Drew Adams <drew.adams@oracle.com> for suggestions:
1099 ;; - `ebnf-arrow-extra-width', `ebnf-arrow-scale',
1100 ;; `ebnf-production-name-p', `ebnf-stop-on-error',
1101 ;; `ebnf-file-suffix-regexp'and `ebnf-special-show-delimiter' variables.
1102 ;; - `ebnf-delete-style', `ebnf-eps-file' and `ebnf-eps-directory'
1106 ;; Thanks to Matthew K. Junker <junker@alum.mit.edu> for the suggestion to deal
1107 ;; with some Bison features (%right, %left and %prec pragmas). His suggestion
1108 ;; was extended to deal with %nonassoc pragma too.
1110 ;; Thanks to all who emailed comments.
1113 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1120 (and (string< ps-print-version
"5.2.3")
1121 (error "`ebnf2ps' requires `ps-print' package version 5.2.3 or later"))
1124 ;; to avoid gripes with Emacs 20
1125 (or (fboundp 'assq-delete-all
)
1126 (defun assq-delete-all (key alist
)
1127 "Delete from ALIST all elements whose car is KEY.
1128 Return the modified alist.
1129 Elements of ALIST that are not conses are ignored."
1132 (if (and (consp (car tail
))
1133 (eq (car (car tail
)) key
))
1134 (setq alist
(delq (car tail
) alist
)))
1135 (setq tail
(cdr tail
)))
1139 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1143 ;;; Interface to the command system
1145 (defgroup postscript nil
1152 (defgroup ebnf2ps nil
1153 "Translate an EBNF to a syntactic chart on PostScript."
1160 (defgroup ebnf-special nil
1161 "Special customization."
1168 (defgroup ebnf-except nil
1169 "Except customization."
1176 (defgroup ebnf-repeat nil
1177 "Repeat customization."
1184 (defgroup ebnf-terminal nil
1185 "Terminal customization."
1192 (defgroup ebnf-non-terminal nil
1193 "Non-Terminal customization."
1200 (defgroup ebnf-production nil
1201 "Production customization."
1208 (defgroup ebnf-shape nil
1209 "Shapes customization."
1216 (defgroup ebnf-displacement nil
1217 "Displacement customization."
1224 (defgroup ebnf-syntactic nil
1225 "Syntactic customization."
1232 (defgroup ebnf-optimization nil
1233 "Optimization customization."
1240 (defcustom ebnf-horizontal-orientation nil
1241 "*Non-nil means productions are drawn horizontally."
1244 :group
'ebnf-displacement
)
1247 (defcustom ebnf-horizontal-max-height nil
1248 "*Non-nil means to use maximum production height in horizontal orientation.
1250 It is only used when `ebnf-horizontal-orientation' is non-nil."
1253 :group
'ebnf-displacement
)
1256 (defcustom ebnf-production-horizontal-space
0.0 ; use ebnf2ps default value
1257 "*Specify horizontal space in points between productions.
1259 Value less or equal to zero forces ebnf2ps to set a proper default value."
1262 :group
'ebnf-displacement
)
1265 (defcustom ebnf-production-vertical-space
0.0 ; use ebnf2ps default value
1266 "*Specify vertical space in points between productions.
1268 Value less or equal to zero forces ebnf2ps to set a proper default value."
1271 :group
'ebnf-displacement
)
1274 (defcustom ebnf-justify-sequence
'center
1275 "*Specify justification of terms in a sequence inside alternatives.
1279 `left' left justification
1280 `right' right justification
1281 any other value centralize"
1282 :type
'(radio :tag
"Sequence Justification"
1283 (const left
) (const right
) (other :tag
"center" center
))
1285 :group
'ebnf-displacement
)
1288 (defcustom ebnf-special-show-delimiter t
1289 "*Non-nil means special delimiter (character `?') is shown."
1292 :group
'ebnf-special
)
1295 (defcustom ebnf-special-font
'(7 Courier
"Black" "Gray95" bold italic
)
1296 "*Specify special font.
1298 See documentation for `ebnf-production-font'."
1299 :type
'(list :tag
"Special Font"
1300 (number :tag
"Font Size")
1301 (symbol :tag
"Font Name")
1302 (choice :tag
"Foreground Color"
1303 (string :tag
"Name")
1304 (other :tag
"Default" nil
))
1305 (choice :tag
"Background Color"
1306 (string :tag
"Name")
1307 (other :tag
"Default" nil
))
1308 (repeat :tag
"Font Attributes" :inline t
1309 (choice (const bold
) (const italic
)
1310 (const underline
) (const strikeout
)
1311 (const overline
) (const shadow
)
1312 (const box
) (const outline
))))
1314 :group
'ebnf-special
)
1317 (defcustom ebnf-special-shape
'bevel
1318 "*Specify special box shape.
1320 See documentation for `ebnf-non-terminal-shape'."
1321 :type
'(radio :tag
"Special Shape"
1322 (const miter
) (const round
) (const bevel
))
1324 :group
'ebnf-special
)
1327 (defcustom ebnf-special-shadow nil
1328 "*Non-nil means special box will have a shadow."
1331 :group
'ebnf-special
)
1334 (defcustom ebnf-special-border-width
0.5
1335 "*Specify border width for special box."
1338 :group
'ebnf-special
)
1341 (defcustom ebnf-special-border-color
"Black"
1342 "*Specify border color for special box."
1345 :group
'ebnf-special
)
1348 (defcustom ebnf-except-font
'(7 Courier
"Black" "Gray90" bold italic
)
1349 "*Specify except font.
1351 See documentation for `ebnf-production-font'."
1352 :type
'(list :tag
"Except Font"
1353 (number :tag
"Font Size")
1354 (symbol :tag
"Font Name")
1355 (choice :tag
"Foreground Color"
1356 (string :tag
"Name")
1357 (other :tag
"Default" nil
))
1358 (choice :tag
"Background Color"
1359 (string :tag
"Name")
1360 (other :tag
"Default" nil
))
1361 (repeat :tag
"Font Attributes" :inline t
1362 (choice (const bold
) (const italic
)
1363 (const underline
) (const strikeout
)
1364 (const overline
) (const shadow
)
1365 (const box
) (const outline
))))
1367 :group
'ebnf-except
)
1370 (defcustom ebnf-except-shape
'bevel
1371 "*Specify except box shape.
1373 See documentation for `ebnf-non-terminal-shape'."
1374 :type
'(radio :tag
"Except Shape"
1375 (const miter
) (const round
) (const bevel
))
1377 :group
'ebnf-except
)
1380 (defcustom ebnf-except-shadow nil
1381 "*Non-nil means except box will have a shadow."
1384 :group
'ebnf-except
)
1387 (defcustom ebnf-except-border-width
0.25
1388 "*Specify border width for except box."
1391 :group
'ebnf-except
)
1394 (defcustom ebnf-except-border-color
"Black"
1395 "*Specify border color for except box."
1398 :group
'ebnf-except
)
1401 (defcustom ebnf-repeat-font
'(7 Courier
"Black" "Gray85" bold italic
)
1402 "*Specify repeat font.
1404 See documentation for `ebnf-production-font'."
1405 :type
'(list :tag
"Repeat Font"
1406 (number :tag
"Font Size")
1407 (symbol :tag
"Font Name")
1408 (choice :tag
"Foreground Color"
1409 (string :tag
"Name")
1410 (other :tag
"Default" nil
))
1411 (choice :tag
"Background Color"
1412 (string :tag
"Name")
1413 (other :tag
"Default" nil
))
1414 (repeat :tag
"Font Attributes" :inline t
1415 (choice (const bold
) (const italic
)
1416 (const underline
) (const strikeout
)
1417 (const overline
) (const shadow
)
1418 (const box
) (const outline
))))
1420 :group
'ebnf-repeat
)
1423 (defcustom ebnf-repeat-shape
'bevel
1424 "*Specify repeat box shape.
1426 See documentation for `ebnf-non-terminal-shape'."
1427 :type
'(radio :tag
"Repeat Shape"
1428 (const miter
) (const round
) (const bevel
))
1430 :group
'ebnf-repeat
)
1433 (defcustom ebnf-repeat-shadow nil
1434 "*Non-nil means repeat box will have a shadow."
1437 :group
'ebnf-repeat
)
1440 (defcustom ebnf-repeat-border-width
0.0
1441 "*Specify border width for repeat box."
1444 :group
'ebnf-repeat
)
1447 (defcustom ebnf-repeat-border-color
"Black"
1448 "*Specify border color for repeat box."
1451 :group
'ebnf-repeat
)
1454 (defcustom ebnf-terminal-font
'(7 Courier
"Black" "White")
1455 "*Specify terminal font.
1457 See documentation for `ebnf-production-font'."
1458 :type
'(list :tag
"Terminal Font"
1459 (number :tag
"Font Size")
1460 (symbol :tag
"Font Name")
1461 (choice :tag
"Foreground Color"
1462 (string :tag
"Name")
1463 (other :tag
"Default" nil
))
1464 (choice :tag
"Background Color"
1465 (string :tag
"Name")
1466 (other :tag
"Default" nil
))
1467 (repeat :tag
"Font Attributes" :inline t
1468 (choice (const bold
) (const italic
)
1469 (const underline
) (const strikeout
)
1470 (const overline
) (const shadow
)
1471 (const box
) (const outline
))))
1473 :group
'ebnf-terminal
)
1476 (defcustom ebnf-terminal-shape
'miter
1477 "*Specify terminal box shape.
1479 See documentation for `ebnf-non-terminal-shape'."
1480 :type
'(radio :tag
"Terminal Shape"
1481 (const miter
) (const round
) (const bevel
))
1483 :group
'ebnf-terminal
)
1486 (defcustom ebnf-terminal-shadow nil
1487 "*Non-nil means terminal box will have a shadow."
1490 :group
'ebnf-terminal
)
1493 (defcustom ebnf-terminal-border-width
1.0
1494 "*Specify border width for terminal box."
1497 :group
'ebnf-terminal
)
1500 (defcustom ebnf-terminal-border-color
"Black"
1501 "*Specify border color for terminal box."
1504 :group
'ebnf-terminal
)
1507 (defcustom ebnf-production-name-p t
1508 "*Non-nil means production name will be printed."
1511 :group
'ebnf-production
)
1514 (defcustom ebnf-sort-production nil
1515 "*Specify how productions are sorted.
1519 nil don't sort productions.
1520 `ascending' ascending sort.
1521 any other value descending sort."
1522 :type
'(radio :tag
"Production Sort"
1523 (const :tag
"Ascending" ascending
)
1524 (const :tag
"Descending" descending
)
1525 (other :tag
"No Sort" nil
))
1527 :group
'ebnf-production
)
1530 (defcustom ebnf-production-font
'(10 Helvetica
"Black" "White" bold
)
1531 "*Specify production header font.
1533 It is a list with the following form:
1535 (SIZE NAME FOREGROUND BACKGROUND ATTRIBUTE...)
1538 SIZE is the font size.
1539 NAME is the font name symbol.
1540 ATTRIBUTE is one of the following symbols:
1541 bold - use bold font.
1542 italic - use italic font.
1543 underline - put a line under text.
1544 strikeout - like underline, but the line is in middle of text.
1545 overline - like underline, but the line is over the text.
1546 shadow - text will have a shadow.
1547 box - text will be surrounded by a box.
1548 outline - print characters as hollow outlines.
1549 FOREGROUND is a foreground string color name; if it's nil, the default color is
1551 BACKGROUND is a background string color name; if it's nil, the default color is
1554 See `ps-font-info-database' for valid font name."
1555 :type
'(list :tag
"Production Font"
1556 (number :tag
"Font Size")
1557 (symbol :tag
"Font Name")
1558 (choice :tag
"Foreground Color"
1559 (string :tag
"Name")
1560 (other :tag
"Default" nil
))
1561 (choice :tag
"Background Color"
1562 (string :tag
"Name")
1563 (other :tag
"Default" nil
))
1564 (repeat :tag
"Font Attributes" :inline t
1565 (choice (const bold
) (const italic
)
1566 (const underline
) (const strikeout
)
1567 (const overline
) (const shadow
)
1568 (const box
) (const outline
))))
1570 :group
'ebnf-production
)
1573 (defcustom ebnf-non-terminal-font
'(7 Helvetica
"Black" "White")
1574 "*Specify non-terminal font.
1576 See documentation for `ebnf-production-font'."
1577 :type
'(list :tag
"Non-Terminal Font"
1578 (number :tag
"Font Size")
1579 (symbol :tag
"Font Name")
1580 (choice :tag
"Foreground Color"
1581 (string :tag
"Name")
1582 (other :tag
"Default" nil
))
1583 (choice :tag
"Background Color"
1584 (string :tag
"Name")
1585 (other :tag
"Default" nil
))
1586 (repeat :tag
"Font Attributes" :inline t
1587 (choice (const bold
) (const italic
)
1588 (const underline
) (const strikeout
)
1589 (const overline
) (const shadow
)
1590 (const box
) (const outline
))))
1592 :group
'ebnf-non-terminal
)
1595 (defcustom ebnf-non-terminal-shape
'round
1596 "*Specify non-terminal box shape.
1612 Any other value is treated as `miter'."
1613 :type
'(radio :tag
"Non-Terminal Shape"
1614 (const miter
) (const round
) (const bevel
))
1616 :group
'ebnf-non-terminal
)
1619 (defcustom ebnf-non-terminal-shadow nil
1620 "*Non-nil means non-terminal box will have a shadow."
1623 :group
'ebnf-non-terminal
)
1626 (defcustom ebnf-non-terminal-border-width
1.0
1627 "*Specify border width for non-terminal box."
1630 :group
'ebnf-non-terminal
)
1633 (defcustom ebnf-non-terminal-border-color
"Black"
1634 "*Specify border color for non-terminal box."
1637 :group
'ebnf-non-terminal
)
1640 (defcustom ebnf-arrow-shape
'hollow
1641 "*Specify the arrow shape.
1647 `semi-up' * `transparent' *
1655 `semi-down' =====* `hollow' *
1671 `semi-up-hollow' `semi-up-full'
1677 `semi-down-hollow' `semi-down-full'
1683 `user' See also documentation for variable `ebnf-user-arrow'.
1685 Any other value is treated as `none'."
1686 :type
'(radio :tag
"Arrow Shape"
1687 (const none
) (const semi-up
)
1688 (const semi-down
) (const simple
)
1689 (const transparent
) (const hollow
)
1690 (const full
) (const semi-up-hollow
)
1691 (const semi-down-hollow
) (const semi-up-full
)
1692 (const semi-down-full
) (const user
))
1697 (defcustom ebnf-chart-shape
'round
1698 "*Specify chart flow shape.
1700 See documentation for `ebnf-non-terminal-shape'."
1701 :type
'(radio :tag
"Chart Flow Shape"
1702 (const miter
) (const round
) (const bevel
))
1707 (defcustom ebnf-user-arrow nil
1708 "*Specify a sexp for user arrow shape (a PostScript code).
1710 When evaluated, the sexp should return nil or a string containing PostScript
1711 code. PostScript code should draw a right arrow.
1713 The anatomy of a right arrow is:
1715 ...... Initial position
1717 : *.................
1721 ======+======*... } hT2
1725 : *.................
1731 :.......................
1733 Where `hT', `hT2' and `hT4' are predefined PostScript variable names that can
1734 be used to generate your own arrow. As these variables are used along
1735 PostScript execution, *DON'T* modify the values of them. Instead, copy the
1736 values, if you need to modify them.
1738 The relation between these variables is: hT = 2 * hT2 = 4 * hT4.
1740 The variable `ebnf-user-arrow' is only used when `ebnf-arrow-shape' is set to
1742 :type
'(sexp :tag
"User Arrow Shape")
1747 (defcustom ebnf-syntax
'ebnf
1748 "*Specify syntax to be recognized.
1752 `ebnf' ebnf2ps recognizes the syntax described in ebnf2ps
1754 The following variables *ONLY* have effect with this
1756 `ebnf-terminal-regexp', `ebnf-case-fold-search',
1757 `ebnf-lex-comment-char' and `ebnf-lex-eop-char'.
1759 `abnf' ebnf2ps recognizes the syntax described in the URL:
1760 `http://www.ietf.org/rfc/rfc2234.txt'
1761 (\"Augmented BNF for Syntax Specifications: ABNF\").
1763 `iso-ebnf' ebnf2ps recognizes the syntax described in the URL:
1764 `http://www.cl.cam.ac.uk/~mgk25/iso-ebnf.html'
1765 (\"International Standard of the ISO EBNF Notation\").
1766 The following variables *ONLY* have effect with this
1768 `ebnf-iso-alternative-p' and `ebnf-iso-normalize-p'.
1770 `yacc' ebnf2ps recognizes the Yacc/Bison syntax.
1771 The following variable *ONLY* has effect with this
1773 `ebnf-yac-ignore-error-recovery'.
1775 `ebnfx' ebnf2ps recognizes the syntax described in the URL:
1776 `http://www.w3.org/TR/2004/REC-xml-20040204/#sec-notation'
1777 (\"Extensible Markup Language (XML) 1.0 (Third Edition)\")
1779 `dtd' ebnf2ps recognizes the syntax described in the URL:
1780 `http://www.w3.org/TR/2004/REC-xml-20040204/'
1781 (\"Extensible Markup Language (XML) 1.0 (Third Edition)\")
1783 Any other value is treated as `ebnf'."
1784 :type
'(radio :tag
"Syntax"
1785 (const ebnf
) (const abnf
) (const iso-ebnf
)
1786 (const yacc
) (const ebnfx
) (const dtd
))
1788 :group
'ebnf-syntactic
)
1791 (defcustom ebnf-lex-comment-char ?\
;
1792 "*Specify the line comment character.
1794 It's used only when `ebnf-syntax' is `ebnf'."
1797 :group
'ebnf-syntactic
)
1800 (defcustom ebnf-lex-eop-char ?.
1801 "*Specify the end of production character.
1803 It's used only when `ebnf-syntax' is `ebnf'."
1806 :group
'ebnf-syntactic
)
1809 (defcustom ebnf-terminal-regexp nil
1810 "*Specify how it's a terminal name.
1812 If it's nil, the terminal name must be enclosed by `\"'.
1813 If it's a string, it should be a regexp that it'll be used to determine a
1814 terminal name; terminal name may also be enclosed by `\"'.
1816 It's used only when `ebnf-syntax' is `ebnf'."
1817 :type
'(radio :tag
"Terminal Name"
1820 :group
'ebnf-syntactic
)
1823 (defcustom ebnf-case-fold-search nil
1824 "*Non-nil means ignore case on matching.
1826 It's only used when `ebnf-terminal-regexp' is non-nil and when `ebnf-syntax' is
1830 :group
'ebnf-syntactic
)
1833 (defcustom ebnf-iso-alternative-p nil
1834 "*Non-nil means use alternative ISO EBNF.
1836 It's only used when `ebnf-syntax' is `iso-ebnf'.
1838 This variable affects the following symbol set:
1840 STANDARD ALTERNATIVE
1849 :group
'ebnf-syntactic
)
1852 (defcustom ebnf-iso-normalize-p nil
1853 "*Non-nil means normalize ISO EBNF syntax names.
1855 Normalize a name means that several contiguous spaces inside name become a
1856 single space, so \"A B C\" is normalized to \"A B C\".
1858 It's only used when `ebnf-syntax' is `iso-ebnf'."
1861 :group
'ebnf-syntactic
)
1864 (defcustom ebnf-file-suffix-regexp
"\.[Bb][Nn][Ff]$"
1865 "*Specify file name suffix that contains EBNF.
1867 See `ebnf-eps-directory' command."
1873 (defcustom ebnf-eps-prefix
"ebnf--"
1874 "*Specify EPS prefix file name.
1876 See `ebnf-eps-buffer' and `ebnf-eps-region' commands."
1882 (defcustom ebnf-entry-percentage
0.5 ; middle
1883 "*Specify entry height on alternatives.
1885 It must be a float between 0.0 (top) and 1.0 (bottom)."
1891 (defcustom ebnf-default-width
0.6
1892 "*Specify additional border width over default terminal, non-terminal or
1899 ;; Printing color requires x-color-values.
1900 (defcustom ebnf-color-p
(or (fboundp 'x-color-values
) ; Emacs
1901 (fboundp 'color-instance-rgb-components
)) ; XEmacs
1902 "*Non-nil means use color."
1908 (defcustom ebnf-line-width
1.0
1909 "*Specify flow line width."
1915 (defcustom ebnf-line-color
"Black"
1916 "*Specify flow line color."
1922 (defcustom ebnf-arrow-extra-width
1923 (if (eq ebnf-arrow-shape
'none
)
1925 (* (sqrt 5.0) 0.65 ebnf-line-width
))
1926 "*Specify extra width for arrow shape drawing.
1928 The extra width is used to avoid that the arrowhead and the terminal border
1929 overlap. It depens on `ebnf-arrow-shape' and `ebnf-line-width'."
1935 (defcustom ebnf-arrow-scale
1.0
1936 "*Specify the arrow scale.
1938 Values lower than 1.0, shrink the arrow.
1939 Values greater than 1.0, expand the arrow."
1945 (defcustom ebnf-debug-ps nil
1946 "*Non-nil means to generate PostScript debug procedures.
1948 It is intended to help PostScript programmers in debugging."
1954 (defcustom ebnf-use-float-format t
1955 "*Non-nil means use `%f' float format.
1957 The advantage of using float format is that ebnf2ps generates a little short
1960 If it occurs the error message:
1962 Invalid format operation %f
1964 when executing ebnf2ps, set `ebnf-use-float-format' to nil."
1970 (defcustom ebnf-stop-on-error nil
1971 "*Non-nil means signal error and stop. Otherwise, signal error and continue."
1977 (defcustom ebnf-yac-ignore-error-recovery nil
1978 "*Non-nil means ignore error recovery.
1980 It's only used when `ebnf-syntax' is `yacc'."
1983 :group
'ebnf-syntactic
)
1986 (defcustom ebnf-ignore-empty-rule nil
1987 "*Non-nil means ignore empty rules.
1989 It's interesting to set this variable if your Yacc/Bison grammar has a lot of
1990 middle action rule."
1993 :group
'ebnf-optimization
)
1996 (defcustom ebnf-optimize nil
1997 "*Non-nil means optimize syntactic chart of rules.
1999 The following optimizations are done:
2002 1. A = B | A C. ==> A = B {C}*.
2003 2. A = B | A B. ==> A = {B}+.
2004 3. A = | A B. ==> A = {B}*.
2005 4. A = B | A C B. ==> A = {B || C}+.
2006 5. A = B | D | A C | A E. ==> A = ( B | D ) { C | E }*.
2009 6. A = B | . ==> A = [B].
2010 7. A = | B . ==> A = [B].
2013 8. A = B C | B D. ==> A = B (C | D).
2014 9. A = C B | D B. ==> A = (C | D) B.
2015 10. A = B C E | B D E. ==> A = B (C | D) E.
2017 The above optimizations are specially useful when `ebnf-syntax' is `yacc'."
2020 :group
'ebnf-optimization
)
2023 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2024 ;; To make this file smaller, some commands go in a separate file.
2025 ;; But autoload them here to make the separation invisible.
2026 ;; Autoload is here to avoid compilation gripes.
2028 (autoload 'ebnf-eliminate-empty-rules
"ebnf-otz"
2029 "Eliminate empty rules.")
2031 (autoload 'ebnf-optimize
"ebnf-otz"
2032 "Syntactic chart optimizer.")
2034 (autoload 'ebnf-otz-initialize
"ebnf-otz"
2035 "Initialize optimizer.")
2038 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2043 (defun ebnf-customize ()
2044 "Customization for ebnf group."
2046 (customize-group 'ebnf2ps
))
2049 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2054 (defun ebnf-print-directory (&optional directory
)
2055 "Generate and print a PostScript syntactic chart image of DIRECTORY.
2057 If DIRECTORY is nil, it's used `default-directory'.
2059 The files in DIRECTORY that matches `ebnf-file-suffix-regexp' (which see) are
2062 See also `ebnf-print-buffer'."
2064 (list (read-file-name "Directory containing EBNF files (print): "
2065 nil default-directory
)))
2066 (ebnf-directory 'ebnf-print-buffer directory
))
2070 (defun ebnf-print-file (file &optional do-not-kill-buffer-when-done
)
2071 "Generate and print a PostScript syntactic chart image of the file FILE.
2073 If optional arg DO-NOT-KILL-BUFFER-WHEN-DONE is non-nil, the buffer isn't
2074 killed after process termination.
2076 See also `ebnf-print-buffer'."
2077 (interactive "fEBNF file to generate PostScript and print from: ")
2078 (ebnf-file 'ebnf-print-buffer file do-not-kill-buffer-when-done
))
2082 (defun ebnf-print-buffer (&optional filename
)
2083 "Generate and print a PostScript syntactic chart image of the buffer.
2085 When called with a numeric prefix argument (C-u), prompts the user for
2086 the name of a file to save the PostScript image in, instead of sending
2089 More specifically, the FILENAME argument is treated as follows: if it
2090 is nil, send the image to the printer. If FILENAME is a string, save
2091 the PostScript image in a file with that name. If FILENAME is a
2092 number, prompt the user for the name of the file to save in."
2093 (interactive (list (ps-print-preprint current-prefix-arg
)))
2094 (ebnf-print-region (point-min) (point-max) filename
))
2098 (defun ebnf-print-region (from to
&optional filename
)
2099 "Generate and print a PostScript syntactic chart image of the region.
2100 Like `ebnf-print-buffer', but prints just the current region."
2101 (interactive (list (point) (mark) (ps-print-preprint current-prefix-arg
)))
2102 (run-hooks 'ebnf-hook
)
2103 (or (ebnf-spool-region from to
)
2104 (ps-do-despool filename
)))
2108 (defun ebnf-spool-directory (&optional directory
)
2109 "Generate and spool a PostScript syntactic chart image of DIRECTORY.
2111 If DIRECTORY is nil, it's used `default-directory'.
2113 The files in DIRECTORY that matches `ebnf-file-suffix-regexp' (which see) are
2116 See also `ebnf-spool-buffer'."
2118 (list (read-file-name "Directory containing EBNF files (spool): "
2119 nil default-directory
)))
2120 (ebnf-directory 'ebnf-spool-buffer directory
))
2124 (defun ebnf-spool-file (file &optional do-not-kill-buffer-when-done
)
2125 "Generate and spool a PostScript syntactic chart image of the file FILE.
2127 If optional arg DO-NOT-KILL-BUFFER-WHEN-DONE is non-nil, the buffer isn't
2128 killed after process termination.
2130 See also `ebnf-spool-buffer'."
2131 (interactive "fEBNF file to generate PostScript and spool from: ")
2132 (ebnf-file 'ebnf-spool-buffer file do-not-kill-buffer-when-done
))
2136 (defun ebnf-spool-buffer ()
2137 "Generate and spool a PostScript syntactic chart image of the buffer.
2138 Like `ebnf-print-buffer' except that the PostScript image is saved in a
2139 local buffer to be sent to the printer later.
2141 Use the command `ebnf-despool' to send the spooled images to the printer."
2143 (ebnf-spool-region (point-min) (point-max)))
2147 (defun ebnf-spool-region (from to
)
2148 "Generate a PostScript syntactic chart image of the region and spool locally.
2149 Like `ebnf-spool-buffer', but spools just the current region.
2151 Use the command `ebnf-despool' to send the spooled images to the printer."
2153 (ebnf-generate-region from to
'ebnf-generate
))
2157 (defun ebnf-eps-directory (&optional directory
)
2158 "Generate EPS files from EBNF files in DIRECTORY.
2160 If DIRECTORY is nil, it's used `default-directory'.
2162 The files in DIRECTORY that matches `ebnf-file-suffix-regexp' (which see) are
2165 See also `ebnf-eps-buffer'."
2167 (list (read-file-name "Directory containing EBNF files (EPS): "
2168 nil default-directory
)))
2169 (ebnf-directory 'ebnf-eps-buffer directory
))
2173 (defun ebnf-eps-file (file &optional do-not-kill-buffer-when-done
)
2174 "Generate an EPS file from EBNF file FILE.
2176 If optional arg DO-NOT-KILL-BUFFER-WHEN-DONE is non-nil, the buffer isn't
2177 killed after EPS generation.
2179 See also `ebnf-eps-buffer'."
2180 (interactive "fEBNF file to generate EPS file from: ")
2181 (ebnf-file 'ebnf-eps-buffer file do-not-kill-buffer-when-done
))
2185 (defun ebnf-eps-buffer ()
2186 "Generate a PostScript syntactic chart image of the buffer in an EPS file.
2188 Generate an EPS file for each production in the buffer.
2189 The EPS file name has the following form:
2191 <PREFIX><PRODUCTION>.eps
2193 <PREFIX> is given by variable `ebnf-eps-prefix'.
2194 The default value is \"ebnf--\".
2196 <PRODUCTION> is the production name.
2197 Some characters in the production file name are replaced to
2198 produce a valid file name. For example, the production name
2199 \"A/B + C\" is modified to produce \"A_B_+_C\", and the EPS
2200 file name used in this case will be \"ebnf--A_B_+_C.eps\".
2202 WARNING: This function does *NOT* ask any confirmation to override existing
2205 (ebnf-eps-region (point-min) (point-max)))
2209 (defun ebnf-eps-region (from to
)
2210 "Generate a PostScript syntactic chart image of the region in an EPS file.
2212 Generate an EPS file for each production in the region.
2213 The EPS file name has the following form:
2215 <PREFIX><PRODUCTION>.eps
2217 <PREFIX> is given by variable `ebnf-eps-prefix'.
2218 The default value is \"ebnf--\".
2220 <PRODUCTION> is the production name.
2221 Some characters in the production file name are replaced to
2222 produce a valid file name. For example, the production name
2223 \"A/B + C\" is modified to produce \"A_B_+_C\", and the EPS
2224 file name used in this case will be \"ebnf--A_B_+_C.eps\".
2226 WARNING: This function does *NOT* ask any confirmation to override existing
2229 (let ((ebnf-eps-executing t
))
2230 (ebnf-generate-region from to
'ebnf-generate-eps
)))
2234 (defalias 'ebnf-despool
'ps-despool
)
2238 (defun ebnf-syntax-directory (&optional directory
)
2239 "Do a syntactic analysis of the files in DIRECTORY.
2241 If DIRECTORY is nil, use `default-directory'.
2243 Only the files in DIRECTORY that match `ebnf-file-suffix-regexp' (which see)
2246 See also `ebnf-syntax-buffer'."
2248 (list (read-file-name "Directory containing EBNF files (syntax): "
2249 nil default-directory
)))
2250 (ebnf-directory 'ebnf-syntax-buffer directory
))
2254 (defun ebnf-syntax-file (file &optional do-not-kill-buffer-when-done
)
2255 "Do a syntactic analysis of the named FILE.
2257 If optional arg DO-NOT-KILL-BUFFER-WHEN-DONE is non-nil, the buffer isn't
2258 killed after syntax checking.
2260 See also `ebnf-syntax-buffer'."
2261 (interactive "fEBNF file to check syntax: ")
2262 (ebnf-file 'ebnf-syntax-buffer file do-not-kill-buffer-when-done
))
2266 (defun ebnf-syntax-buffer ()
2267 "Do a syntactic analysis of the current buffer."
2269 (ebnf-syntax-region (point-min) (point-max)))
2273 (defun ebnf-syntax-region (from to
)
2274 "Do a syntactic analysis of region."
2276 (ebnf-generate-region from to nil
))
2279 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2284 (defun ebnf-setup ()
2285 "Return the current ebnf2ps setup."
2288 ;;; ebnf2ps.el version %s
2290 \(setq ebnf-special-show-delimiter %S
2291 ebnf-special-font %s
2292 ebnf-special-shape %s
2293 ebnf-special-shadow %S
2294 ebnf-special-border-width %S
2295 ebnf-special-border-color %S
2297 ebnf-except-shape %s
2298 ebnf-except-shadow %S
2299 ebnf-except-border-width %S
2300 ebnf-except-border-color %S
2302 ebnf-repeat-shape %s
2303 ebnf-repeat-shadow %S
2304 ebnf-repeat-border-width %S
2305 ebnf-repeat-border-color %S
2306 ebnf-terminal-regexp %S
2307 ebnf-case-fold-search %S
2308 ebnf-terminal-font %s
2309 ebnf-terminal-shape %s
2310 ebnf-terminal-shadow %S
2311 ebnf-terminal-border-width %S
2312 ebnf-terminal-border-color %S
2313 ebnf-non-terminal-font %s
2314 ebnf-non-terminal-shape %s
2315 ebnf-non-terminal-shadow %S
2316 ebnf-non-terminal-border-width %S
2317 ebnf-non-terminal-border-color %S
2318 ebnf-production-name-p %S
2319 ebnf-sort-production %s
2320 ebnf-production-font %s
2324 ebnf-horizontal-orientation %S
2325 ebnf-horizontal-max-height %S
2326 ebnf-production-horizontal-space %S
2327 ebnf-production-vertical-space %S
2328 ebnf-justify-sequence %s
2329 ebnf-lex-comment-char ?\\%03o
2330 ebnf-lex-eop-char ?\\%03o
2332 ebnf-iso-alternative-p %S
2333 ebnf-iso-normalize-p %S
2334 ebnf-file-suffix-regexp %S
2336 ebnf-entry-percentage %S
2341 ebnf-use-float-format %S
2342 ebnf-stop-on-error %S
2343 ebnf-yac-ignore-error-recovery %S
2344 ebnf-ignore-empty-rule %S
2347 ;;; ebnf2ps.el - end of settings
2350 ebnf-special-show-delimiter
2351 (ps-print-quote ebnf-special-font
)
2352 (ps-print-quote ebnf-special-shape
)
2354 ebnf-special-border-width
2355 ebnf-special-border-color
2356 (ps-print-quote ebnf-except-font
)
2357 (ps-print-quote ebnf-except-shape
)
2359 ebnf-except-border-width
2360 ebnf-except-border-color
2361 (ps-print-quote ebnf-repeat-font
)
2362 (ps-print-quote ebnf-repeat-shape
)
2364 ebnf-repeat-border-width
2365 ebnf-repeat-border-color
2366 ebnf-terminal-regexp
2367 ebnf-case-fold-search
2368 (ps-print-quote ebnf-terminal-font
)
2369 (ps-print-quote ebnf-terminal-shape
)
2370 ebnf-terminal-shadow
2371 ebnf-terminal-border-width
2372 ebnf-terminal-border-color
2373 (ps-print-quote ebnf-non-terminal-font
)
2374 (ps-print-quote ebnf-non-terminal-shape
)
2375 ebnf-non-terminal-shadow
2376 ebnf-non-terminal-border-width
2377 ebnf-non-terminal-border-color
2378 ebnf-production-name-p
2379 (ps-print-quote ebnf-sort-production
)
2380 (ps-print-quote ebnf-production-font
)
2381 (ps-print-quote ebnf-arrow-shape
)
2382 (ps-print-quote ebnf-chart-shape
)
2383 (ps-print-quote ebnf-user-arrow
)
2384 ebnf-horizontal-orientation
2385 ebnf-horizontal-max-height
2386 ebnf-production-horizontal-space
2387 ebnf-production-vertical-space
2388 (ps-print-quote ebnf-justify-sequence
)
2389 ebnf-lex-comment-char
2391 (ps-print-quote ebnf-syntax
)
2392 ebnf-iso-alternative-p
2393 ebnf-iso-normalize-p
2394 ebnf-file-suffix-regexp
2396 ebnf-entry-percentage
2401 ebnf-use-float-format
2403 ebnf-yac-ignore-error-recovery
2404 ebnf-ignore-empty-rule
2408 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2412 (defvar ebnf-stack-style nil
2413 "Used in functions `ebnf-reset-style', `ebnf-push-style' and
2417 (defvar ebnf-current-style
'default
2418 "Used in functions `ebnf-apply-style' and `ebnf-push-style'.")
2421 (defconst ebnf-style-custom-list
2422 '(ebnf-special-show-delimiter
2426 ebnf-special-border-width
2427 ebnf-special-border-color
2431 ebnf-except-border-width
2432 ebnf-except-border-color
2436 ebnf-repeat-border-width
2437 ebnf-repeat-border-color
2438 ebnf-terminal-regexp
2439 ebnf-case-fold-search
2442 ebnf-terminal-shadow
2443 ebnf-terminal-border-width
2444 ebnf-terminal-border-color
2445 ebnf-non-terminal-font
2446 ebnf-non-terminal-shape
2447 ebnf-non-terminal-shadow
2448 ebnf-non-terminal-border-width
2449 ebnf-non-terminal-border-color
2450 ebnf-production-name-p
2451 ebnf-sort-production
2452 ebnf-production-font
2456 ebnf-horizontal-orientation
2457 ebnf-horizontal-max-height
2458 ebnf-production-horizontal-space
2459 ebnf-production-vertical-space
2460 ebnf-justify-sequence
2461 ebnf-lex-comment-char
2464 ebnf-iso-alternative-p
2465 ebnf-iso-normalize-p
2466 ebnf-file-suffix-regexp
2468 ebnf-entry-percentage
2473 ebnf-use-float-format
2475 ebnf-yac-ignore-error-recovery
2476 ebnf-ignore-empty-rule
2478 "List of valid symbol custom variable.")
2481 (defvar ebnf-style-database
2485 (ebnf-special-show-delimiter . t
)
2486 (ebnf-special-font .
'(7 Courier
"Black" "Gray95" bold italic
))
2487 (ebnf-special-shape .
'bevel
)
2488 (ebnf-special-shadow . nil
)
2489 (ebnf-special-border-width .
0.5)
2490 (ebnf-special-border-color .
"Black")
2491 (ebnf-except-font .
'(7 Courier
"Black" "Gray90" bold italic
))
2492 (ebnf-except-shape .
'bevel
)
2493 (ebnf-except-shadow . nil
)
2494 (ebnf-except-border-width .
0.25)
2495 (ebnf-except-border-color .
"Black")
2496 (ebnf-repeat-font .
'(7 Courier
"Black" "Gray85" bold italic
))
2497 (ebnf-repeat-shape .
'bevel
)
2498 (ebnf-repeat-shadow . nil
)
2499 (ebnf-repeat-border-width .
0.0)
2500 (ebnf-repeat-border-color .
"Black")
2501 (ebnf-terminal-regexp . nil
)
2502 (ebnf-case-fold-search . nil
)
2503 (ebnf-terminal-font .
'(7 Courier
"Black" "White"))
2504 (ebnf-terminal-shape .
'miter
)
2505 (ebnf-terminal-shadow . nil
)
2506 (ebnf-terminal-border-width .
1.0)
2507 (ebnf-terminal-border-color .
"Black")
2508 (ebnf-non-terminal-font .
'(7 Helvetica
"Black" "White"))
2509 (ebnf-non-terminal-shape .
'round
)
2510 (ebnf-non-terminal-shadow . nil
)
2511 (ebnf-non-terminal-border-width .
1.0)
2512 (ebnf-non-terminal-border-color .
"Black")
2513 (ebnf-production-name-p . t
)
2514 (ebnf-sort-production . nil
)
2515 (ebnf-production-font .
'(10 Helvetica
"Black" "White" bold
))
2516 (ebnf-arrow-shape .
'hollow
)
2517 (ebnf-chart-shape .
'round
)
2518 (ebnf-user-arrow . nil
)
2519 (ebnf-horizontal-orientation . nil
)
2520 (ebnf-horizontal-max-height . nil
)
2521 (ebnf-production-horizontal-space .
0.0)
2522 (ebnf-production-vertical-space .
0.0)
2523 (ebnf-justify-sequence .
'center
)
2524 (ebnf-lex-comment-char . ?\
;)
2525 (ebnf-lex-eop-char . ?.
)
2526 (ebnf-syntax .
'ebnf
)
2527 (ebnf-iso-alternative-p . nil
)
2528 (ebnf-iso-normalize-p . nil
)
2529 (ebnf-file-suffix-regexp .
"\.[Bb][Nn][Ff]$")
2530 (ebnf-eps-prefix .
"ebnf--")
2531 (ebnf-entry-percentage .
0.5)
2532 (ebnf-color-p .
(or (fboundp 'x-color-values
) ; Emacs
2533 (fboundp 'color-instance-rgb-components
))) ; XEmacs
2534 (ebnf-line-width .
1.0)
2535 (ebnf-line-color .
"Black")
2536 (ebnf-debug-ps . nil
)
2537 (ebnf-use-float-format . t
)
2538 (ebnf-stop-on-error . nil
)
2539 (ebnf-yac-ignore-error-recovery . nil
)
2540 (ebnf-ignore-empty-rule . nil
)
2541 (ebnf-optimize . nil
))
2542 ;; Happy EBNF default
2545 (ebnf-justify-sequence .
'left
)
2546 (ebnf-lex-comment-char . ?\
#)
2547 (ebnf-lex-eop-char . ?\
;))
2551 (ebnf-syntax .
'abnf
))
2555 (ebnf-syntax .
'iso-ebnf
))
2556 ;; Yacc/Bison default
2559 (ebnf-syntax .
'yacc
))
2563 (ebnf-syntax .
'ebnfx
))
2567 (ebnf-syntax .
'dtd
))
2571 Each element has the following form:
2573 (NAME INHERITS (VAR . VALUE)...)
2577 NAME is a symbol name style.
2579 INHERITS is a symbol name style from which the current style inherits
2580 the context. If INHERITS is nil, then there is no inheritance.
2582 This is a simple inheritance of style: if you declare that
2583 style A inherits from style B, all settings of B are applied
2584 first, and then the settings of A are applied. This is useful
2585 when you wish to modify some aspects of an existing style, but
2586 at the same time wish to keep it unmodified.
2588 VAR is a valid ebnf2ps symbol custom variable.
2589 See `ebnf-style-custom-list' for valid symbol variables.
2591 VALUE is a sexp which will be evaluated to set the value of VAR.
2592 Don't forget to quote symbols and constant lists.
2593 See `default' style for an example.
2595 Don't use this variable directly. Use functions `ebnf-insert-style',
2596 `ebnf-delete-style' and `ebnf-merge-style'.")
2599 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2604 (defun ebnf-insert-style (name inherits
&rest values
)
2605 "Insert a new style NAME with inheritance INHERITS and values VALUES.
2607 See `ebnf-style-database' documentation."
2608 (interactive "SStyle name: \nSStyle inherits from: \nXStyle values: ")
2609 (and (assoc name ebnf-style-database
)
2610 (error "Style name already exists: %s" name
))
2611 (or (assoc inherits ebnf-style-database
)
2612 (error "Style inheritance name doesn't exist: %s" inherits
))
2613 (setq ebnf-style-database
2614 (cons (cons name
(cons inherits
(ebnf-check-style-values values
)))
2615 ebnf-style-database
)))
2619 (defun ebnf-delete-style (name)
2622 See `ebnf-style-database' documentation."
2623 (interactive "SDelete style name: ")
2624 (or (assoc name ebnf-style-database
)
2625 (error "Style name doesn't exist: %s" name
))
2626 (let ((db ebnf-style-database
))
2628 (and (eq (nth 1 (car db
)) name
)
2629 (error "Style name `%s' is inherited by `%s' style"
2630 name
(nth 0 (car db
))))
2631 (setq db
(cdr db
))))
2632 (setq ebnf-style-database
(assq-delete-all name ebnf-style-database
)))
2636 (defun ebnf-merge-style (name &rest values
)
2637 "Merge values of style NAME with style VALUES.
2639 See `ebnf-style-database' documentation."
2640 (interactive "SStyle name: \nXStyle values: ")
2641 (let ((style (or (assoc name ebnf-style-database
)
2642 (error "Style name doesn't exist: %s" name
)))
2643 (merge (ebnf-check-style-values values
))
2645 ;; modify value of existing variables
2646 (setq val
(nthcdr 2 style
))
2648 (setq check
(car merge
)
2650 elt
(assoc (car check
) val
))
2652 (setcdr elt
(cdr check
))
2653 (setq new
(cons check new
))))
2654 ;; insert new variables
2655 (nconc style
(nreverse new
))))
2659 (defun ebnf-apply-style (style)
2660 "Set STYLE as the current style.
2662 Returns the old style symbol.
2664 See `ebnf-style-database' documentation."
2665 (interactive "SApply style: ")
2668 (and (ebnf-apply-style1 style
)
2669 (setq ebnf-current-style style
))))
2673 (defun ebnf-reset-style (&optional style
)
2674 "Reset current style.
2676 Returns the old style symbol.
2678 See `ebnf-style-database' documentation."
2679 (interactive "SReset style: ")
2680 (setq ebnf-stack-style nil
)
2681 (ebnf-apply-style (or style
'default
)))
2685 (defun ebnf-push-style (&optional style
)
2686 "Push the current style onto a stack and set STYLE as the current style.
2688 Returns the old style symbol.
2690 See also `ebnf-pop-style'.
2692 See `ebnf-style-database' documentation."
2693 (interactive "SPush style: ")
2696 (setq ebnf-stack-style
(cons ebnf-current-style ebnf-stack-style
))
2698 (ebnf-apply-style style
))))
2702 (defun ebnf-pop-style ()
2703 "Pop a style from the stack of pushed styles and set it as the current style.
2705 Returns the old style symbol.
2707 See also `ebnf-push-style'.
2709 See `ebnf-style-database' documentation."
2712 (ebnf-apply-style (car ebnf-stack-style
))
2713 (setq ebnf-stack-style
(cdr ebnf-stack-style
))))
2716 (defun ebnf-apply-style1 (style)
2717 (let ((value (cdr (assoc style ebnf-style-database
))))
2720 (and (car value
) (ebnf-apply-style1 (car value
)))
2721 (while (setq value
(cdr value
))
2722 (set (caar value
) (eval (cdar value
)))))))
2725 (defun ebnf-check-style-values (values)
2728 (and (memq (caar values
) ebnf-style-custom-list
)
2729 (setq style
(cons (car values
) style
)))
2730 (setq values
(cdr values
)))
2734 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2735 ;; Internal variables
2738 (defvar ebnf-eps-buffer-name
" *EPS*")
2739 (defvar ebnf-parser-func nil
)
2740 (defvar ebnf-eps-executing nil
)
2741 (defvar ebnf-eps-upper-x
0.0)
2742 (make-variable-buffer-local 'ebnf-eps-upper-x
)
2743 (defvar ebnf-eps-upper-y
0.0)
2744 (make-variable-buffer-local 'ebnf-eps-upper-y
)
2745 (defvar ebnf-eps-prod-width
0.0)
2746 (make-variable-buffer-local 'ebnf-eps-prod-width
)
2747 (defvar ebnf-eps-max-height
0.0)
2748 (make-variable-buffer-local 'ebnf-eps-max-height
)
2749 (defvar ebnf-eps-max-width
0.0)
2750 (make-variable-buffer-local 'ebnf-eps-max-width
)
2753 (defvar ebnf-eps-context nil
2754 "List of EPS file name during parsing.
2756 See section \"Actions in Comments\" in ebnf2ps documentation.")
2759 (defvar ebnf-eps-production-list nil
2760 "Alist associating production name with EPS file name list.
2762 Each element has the following form:
2764 (PRODUCTION EPS-FILENAME...)
2766 PRODUCTION is the production name.
2767 EPS-FILENAME is the EPS file name.
2769 This is generated during parsing and used during EPS generation.
2771 See `ebnf-eps-context' and section \"Actions in Comments\" in ebnf2ps
2775 (defconst ebnf-arrow-shape-alist
2783 (semi-up-hollow .
7)
2785 (semi-down-hollow .
9)
2786 (semi-down-full .
10)
2788 "Alist associating values for `ebnf-arrow-shape'.
2790 See documentation for `ebnf-arrow-shape'.")
2793 (defconst ebnf-terminal-shape-alist
2797 "Alist associating values from `ebnf-terminal-shape' to a bit vector.
2799 See documentation for `ebnf-terminal-shape', `ebnf-non-terminal-shape' and
2800 `ebnf-chart-shape'.")
2803 (defvar ebnf-limit nil
)
2804 (defvar ebnf-action nil
)
2805 (defvar ebnf-action-list nil
)
2808 (defvar ebnf-default-p nil
)
2811 (defvar ebnf-font-height-P
0)
2812 (defvar ebnf-font-height-T
0)
2813 (defvar ebnf-font-height-NT
0)
2814 (defvar ebnf-font-height-S
0)
2815 (defvar ebnf-font-height-E
0)
2816 (defvar ebnf-font-height-R
0)
2817 (defvar ebnf-font-width-P
0)
2818 (defvar ebnf-font-width-T
0)
2819 (defvar ebnf-font-width-NT
0)
2820 (defvar ebnf-font-width-S
0)
2821 (defvar ebnf-font-width-E
0)
2822 (defvar ebnf-font-width-R
0)
2823 (defvar ebnf-space-T
0)
2824 (defvar ebnf-space-NT
0)
2825 (defvar ebnf-space-S
0)
2826 (defvar ebnf-space-E
0)
2827 (defvar ebnf-space-R
0)
2830 (defvar ebnf-basic-width
0)
2831 (defvar ebnf-basic-height
0)
2832 (defvar ebnf-vertical-space
0)
2833 (defvar ebnf-horizontal-space
0)
2836 (defvar ebnf-settings nil
)
2837 (defvar ebnf-fonts-required nil
)
2840 (defconst ebnf-debug
2842 % === begin EBNF procedures to help debugging
2844 % Mark visually current point: string debug
2848 gsave -s- show grestore
2860 % Show number value: number string debug-number
2863 20 0 rmoveto show ([) show 60 string cvs show (]) show
2867 % === end EBNF procedures to help debugging
2870 "This is intended to help debugging PostScript programming.")
2873 (defconst ebnf-prologue
2875 % === begin EBNF engine
2877 % --- Basic Definitions
2880 /SpaceS FontHeight 0.5 mul def
2881 /HeightS FontHeight FontHeight add def
2884 /SpaceE FontHeight 0.5 mul def
2885 /HeightE FontHeight FontHeight add def
2888 /SpaceR FontHeight 0.5 mul def
2889 /HeightR FontHeight FontHeight add def
2892 /SpaceT FontHeight 0.5 mul def
2893 /HeightT FontHeight FontHeight add def
2896 /SpaceNT FontHeight 0.5 mul def
2897 /HeightNT FontHeight FontHeight add def
2899 /T HeightT HeightNT add 0.5 mul def
2901 /hT2 hT 0.5 mul ArrowScale mul def
2902 /hT4 hT 0.25 mul ArrowScale mul def
2904 /Er 0.1 def % Error factor
2907 /c{currentpoint}bind def
2908 /xyi{/xi c /yi exch def def}bind def
2909 /xyo{/xo c /yo exch def def}bind def
2910 /xyp{/xp c /yp exch def def}bind def
2911 /xyt{/xt c /yt exch def def}bind def
2913 % vertical movement: x y height vm
2914 /vm{add moveto}bind def
2916 % horizontal movement: x y width hm
2917 /hm{3 -1 roll exch add exch moveto}bind def
2919 % set color: [R G B] SetRGB
2920 /SetRGB{aload pop setrgbcolor}bind def
2922 % filling gray area: gray-scale FillGray
2923 /FillGray{gsave setgray fill grestore}bind def
2925 % filling color area: [R G B] FillRGB
2926 /FillRGB{gsave SetRGB fill grestore}bind def
2928 /Stroke{LineWidth setlinewidth LineColor SetRGB stroke}bind def
2929 /StrokeShape{borderwidth setlinewidth bordercolor SetRGB stroke}bind def
2930 /Gstroke{gsave Stroke grestore}bind def
2932 % Empty Line: width EL
2933 /EL{0 rlineto Gstroke}bind def
2937 /Down{hT2 neg hT4 neg rlineto}bind def
2940 {hT2 neg hT4 rmoveto
2945 /ArrowPath{c newpath moveto Arrow closepath}bind def
2969 {hT2 neg hT4 rlineto} % 1 - semi-up
2970 {Down} % 2 - semi-down
2971 {Arrow} % 3 - simple
2972 {Gstroke ArrowPath} % 4 - transparent
2973 {Gstroke ArrowPath 1 FillGray} % 5 - hollow
2974 {Gstroke ArrowPath LineColor FillRGB} % 6 - full
2975 {Gstroke UpPath 1 FillGray} % 7 - semi-up-hollow
2976 {Gstroke UpPath LineColor FillRGB} % 8 - semi-up-full
2977 {Gstroke DownPath 1 FillGray} % 9 - semi-down-hollow
2978 {Gstroke DownPath LineColor FillRGB} % 10 - semi-down-full
2979 {Gstroke gsave UserArrow grestore} % 11 - user
2985 RA-vector ArrowShape get exec
2988 ExtraWidth 0 rmoveto
2991 % rotation DrawArrow
3006 /LA{180 DrawArrow}def
3013 /UA{90 DrawArrow}def
3020 /DA{270 DrawArrow}def
3024 %>corner Right Descendent: height arrow corner_RD
3026 % / height > 0 | 0 - none
3028 % * ---------- | 2 - left
3047 h 0 gt{DA}{UA}ifelse
3052 [{cRD0-vector arrow get exec} % 0 - miter
3053 {0 0 0 h hT h rcurveto} % 1 - rounded
3054 {hT h rlineto} % 2 - bevel
3058 {/arrow exch def /h exch def
3059 cRD-vector ChartShape get exec
3063 %>corner Right Ascendent: height arrow corner_RA
3065 % | height > 0 | 0 - none
3067 % *- ---------- | 2 - left
3085 h 0 gt{DA}{UA}ifelse
3091 [{cRA0-vector arrow get exec} % 0 - miter
3092 {0 0 hT 0 hT h rcurveto} % 1 - rounded
3093 {hT h rlineto} % 2 - bevel
3097 {/arrow exch def /h exch def
3098 cRA-vector ChartShape get exec
3102 %>corner Left Descendent: height arrow corner_LD
3104 % \\ height > 0 | 0 - none
3106 % * ---------- | 2 - left
3115 {hT neg h rmoveto xyi
3123 {hT neg h rmoveto xyi
3125 h 0 gt{DA}{UA}ifelse
3130 [{cLD0-vector arrow get exec} % 0 - miter
3131 {0 0 0 h hT neg h rcurveto} % 1 - rounded
3132 {hT neg h rlineto} % 2 - bevel
3136 {/arrow exch def /h exch def
3137 cLD-vector ChartShape get exec
3141 %>corner Left Ascendent: height arrow corner_LA
3143 % | height > 0 | 0 - none
3145 % -* ---------- | 2 - left
3154 {hT neg h rmoveto xyi
3162 {hT neg h rmoveto xyi
3163 h 0 gt{DA}{UA}ifelse
3169 [{cLA0-vector arrow get exec} % 0 - miter
3170 {0 0 hT neg 0 hT neg h rcurveto} % 1 - rounded
3171 {hT neg h rlineto} % 2 - bevel
3175 {/arrow exch def /h exch def
3176 cLA-vector ChartShape get exec
3182 % height prepare_height |- line_height corner_height corner_height
3186 {T add hT neg}ifelse
3190 %>Left Alternative: height LAlt
3217 %>Left Loop: height LLoop
3236 %>Right Alternative: height RAlt
3250 {T neg exch rlineto}
3263 %>Right Loop: height RLoop
3282 % --- Terminal, Non-terminal and Special Basics
3284 % string width prepare-width |- string
3287 dup stringwidth pop space add space add width exch sub ExtraWidth sub 0.5 mul
3291 % string width begin-right
3301 {xo width add Er add yo moveto
3306 % string width begin-left
3315 {xo width add Er add yo moveto
3328 {/half YY yy sub 0.5 mul abs def
3329 xx half add YY moveto
3330 0 0 half neg 0 half neg half neg rcurveto
3331 0 0 0 half neg half half neg rcurveto
3332 XX xx sub abs half sub half sub 0 rlineto
3333 0 0 half 0 half half rcurveto
3334 0 0 0 half half neg half rcurveto}
3336 {/quarter YY yy sub 0.25 mul abs def
3337 xx quarter add YY moveto
3338 quarter neg quarter neg rlineto
3339 0 quarter quarter add neg rlineto
3340 quarter quarter neg rlineto
3341 XX xx sub abs quarter sub quarter sub 0 rlineto
3342 quarter quarter rlineto
3343 0 quarter quarter add rlineto
3344 quarter neg quarter rlineto}
3349 ShapePath-vector shape get exec
3355 Xshadow Xshadow add Xshadow add
3356 Yshadow Yshadow add Yshadow add translate
3370 % string SBound |- string
3372 {/xx c dup /yy exch def
3373 FontHeight add /YY exch def def
3374 dup stringwidth pop xx add /XX exch def
3376 {/yy yy YShadow add def
3377 /XX XX XShadow add def
3386 /XX XX space add space add def
3387 /YY YY space add def
3388 /yy yy space sub def
3389 shadow{doShapeShadow}if
3391 space Descent abs rmoveto
3398 % TeRminal: string TR
3400 {/Effect EffectT def
3402 /shapecolor BackgroundT def
3403 /borderwidth BorderWidthT def
3404 /bordercolor BorderColorT def
3405 /foreground ForegroundT def
3410 %>Right Terminal: string width RT |- x y
3421 %>Left Terminal: string width LT |- x y
3432 %>Right Terminal Default: string width RTD |- x y
3434 {/-save- BorderWidthT def
3435 /BorderWidthT BorderWidthT DefaultWidth add def
3437 /BorderWidthT -save- def
3440 %>Left Terminal Default: string width LTD |- x y
3442 {/-save- BorderWidthT def
3443 /BorderWidthT BorderWidthT DefaultWidth add def
3445 /BorderWidthT -save- def
3450 % Non-Terminal: string NT
3452 {/Effect EffectNT def
3454 /shapecolor BackgroundNT def
3455 /borderwidth BorderWidthNT def
3456 /bordercolor BorderColorNT def
3457 /foreground ForegroundNT def
3458 /shadow ShadowNT def
3462 %>Right Non-Terminal: string width RNT |- x y
3473 %>Left Non-Terminal: string width LNT |- x y
3484 %>Right Non-Terminal Default: string width RNTD |- x y
3486 {/-save- BorderWidthNT def
3487 /BorderWidthNT BorderWidthNT DefaultWidth add def
3489 /BorderWidthNT -save- def
3492 %>Left Non-Terminal Default: string width LNTD |- x y
3494 {/-save- BorderWidthNT def
3495 /BorderWidthNT BorderWidthNT DefaultWidth add def
3497 /BorderWidthNT -save- def
3502 % SPecial: string SP
3504 {/Effect EffectS def
3506 /shapecolor BackgroundS def
3507 /borderwidth BorderWidthS def
3508 /bordercolor BorderColorS def
3509 /foreground ForegroundS def
3514 %>Right SPecial: string width RSP |- x y
3525 %>Left SPecial: string width LSP |- x y
3536 %>Right SPecial Default: string width RSPD |- x y
3538 {/-save- BorderWidthS def
3539 /BorderWidthS BorderWidthS DefaultWidth add def
3541 /BorderWidthS -save- def
3544 %>Left SPecial Default: string width LSPD |- x y
3546 {/-save- BorderWidthS def
3547 /BorderWidthS BorderWidthS DefaultWidth add def
3549 /BorderWidthS -save- def
3552 % --- Repeat and Except basics
3555 {/w width rwidth sub 0.5 mul def
3560 /xx c entry add /YY exch def def
3561 /yy YY height sub def
3562 /XX xx rwidth add def
3563 shadow{doShapeShadow}if
3586 % entry height width rwidth begin-repeat
3596 /shapecolor BackgroundR def
3597 /borderwidth BorderWidthR def
3598 /bordercolor BorderColorR def
3599 /foreground ForegroundR def
3604 % string end-repeat |- x y
3607 space Descent rmoveto
3611 exch space add exch moveto
3615 %>Right RePeat: string entry height width rwidth RRP |- x y
3616 /RRP{begin-repeat right-direction end-repeat}def
3618 %>Left RePeat: string entry height width rwidth LRP |- x y
3619 /LRP{begin-repeat left-direction end-repeat}def
3623 % entry height width rwidth begin-except
3633 /shapecolor BackgroundE def
3634 /borderwidth BorderWidthE def
3635 /bordercolor BorderColorE def
3636 /foreground ForegroundE def
3641 % x-width end-except |- x y
3644 space space add add Descent rmoveto
3645 (-) foreground SetRGB S
3651 %>Right EXcept: x-width entry height width rwidth REX |- x y
3652 /REX{begin-except right-direction end-except}def
3654 %>Left EXcept: x-width entry height width rwidth LEX |- x y
3655 /LEX{begin-except left-direction end-except}def
3659 %>Beginning Of Sequence: BOS |- x y
3660 /BOS{currentpoint}bind def
3662 %>End Of Sequence: x y x1 y1 EOS |- x y
3663 /EOS{pop pop}bind def
3667 %>Beginning Of Production: string width height BOP |- y x
3670 neg yp add /yw exch def
3671 xp add T sub /xw exch def
3672 dup length 0 gt % empty string ==> no production name
3673 {/Effect EffectP def
3674 /fP F ForegroundP SetRGB BackgroundP aload pop true BG S
3684 %>End Of Production: y x delta EOP
3685 /EOPH{add exch moveto}bind def % horizontal
3686 /EOPV{exch pop sub 0 exch moveto}bind def % vertical
3688 % --- Empty Alternative
3690 %>Empty Alternative: width EA |- x y
3701 %>AlTernative: h1 h2 ... hn n width AT |- x y
3703 {xyo xo add /xw exch def
3715 %>OPtional: height width OP |- x y
3732 %>One or More: height width OM |- x y
3746 %>Zero or More: h2 h1 width ZM |- x y
3756 yo add xo T add exch moveto
3760 % === end EBNF engine
3763 "EBNF PostScript prologue")
3766 (defconst ebnf-eps-prologue
3768 /#ebnf2ps#dict 230 dict def
3771 % Initiliaze variables to avoid name-conflicting with document variables.
3772 % This is the case when using `bind' operator.
3773 /-fillp- 0 def /h 0 def
3774 /-ox- 0 def /half 0 def
3775 /-oy- 0 def /height 0 def
3776 /-save- 0 def /ow 0 def
3777 /Ascent 0 def /quarter 0 def
3778 /Descent 0 def /rXX 0 def
3779 /Effect 0 def /rYY 0 def
3780 /FontHeight 0 def /rwidth 0 def
3781 /LineThickness 0 def /rxx 0 def
3782 /OverlinePosition 0 def /ryy 0 def
3783 /SpaceBackground 0 def /shadow 0 def
3784 /StrikeoutPosition 0 def /shape 0 def
3785 /UnderlinePosition 0 def /shapecolor 0 def
3786 /XBox 0 def /space 0 def
3787 /XX 0 def /st 1 string def
3788 /Xshadow 0 def /w 0 def
3789 /YBox 0 def /width 0 def
3791 /Yshadow 0 def /xo 0 def
3792 /arrow 0 def /xp 0 def
3793 /bg false def /xt 0 def
3794 /bgcolor 0 def /xw 0 def
3795 /bordercolor 0 def /xx 0 def
3796 /borderwidth 0 def /yi 0 def
3798 /entry 0 def /yp 0 def
3799 /foreground 0 def /yt 0 def
3803 % ISOLatin1Encoding stolen from ps_init.ps in GhostScript 2.6.1.4:
3804 /ISOLatin1Encoding where
3806 {% -- The ISO Latin-1 encoding vector isn't known, so define it.
3807 % -- The first half is the same as the standard encoding,
3808 % -- except for minus instead of hyphen at code 055.
3810 StandardEncoding 0 45 getinterval aload pop
3812 StandardEncoding 46 82 getinterval aload pop
3813 %*** NOTE: the following are missing in the Adobe documentation,
3814 %*** but appear in the displayed table:
3815 %*** macron at 0225, dieresis at 0230, cedilla at 0233, space at 0240.
3817 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
3818 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
3819 /dotlessi /grave /acute /circumflex /tilde /macron /breve /dotaccent
3820 /dieresis /.notdef /ring /cedilla /.notdef /hungarumlaut /ogonek /caron
3822 /space /exclamdown /cent /sterling
3823 /currency /yen /brokenbar /section
3824 /dieresis /copyright /ordfeminine /guillemotleft
3825 /logicalnot /hyphen /registered /macron
3826 /degree /plusminus /twosuperior /threesuperior
3827 /acute /mu /paragraph /periodcentered
3828 /cedilla /onesuperior /ordmasculine /guillemotright
3829 /onequarter /onehalf /threequarters /questiondown
3831 /Agrave /Aacute /Acircumflex /Atilde
3832 /Adieresis /Aring /AE /Ccedilla
3833 /Egrave /Eacute /Ecircumflex /Edieresis
3834 /Igrave /Iacute /Icircumflex /Idieresis
3835 /Eth /Ntilde /Ograve /Oacute
3836 /Ocircumflex /Otilde /Odieresis /multiply
3837 /Oslash /Ugrave /Uacute /Ucircumflex
3838 /Udieresis /Yacute /Thorn /germandbls
3840 /agrave /aacute /acircumflex /atilde
3841 /adieresis /aring /ae /ccedilla
3842 /egrave /eacute /ecircumflex /edieresis
3843 /igrave /iacute /icircumflex /idieresis
3844 /eth /ntilde /ograve /oacute
3845 /ocircumflex /otilde /odieresis /divide
3846 /oslash /ugrave /uacute /ucircumflex
3847 /udieresis /yacute /thorn /ydieresis
3851 /reencodeFontISO %def
3853 length 12 add dict % Make a new font (a new dict the same size
3854 % as the old one) with room for our new symbols.
3856 begin % Make the new font the current dictionary.
3858 {def}{pop pop}ifelse
3859 }forall % Copy each of the symbols from the old dictionary
3860 % to the new one except for the font ID.
3862 currentdict /FontType get 0 ne
3863 {/Encoding ISOLatin1Encoding def}if % Override the encoding with
3864 % the ISOLatin1 encoding.
3866 % Use the font's bounding box to determine the ascent, descent,
3867 % and overall height; don't forget that these values have to be
3868 % transformed using the font's matrix.
3875 % | | | | Ascent (usually > 0)
3877 % (0 0) -> +--+----+-------->
3879 % | | v Descent (usually < 0)
3880 % (x1 y1) --> +----+ - -
3882 currentdict /FontType get 0 ne
3883 {/FontBBox load aload pop % -- x1 y1 x2 y2
3884 FontMatrix transform /Ascent exch def pop
3885 FontMatrix transform /Descent exch def pop}
3886 {/PrimaryFont FDepVector 0 get def
3887 PrimaryFont /FontBBox get aload pop
3888 PrimaryFont /FontMatrix get transform /Ascent exch def pop
3889 PrimaryFont /FontMatrix get transform /Descent exch def pop
3892 /FontHeight Ascent Descent sub def % use `sub' because descent < 0
3894 % Define these in case they're not in the FontInfo
3895 % (also, here they're easier to get to).
3896 /UnderlinePosition Descent 0.70 mul def
3897 /OverlinePosition Descent UnderlinePosition sub Ascent add def
3898 /StrikeoutPosition Ascent 0.30 mul def
3899 /LineThickness FontHeight 0.05 mul def
3900 /Xshadow FontHeight 0.08 mul def
3901 /Yshadow FontHeight -0.09 mul def
3902 /SpaceBackground Descent neg UnderlinePosition add def
3903 /XBox Descent neg def
3904 /YBox LineThickness 0.7 mul def
3906 currentdict % Leave the new font on the stack
3907 end % Stop using the font as the current dictionary
3908 definefont % Put the font into the font dictionary
3909 pop % Discard the returned font
3913 /DefFont{findfont exch scalefont reencodeFontISO}def
3918 dup /Ascent get /Ascent exch def
3919 dup /Descent get /Descent exch def
3920 dup /FontHeight get /FontHeight exch def
3921 dup /UnderlinePosition get /UnderlinePosition exch def
3922 dup /OverlinePosition get /OverlinePosition exch def
3923 dup /StrikeoutPosition get /StrikeoutPosition exch def
3924 dup /LineThickness get /LineThickness exch def
3925 dup /Xshadow get /Xshadow exch def
3926 dup /Yshadow get /Yshadow exch def
3927 dup /SpaceBackground get /SpaceBackground exch def
3928 dup /XBox get /XBox exch def
3929 dup /YBox get /YBox exch def
3942 /FillBgColor{bgcolor aload pop setrgbcolor fill}bind def
3944 % stack: fill-or-not lower-x lower-y upper-x upper-y |- --
3957 % top of stack: fill-or-not
3959 {LineThickness setlinewidth stroke}
3964 % stack: string fill-or-not |- --
3967 /-ox- currentpoint /-oy- exch def def
3969 LineThickness setlinewidth
3971 st dup true charpath
3972 -fillp- {gsave FillBgColor grestore}if
3974 -oy- add /-oy- exch def
3975 -ox- add /-ox- exch def
3982 % stack: fill-or-not delta |- --
3985 xx XBox sub dd sub yy YBox sub dd sub
3986 XX XBox add dd add YY YBox add dd add
3990 % stack: string |- --
3993 Xshadow Yshadow rmoveto
3998 % stack: position |- --
4000 {currentpoint exch pop add dup
4006 LineThickness setlinewidth stroke
4010 % stack: string |- --
4011 % effect: 1 - underline 2 - strikeout 4 - overline
4012 % 8 - shadow 16 - box 32 - outline
4014 {/xx currentpoint dup Descent add /yy exch def
4015 Ascent add /YY exch def def
4016 dup stringwidth pop xx add /XX exch def
4018 {/yy yy Yshadow add def
4019 /XX XX Xshadow add def
4024 {SpaceBackground doBox}
4025 {xx yy XX YY doRect}
4028 Effect 16 and 0 ne{false 0 doBox}if % box
4029 Effect 8 and 0 ne{dup doShadow}if % shadow
4031 {true doOutline} % outline
4032 {show} % normal text
4034 Effect 1 and 0 ne{UnderlinePosition Hline}if % underline
4035 Effect 2 and 0 ne{StrikeoutPosition Hline}if % strikeout
4036 Effect 4 and 0 ne{OverlinePosition Hline}if % overline
4040 "EBNF EPS prologue")
4043 (defconst ebnf-eps-begin
4047 % x y #ebnf2ps#begin
4049 {#ebnf2ps#dict begin /#ebnf2ps#save save def
4050 moveto false BG 0.0 0.0 0.0 setrgbcolor}def
4052 /#ebnf2ps#end{showpage #ebnf2ps#save restore end}def
4059 (defconst ebnf-eps-end
4066 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4070 (defvar ebnf-format-float
"%1.3f")
4073 (defun ebnf-format-float (&rest floats
)
4076 (format ebnf-format-float float
))
4081 (defun ebnf-format-color (format-str color default
)
4082 (let* ((the-color (or color default
))
4083 (rgb (ps-color-scale the-color
)))
4086 (ebnf-format-float (nth 0 rgb
) (nth 1 rgb
) (nth 2 rgb
))
4091 (defvar ebnf-message-float
"%3.2f")
4094 (defsubst ebnf-message-float
(format-str value
)
4096 (format ebnf-message-float value
)))
4099 (defvar ebnf-total
0)
4100 (defvar ebnf-nprod
0)
4103 (defsubst ebnf-message-info
(messag)
4104 (message "%s...%3d%%"
4106 (round (/ (* (setq ebnf-nprod
(1+ ebnf-nprod
)) 100.0) ebnf-total
))))
4109 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4113 (defmacro ebnf-node-kind
(vec &optional value
)
4115 `(aset ,vec
0 ,value
)
4119 (defmacro ebnf-node-width-func
(node width
)
4120 `(funcall (aref ,node
1) ,node
,width
))
4123 (defmacro ebnf-node-dimension-func
(node &optional value
)
4125 `(aset ,node
2 ,value
)
4126 `(funcall (aref ,node
2) ,node
)))
4129 (defmacro ebnf-node-entry
(vec &optional value
)
4131 `(aset ,vec
3 ,value
)
4135 (defmacro ebnf-node-height
(vec &optional value
)
4137 `(aset ,vec
4 ,value
)
4141 (defmacro ebnf-node-width
(vec &optional value
)
4143 `(aset ,vec
5 ,value
)
4147 (defmacro ebnf-node-name
(vec)
4151 (defmacro ebnf-node-list
(vec &optional value
)
4153 `(aset ,vec
6 ,value
)
4157 (defmacro ebnf-node-default
(vec)
4161 (defmacro ebnf-node-production
(vec &optional value
)
4163 `(aset ,vec
7 ,value
)
4167 (defmacro ebnf-node-separator
(vec &optional value
)
4169 `(aset ,vec
7 ,value
)
4173 (defmacro ebnf-node-action
(vec &optional value
)
4175 `(aset ,vec
8 ,value
)
4179 (defmacro ebnf-node-generation
(node)
4180 `(funcall (ebnf-node-kind ,node
) ,node
))
4183 (defmacro ebnf-max-width
(prod)
4184 `(max (ebnf-node-width ,prod
)
4185 (+ (* (length (ebnf-node-name ,prod
))
4187 ebnf-production-horizontal-space
)))
4190 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4191 ;; PostScript generation
4194 (defun ebnf-generate-eps (ebnf-tree)
4195 (let* ((ps-color-p (and ebnf-color-p
(ps-color-device)))
4196 (ps-print-color-scale (if ps-color-p
4197 (float (car (ps-color-values "white")))
4199 (ebnf-total (length ebnf-tree
))
4201 (old-ps-output (symbol-function 'ps-output
))
4202 (old-ps-output-string (symbol-function 'ps-output-string
))
4203 (eps-buffer (get-buffer-create ebnf-eps-buffer-name
))
4204 ebnf-debug-ps error-msg horizontal
4205 prod prod-name prod-width prod-height prod-list file-list
)
4206 ;; redefines `ps-output' and `ps-output-string'
4207 (defalias 'ps-output
'ebnf-eps-output
)
4208 (defalias 'ps-output-string
'ps-output-string-prim
)
4209 ;; generate EPS file
4211 (condition-case data
4214 (setq prod
(car ebnf-tree
)
4215 prod-name
(ebnf-node-name prod
)
4216 prod-width
(ebnf-max-width prod
)
4217 prod-height
(ebnf-node-height prod
)
4218 horizontal
(memq (ebnf-node-action prod
)
4220 ;; generate production in EPS buffer
4222 (set-buffer eps-buffer
)
4223 (setq ebnf-eps-upper-x
0.0
4224 ebnf-eps-upper-y
0.0
4225 ebnf-eps-max-width prod-width
4226 ebnf-eps-max-height prod-height
)
4227 (ebnf-generate-production prod
))
4228 (if (setq prod-list
(cdr (assoc prod-name
4229 ebnf-eps-production-list
)))
4230 ;; insert EPS buffer in all buffer associated with production
4231 (ebnf-eps-production-list prod-list
'file-list horizontal
4232 prod-width prod-height eps-buffer
)
4233 ;; write EPS file for production
4234 (ebnf-eps-finish-and-write eps-buffer
4235 (ebnf-eps-filename prod-name
)))
4236 ;; prepare for next loop
4238 (set-buffer eps-buffer
)
4240 (setq ebnf-tree
(cdr ebnf-tree
)))
4241 ;; write and kill temporary buffers
4242 (ebnf-eps-write-kill-temp file-list t
)
4243 (setq file-list nil
))
4246 (setq error-msg
(error-message-string data
)))))
4247 ;; restore `ps-output' and `ps-output-string'
4248 (defalias 'ps-output old-ps-output
)
4249 (defalias 'ps-output-string old-ps-output-string
)
4250 ;; kill temporary buffers
4251 (kill-buffer eps-buffer
)
4252 (ebnf-eps-write-kill-temp file-list nil
)
4253 (and error-msg
(error error-msg
))
4257 ;; write and kill temporary buffers
4258 (defun ebnf-eps-write-kill-temp (file-list write-p
)
4260 (let ((buffer (get-buffer (concat " *" (car file-list
) "*"))))
4263 (ebnf-eps-finish-and-write buffer
(car file-list
)))
4264 (kill-buffer buffer
)))
4265 (setq file-list
(cdr file-list
))))
4268 ;; insert EPS buffer in all buffer associated with production
4269 (defun ebnf-eps-production-list (prod-list file-list-sym horizontal
4270 prod-width prod-height eps-buffer
)
4272 (add-to-list file-list-sym
(car prod-list
))
4274 (set-buffer (get-buffer-create (concat " *" (car prod-list
) "*")))
4275 (goto-char (point-max))
4278 ((zerop (buffer-size))
4279 (setq ebnf-eps-upper-x
0.0
4280 ebnf-eps-upper-y
0.0
4281 ebnf-eps-max-width prod-width
4282 ebnf-eps-max-height prod-height
))
4285 (ebnf-eop-horizontal ebnf-eps-prod-width
)
4286 (setq ebnf-eps-max-width
(+ ebnf-eps-max-width
4287 ebnf-production-horizontal-space
4289 ebnf-eps-max-height
(max ebnf-eps-max-height prod-height
)))
4292 (ebnf-eop-vertical ebnf-eps-max-height
)
4293 (setq ebnf-eps-upper-x
(max ebnf-eps-upper-x ebnf-eps-max-width
)
4294 ebnf-eps-upper-y
(if (zerop ebnf-eps-upper-y
)
4297 ebnf-production-vertical-space
4298 ebnf-eps-max-height
))
4299 ebnf-eps-max-width prod-width
4300 ebnf-eps-max-height prod-height
))
4302 (setq ebnf-eps-prod-width prod-width
)
4303 (insert-buffer-substring eps-buffer
))
4304 (setq prod-list
(cdr prod-list
))))
4307 (defun ebnf-generate (ebnf-tree)
4308 (let* ((ps-color-p (and ebnf-color-p
(ps-color-device)))
4309 (ps-print-color-scale (if ps-color-p
4310 (float (car (ps-color-values "white")))
4312 ps-zebra-stripes ps-line-number ps-razzle-dazzle
4314 ps-print-begin-sheet-hook
4315 ps-print-begin-page-hook
4316 ps-print-begin-column-hook
)
4317 (ps-generate (current-buffer) (point-min) (point-max)
4318 'ebnf-generate-postscript
)))
4321 (defvar ebnf-tree nil
)
4322 (defvar ebnf-direction
"R")
4325 (defun ebnf-generate-postscript (from to
)
4327 (if ebnf-horizontal-max-height
4328 (ebnf-generate-with-max-height)
4329 (ebnf-generate-without-max-height))
4333 (defun ebnf-generate-with-max-height ()
4334 (let ((ebnf-total (length ebnf-tree
))
4336 next-line max-height prod the-width
)
4338 ;; find next line point
4339 (setq next-line ebnf-tree
4340 prod
(car ebnf-tree
)
4341 max-height
(ebnf-node-height prod
))
4342 (ebnf-begin-line prod
(ebnf-max-width prod
))
4343 (while (and (setq next-line
(cdr next-line
))
4344 (setq prod
(car next-line
))
4345 (memq (ebnf-node-action prod
) ebnf-action-list
)
4346 (setq the-width
(ebnf-max-width prod
))
4347 (<= the-width ps-width-remaining
))
4348 (setq max-height
(max max-height
(ebnf-node-height prod
))
4349 ps-width-remaining
(- ps-width-remaining
4351 ebnf-production-horizontal-space
))))
4352 ;; generate current line
4353 (ebnf-newline max-height
)
4354 (setq prod
(car ebnf-tree
))
4355 (ebnf-generate-production prod
)
4356 (while (not (eq (setq ebnf-tree
(cdr ebnf-tree
)) next-line
))
4357 (ebnf-eop-horizontal (ebnf-max-width prod
))
4358 (setq prod
(car ebnf-tree
))
4359 (ebnf-generate-production prod
))
4360 (ebnf-eop-vertical max-height
))))
4363 (defun ebnf-generate-without-max-height ()
4364 (let ((ebnf-total (length ebnf-tree
))
4366 max-height prod bef-width cur-width
)
4368 ;; generate current line
4369 (setq prod
(car ebnf-tree
)
4370 max-height
(ebnf-node-height prod
)
4371 bef-width
(ebnf-max-width prod
))
4372 (ebnf-begin-line prod bef-width
)
4373 (ebnf-generate-production prod
)
4374 (while (and (setq ebnf-tree
(cdr ebnf-tree
))
4375 (setq prod
(car ebnf-tree
))
4376 (memq (ebnf-node-action prod
) ebnf-action-list
)
4377 (setq cur-width
(ebnf-max-width prod
))
4378 (<= cur-width ps-width-remaining
)
4379 (<= (ebnf-node-height prod
) ps-height-remaining
))
4380 (ebnf-eop-horizontal bef-width
)
4381 (ebnf-generate-production prod
)
4382 (setq bef-width cur-width
4383 max-height
(max max-height
(ebnf-node-height prod
))
4384 ps-width-remaining
(- ps-width-remaining
4386 ebnf-production-horizontal-space
))))
4387 (ebnf-eop-vertical max-height
)
4388 ;; prepare next line
4389 (ebnf-newline max-height
))))
4392 (defun ebnf-begin-line (prod width
)
4393 (and (or (eq (ebnf-node-action prod
) 'form-feed
)
4394 (> (ebnf-node-height prod
) ps-height-remaining
))
4396 (setq ps-width-remaining
(- ps-width-remaining
4398 ebnf-production-horizontal-space
))))
4401 (defun ebnf-newline (height)
4402 (and (> height ps-height-remaining
)
4404 (setq ps-width-remaining ps-print-width
4405 ps-height-remaining
(- ps-height-remaining
4407 ebnf-production-vertical-space
))))
4410 ;; [production width-fun dim-fun entry height width name production action]
4411 (defun ebnf-generate-production (production)
4412 (ebnf-message-info "Generating")
4413 (run-hooks 'ebnf-production-hook
)
4414 (ps-output-string (if ebnf-production-name-p
4415 (ebnf-node-name production
)
4419 (ebnf-node-width production
)
4420 (+ (if ebnf-production-name-p
4423 (ebnf-node-entry (ebnf-node-production production
))))
4425 (ebnf-node-generation (ebnf-node-production production
))
4426 (ps-output "EOS\n"))
4429 ;; [alternative width-fun dim-fun entry height width list]
4430 (defun ebnf-generate-alternative (alternative)
4431 (let ((alt (ebnf-node-list alternative
))
4432 (entry (ebnf-node-entry alternative
))
4434 alt-height alt-entry
)
4436 (ps-output (ebnf-format-float (- entry
(ebnf-node-entry (car alt
))))
4438 (setq entry
(- entry
(ebnf-node-height (car alt
)) ebnf-vertical-space
)
4441 (ps-output (format "%d " nlist
)
4442 (ebnf-format-float (ebnf-node-width alternative
))
4444 (setq alt
(ebnf-node-list alternative
))
4446 (ebnf-node-generation (car alt
))
4447 (setq alt-height
(- (ebnf-node-height (car alt
))
4448 (ebnf-node-entry (car alt
)))))
4449 (while (setq alt
(cdr alt
))
4450 (setq alt-entry
(ebnf-node-entry (car alt
)))
4451 (ebnf-vertical-movement
4452 (- (+ alt-height ebnf-vertical-space alt-entry
)))
4453 (ebnf-node-generation (car alt
))
4454 (setq alt-height
(- (ebnf-node-height (car alt
)) alt-entry
))))
4455 (ps-output "EOS\n"))
4458 ;; [sequence width-fun dim-fun entry height width list]
4459 (defun ebnf-generate-sequence (sequence)
4461 (let ((seq (ebnf-node-list sequence
))
4464 (ebnf-node-generation (car seq
))
4465 (setq seq-width
(ebnf-node-width (car seq
))))
4466 (while (setq seq
(cdr seq
))
4467 (ebnf-horizontal-movement seq-width
)
4468 (ebnf-node-generation (car seq
))
4469 (setq seq-width
(ebnf-node-width (car seq
)))))
4470 (ps-output "EOS\n"))
4473 ;; [terminal width-fun dim-fun entry height width name]
4474 (defun ebnf-generate-terminal (terminal)
4475 (ebnf-gen-terminal terminal
"T"))
4478 ;; [non-terminal width-fun dim-fun entry height width name]
4479 (defun ebnf-generate-non-terminal (non-terminal)
4480 (ebnf-gen-terminal non-terminal
"NT"))
4483 ;; [empty width-fun dim-fun entry height width]
4484 (defun ebnf-generate-empty (empty)
4485 (ebnf-empty-alternative (ebnf-node-width empty
)))
4488 ;; [optional width-fun dim-fun entry height width element]
4489 (defun ebnf-generate-optional (optional)
4490 (let ((the-optional (ebnf-node-list optional
)))
4491 (ps-output (ebnf-format-float
4492 (+ (- (ebnf-node-height the-optional
)
4493 (ebnf-node-entry optional
))
4494 ebnf-vertical-space
)
4495 (ebnf-node-width optional
))
4497 (ebnf-node-generation the-optional
)
4498 (ps-output "EOS\n")))
4501 ;; [one-or-more width-fun dim-fun entry height width element separator]
4502 (defun ebnf-generate-one-or-more (one-or-more)
4503 (let* ((width (ebnf-node-width one-or-more
))
4504 (sep (ebnf-node-separator one-or-more
))
4505 (entry (- (ebnf-node-entry one-or-more
)
4507 (ebnf-node-entry sep
)
4509 (ps-output (ebnf-format-float entry width
)
4511 (ebnf-node-generation (ebnf-node-list one-or-more
))
4512 (ebnf-vertical-movement entry
)
4514 (let ((ebnf-direction "L"))
4515 (ebnf-node-generation sep
))
4516 (ebnf-empty-alternative (- width ebnf-horizontal-space
))))
4517 (ps-output "EOS\n"))
4520 ;; [zero-or-more width-fun dim-fun entry height width element separator]
4521 (defun ebnf-generate-zero-or-more (zero-or-more)
4522 (let* ((width (ebnf-node-width zero-or-more
))
4523 (node-list (ebnf-node-list zero-or-more
))
4524 (list-entry (ebnf-node-entry node-list
))
4525 (node-sep (ebnf-node-separator zero-or-more
))
4526 (entry (+ list-entry
4529 (- (ebnf-node-height node-sep
)
4530 (ebnf-node-entry node-sep
))
4532 (ps-output (ebnf-format-float entry
4533 (+ (- (ebnf-node-height node-list
)
4535 ebnf-vertical-space
)
4538 (ebnf-node-generation (ebnf-node-list zero-or-more
))
4539 (ebnf-vertical-movement entry
)
4540 (if (ebnf-node-separator zero-or-more
)
4541 (let ((ebnf-direction "L"))
4542 (ebnf-node-generation (ebnf-node-separator zero-or-more
)))
4543 (ebnf-empty-alternative (- width ebnf-horizontal-space
))))
4544 (ps-output "EOS\n"))
4547 ;; [special width-fun dim-fun entry height width name]
4548 (defun ebnf-generate-special (special)
4549 (ebnf-gen-terminal special
"SP"))
4552 ;; [repeat width-fun dim-fun entry height width times element]
4553 (defun ebnf-generate-repeat (repeat)
4554 (let ((times (ebnf-node-name repeat
))
4555 (element (ebnf-node-separator repeat
)))
4556 (ps-output-string times
)
4559 (ebnf-node-entry repeat
)
4560 (ebnf-node-height repeat
)
4561 (ebnf-node-width repeat
)
4563 (+ (ebnf-node-width element
)
4564 ebnf-space-R ebnf-space-R ebnf-space-R
4565 (* (length times
) ebnf-font-width-R
))
4567 " " ebnf-direction
"RP\n")
4569 (ebnf-node-generation element
)))
4570 (ps-output "EOS\n"))
4573 ;; [except width-fun dim-fun entry height width element element]
4574 (defun ebnf-generate-except (except)
4575 (let* ((element (ebnf-node-list except
))
4576 (exception (ebnf-node-separator except
))
4577 (width (ebnf-node-width element
)))
4578 (ps-output (ebnf-format-float
4580 (ebnf-node-entry except
)
4581 (ebnf-node-height except
)
4582 (ebnf-node-width except
)
4584 ebnf-space-E ebnf-space-E ebnf-space-E
4587 (+ (ebnf-node-width exception
) ebnf-space-E
)
4589 " " ebnf-direction
"EX\n")
4590 (ebnf-node-generation (ebnf-node-list except
))
4592 (ebnf-horizontal-movement (+ width ebnf-space-E
4593 ebnf-font-width-E ebnf-space-E
))
4594 (ebnf-node-generation exception
)))
4595 (ps-output "EOS\n"))
4598 (defun ebnf-gen-terminal (node code
)
4599 (ps-output-string (ebnf-node-name node
))
4600 (ps-output " " (ebnf-format-float (ebnf-node-width node
))
4601 " " ebnf-direction code
4602 (if (ebnf-node-default node
)
4607 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4608 ;; Internal functions
4611 (defun ebnf-directory (fun &optional directory
)
4612 "Process files in DIRECTORY applying function FUN on each file.
4614 If DIRECTORY is nil, use `default-directory'.
4616 Only files in DIRECTORY that match `ebnf-file-suffix-regexp' (which see) are
4618 (let ((files (directory-files (or directory default-directory
)
4619 t ebnf-file-suffix-regexp
)))
4621 (set-buffer (find-file-noselect (car files
)))
4623 (setq buffer-backed-up t
) ; Do not back it up.
4624 (save-buffer) ; Just save new version.
4625 (kill-buffer (current-buffer))
4626 (setq files
(cdr files
)))))
4629 (defun ebnf-file (fun file
&optional do-not-kill-buffer-when-done
)
4630 "Process the named FILE applying function FUN.
4632 If optional arg DO-NOT-KILL-BUFFER-WHEN-DONE is non-nil, the buffer isn't
4633 killed after process termination."
4634 (set-buffer (find-file-noselect file
))
4636 (or do-not-kill-buffer-when-done
4637 (kill-buffer (current-buffer))))
4640 ;; function `ebnf-range-regexp' is used to avoid a bug of `skip-chars-forward'
4641 ;; on version 20.4.1, that is, it doesn't accept ranges like "\240-\377" (or
4642 ;; "\177-\237"), but it accepts the character sequence from \240 to \377 (or
4643 ;; from \177 to \237). It seems that version 20.7 has the same problem.
4644 (defun ebnf-range-regexp (prefix from to
)
4647 (setq str
(concat str
(char-to-string from
))
4649 (concat prefix str
)))
4652 (defvar ebnf-map-name
4653 (let ((map (make-vector 256 ?\_
)))
4654 (mapcar #'(lambda (char)
4655 (aset map char char
))
4656 (concat "#$%&+-.0123456789=?@~"
4657 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
4658 "abcdefghijklmnopqrstuvwxyz"))
4662 (defun ebnf-eps-filename (str)
4663 (let* ((len (length str
))
4665 (new (make-string len ?\s
)))
4667 (aset new stri
(aref ebnf-map-name
(aref str stri
)))
4668 (setq stri
(1+ stri
)))
4669 (concat ebnf-eps-prefix new
".eps")))
4672 (defun ebnf-eps-output (&rest args
)
4675 (setq args
(cdr args
))))
4678 (defun ebnf-generate-region (from to gen-func
)
4679 (run-hooks 'ebnf-hook
)
4680 (let ((ebnf-limit (max from to
))
4681 (error-msg "SYNTAX")
4686 (condition-case data
4687 (let ((tree (ebnf-parse-and-sort (min from to
))))
4689 (setq error-msg
"EMPTY RULES"
4690 tree
(ebnf-eliminate-empty-rules tree
))
4691 (setq error-msg
"OPTMIZE"
4692 tree
(ebnf-optimize tree
))
4693 (setq error-msg
"DIMENSIONS"
4694 tree
(ebnf-dimensions tree
))
4695 (setq error-msg
"GENERATION")
4696 (funcall gen-func tree
))
4697 (setq error-msg nil
)) ; here it's ok
4701 (setq the-point
(max (1- (point)) (point-min))
4702 error-msg
(concat error-msg
": "
4703 (error-message-string data
)
4705 (and (string= error-msg
"SYNTAX")
4706 (format "at position %d "
4708 (format "in buffer \"%s\"."
4709 (buffer-name)))))))))
4713 (goto-char the-point
)
4714 (if ebnf-stop-on-error
4716 (message "%s" error-msg
)))
4717 ;; generated output OK
4720 ;; syntax checked OK
4722 (message "EBNF syntactic analysis: NO ERRORS.")))))
4725 (defun ebnf-parse-and-sort (start)
4727 (let ((tree (funcall ebnf-parser-func start
)))
4728 (if ebnf-sort-production
4730 (message "Sorting...")
4732 (if (eq ebnf-sort-production
'ascending
)
4733 'ebnf-sorter-ascending
4734 'ebnf-sorter-descending
)))
4738 (defun ebnf-sorter-ascending (first second
)
4739 (string< (ebnf-node-name first
)
4740 (ebnf-node-name second
)))
4743 (defun ebnf-sorter-descending (first second
)
4744 (string< (ebnf-node-name second
)
4745 (ebnf-node-name first
)))
4748 (defun ebnf-empty-alternative (width)
4749 (ps-output (ebnf-format-float width
) " EA\n"))
4752 (defun ebnf-vertical-movement (height)
4753 (ps-output (ebnf-format-float height
) " vm\n"))
4756 (defun ebnf-horizontal-movement (width)
4757 (ps-output (ebnf-format-float width
) " hm\n"))
4760 (defun ebnf-entry (height)
4761 (* height ebnf-entry-percentage
))
4764 (defun ebnf-eop-vertical (height)
4765 (ps-output (ebnf-format-float (+ height ebnf-production-vertical-space
))
4769 (defun ebnf-eop-horizontal (width)
4770 (ps-output (ebnf-format-float (+ width ebnf-production-horizontal-space
))
4774 (defun ebnf-new-page ()
4775 (when (< ps-height-remaining ps-print-height
)
4776 (run-hooks 'ebnf-page-hook
)
4781 (defsubst ebnf-font-size
(font) (nth 0 font
))
4782 (defsubst ebnf-font-name
(font) (nth 1 font
))
4783 (defsubst ebnf-font-foreground
(font) (nth 2 font
))
4784 (defsubst ebnf-font-background
(font) (nth 3 font
))
4785 (defsubst ebnf-font-list
(font) (nthcdr 4 font
))
4786 (defsubst ebnf-font-attributes
(font)
4787 (lsh (ps-extension-bit (cdr font
)) -
2))
4790 (defconst ebnf-font-name-select
4791 (vector 'normal
'bold
'italic
'bold-italic
))
4794 (defun ebnf-font-name-select (font)
4795 (let* ((font-list (ebnf-font-list font
))
4796 (font-index (+ (if (memq 'bold font-list
) 1 0)
4797 (if (memq 'italic font-list
) 2 0)))
4798 (name (ebnf-font-name font
))
4799 (database (cdr (assoc name ps-font-info-database
)))
4800 (info-list (or (cdr (assoc 'fonts database
))
4801 (error "Invalid font: %s" name
))))
4802 (or (cdr (assoc (aref ebnf-font-name-select font-index
)
4804 (error "Invalid attributes for font %s" name
))))
4807 (defun ebnf-font-select (font select
)
4808 (let* ((name (ebnf-font-name font
))
4809 (database (cdr (assoc name ps-font-info-database
)))
4810 (size (cdr (assoc 'size database
)))
4811 (base (cdr (assoc select database
))))
4813 (/ (* (ebnf-font-size font
) base
)
4815 (error "Invalid font: %s" name
))))
4818 (defsubst ebnf-font-width
(font)
4819 (ebnf-font-select font
'avg-char-width
))
4820 (defsubst ebnf-font-height
(font)
4821 (ebnf-font-select font
'line-height
))
4824 (defconst ebnf-syntax-alist
4825 ;; 0.syntax 1.parser 2.initializer
4826 '((iso-ebnf ebnf-iso-parser ebnf-iso-initialize
)
4827 (yacc ebnf-yac-parser ebnf-yac-initialize
)
4828 (abnf ebnf-abn-parser ebnf-abn-initialize
)
4829 (ebnf ebnf-bnf-parser ebnf-bnf-initialize
)
4830 (ebnfx ebnf-ebx-parser ebnf-ebx-initialize
)
4831 (dtd ebnf-dtd-parser ebnf-dtd-initialize
))
4832 "Alist associating EBNF syntax with a parser and an initializer.")
4835 (defun ebnf-begin-job ()
4836 (ps-printing-region nil nil nil
)
4837 (if ebnf-use-float-format
4838 (setq ebnf-format-float
"%1.3f"
4839 ebnf-message-float
"%3.2f")
4840 (setq ebnf-format-float
"%s"
4841 ebnf-message-float
"%s"))
4842 (ebnf-otz-initialize)
4843 ;; to avoid compilation gripes when calling autoloaded functions
4844 (let ((init (or (assoc ebnf-syntax ebnf-syntax-alist
)
4845 (assoc 'ebnf ebnf-syntax-alist
))))
4846 (setq ebnf-parser-func
(nth 1 init
))
4847 (funcall (nth 2 init
)))
4848 (and ebnf-terminal-regexp
; ensures that it's a string or nil
4849 (not (stringp ebnf-terminal-regexp
))
4850 (setq ebnf-terminal-regexp nil
))
4851 (or (and ebnf-eps-prefix
; ensures that it's a string
4852 (stringp ebnf-eps-prefix
))
4853 (setq ebnf-eps-prefix
"ebnf--"))
4854 (setq ebnf-entry-percentage
; ensures value between 0.0 and 1.0
4855 (min (max ebnf-entry-percentage
0.0) 1.0)
4856 ebnf-action-list
(if ebnf-horizontal-orientation
4860 ebnf-fonts-required nil
4863 ebnf-eps-context nil
4864 ebnf-eps-production-list nil
4865 ebnf-eps-upper-x
0.0
4866 ebnf-eps-upper-y
0.0
4867 ebnf-font-height-P
(ebnf-font-height ebnf-production-font
)
4868 ebnf-font-height-T
(ebnf-font-height ebnf-terminal-font
)
4869 ebnf-font-height-NT
(ebnf-font-height ebnf-non-terminal-font
)
4870 ebnf-font-height-S
(ebnf-font-height ebnf-special-font
)
4871 ebnf-font-height-E
(ebnf-font-height ebnf-except-font
)
4872 ebnf-font-height-R
(ebnf-font-height ebnf-repeat-font
)
4873 ebnf-font-width-P
(ebnf-font-width ebnf-production-font
)
4874 ebnf-font-width-T
(ebnf-font-width ebnf-terminal-font
)
4875 ebnf-font-width-NT
(ebnf-font-width ebnf-non-terminal-font
)
4876 ebnf-font-width-S
(ebnf-font-width ebnf-special-font
)
4877 ebnf-font-width-E
(ebnf-font-width ebnf-except-font
)
4878 ebnf-font-width-R
(ebnf-font-width ebnf-repeat-font
)
4879 ebnf-space-T
(* ebnf-font-height-T
0.5)
4880 ebnf-space-NT
(* ebnf-font-height-NT
0.5)
4881 ebnf-space-S
(* ebnf-font-height-S
0.5)
4882 ebnf-space-E
(* ebnf-font-height-E
0.5)
4883 ebnf-space-R
(* ebnf-font-height-R
0.5))
4884 (let ((basic (+ ebnf-font-height-T ebnf-font-height-NT
)))
4885 (setq ebnf-basic-width
(* basic
0.5)
4886 ebnf-horizontal-space
(+ basic basic
)
4887 ebnf-basic-height ebnf-basic-width
4888 ebnf-vertical-space ebnf-basic-width
)
4889 ;; ensures value is greater than zero
4890 (or (and (numberp ebnf-production-horizontal-space
)
4891 (> ebnf-production-horizontal-space
0.0))
4892 (setq ebnf-production-horizontal-space basic
))
4893 ;; ensures value is greater than zero
4894 (or (and (numberp ebnf-production-vertical-space
)
4895 (> ebnf-production-vertical-space
0.0))
4896 (setq ebnf-production-vertical-space basic
))))
4899 (defsubst ebnf-shape-value
(sym alist
)
4900 (or (cdr (assq sym alist
)) 0))
4903 (defsubst ebnf-boolean
(value)
4904 (if value
"true" "false"))
4907 (defun ebnf-begin-file ()
4910 (set-buffer ps-spool-buffer
)
4911 (goto-char (point-min))
4912 (and (search-forward "%%Creator: " nil t
)
4913 (not (search-forward "& ebnf2ps v"
4914 (save-excursion (end-of-line) (point))
4917 ;; adjust creator comment
4919 (insert " & ebnf2ps v" ebnf-version
)
4920 ;; insert ebnf settings & engine
4921 (goto-char (point-max))
4922 (search-backward "\n%%EndProlog\n")
4923 (ebnf-insert-ebnf-prologue)
4924 (ps-output "\n")))))
4927 (defun ebnf-eps-finish-and-write (buffer filename
)
4928 (when (buffer-modified-p buffer
)
4931 (setq ebnf-eps-upper-x
(max ebnf-eps-upper-x ebnf-eps-max-width
)
4932 ebnf-eps-upper-y
(if (zerop ebnf-eps-upper-y
)
4935 ebnf-production-vertical-space
4936 ebnf-eps-max-height
)))
4938 (goto-char (point-min))
4940 "%!PS-Adobe-3.0 EPSF-3.0"
4941 "\n%%BoundingBox: 0 0 "
4942 (format "%d %d" (1+ ebnf-eps-upper-x
) (1+ ebnf-eps-upper-y
))
4943 "\n%%Title: " filename
4944 "\n%%CreationDate: " (format-time-string "%T %b %d %Y")
4945 "\n%%Creator: " (user-full-name) " (using ebnf2ps v" ebnf-version
")"
4946 "\n%%DocumentNeededResources: font "
4947 (or ebnf-fonts-required
4948 (setq ebnf-fonts-required
4949 (mapconcat 'identity
4950 (ps-remove-duplicates
4951 (mapcar 'ebnf-font-name-select
4952 (list ebnf-production-font
4954 ebnf-non-terminal-font
4959 "\n%%Pages: 0\n%%EndComments\n\n%%BeginProlog\n"
4961 (ebnf-insert-ebnf-prologue)
4962 (insert ebnf-eps-begin
4963 "\n0 " (ebnf-format-float
4964 (- ebnf-eps-upper-y
(* ebnf-font-height-P
0.7)))
4965 " #ebnf2ps#begin\n")
4967 (goto-char (point-max))
4968 (insert ebnf-eps-end
)
4970 (message "Saving...")
4971 (setq filename
(expand-file-name filename
))
4972 (let ((coding-system-for-write 'raw-text-unix
))
4973 (write-region (point-min) (point-max) filename
))
4974 (message "Wrote %s" filename
))))
4977 (defun ebnf-insert-ebnf-prologue ()
4982 "\n\n% === begin EBNF settings\n\n"
4984 (format "/fP %s /%s DefFont\n"
4985 (ebnf-format-float (ebnf-font-size ebnf-production-font
))
4986 (ebnf-font-name-select ebnf-production-font
))
4987 (ebnf-format-color "/ForegroundP %s def %% %s\n"
4988 (ebnf-font-foreground ebnf-production-font
)
4990 (ebnf-format-color "/BackgroundP %s def %% %s\n"
4991 (ebnf-font-background ebnf-production-font
)
4993 (format "/EffectP %d def\n"
4994 (ebnf-font-attributes ebnf-production-font
))
4996 (format "/fT %s /%s DefFont\n"
4997 (ebnf-format-float (ebnf-font-size ebnf-terminal-font
))
4998 (ebnf-font-name-select ebnf-terminal-font
))
4999 (ebnf-format-color "/ForegroundT %s def %% %s\n"
5000 (ebnf-font-foreground ebnf-terminal-font
)
5002 (ebnf-format-color "/BackgroundT %s def %% %s\n"
5003 (ebnf-font-background ebnf-terminal-font
)
5005 (format "/EffectT %d def\n"
5006 (ebnf-font-attributes ebnf-terminal-font
))
5007 (format "/BorderWidthT %s def\n"
5008 (ebnf-format-float ebnf-terminal-border-width
))
5009 (ebnf-format-color "/BorderColorT %s def %% %s\n"
5010 ebnf-terminal-border-color
5012 (format "/ShapeT %d def\n"
5013 (ebnf-shape-value ebnf-terminal-shape
5014 ebnf-terminal-shape-alist
))
5015 (format "/ShadowT %s def\n"
5016 (ebnf-boolean ebnf-terminal-shadow
))
5018 (format "/fNT %s /%s DefFont\n"
5020 (ebnf-font-size ebnf-non-terminal-font
))
5021 (ebnf-font-name-select ebnf-non-terminal-font
))
5022 (ebnf-format-color "/ForegroundNT %s def %% %s\n"
5023 (ebnf-font-foreground ebnf-non-terminal-font
)
5025 (ebnf-format-color "/BackgroundNT %s def %% %s\n"
5026 (ebnf-font-background ebnf-non-terminal-font
)
5028 (format "/EffectNT %d def\n"
5029 (ebnf-font-attributes ebnf-non-terminal-font
))
5030 (format "/BorderWidthNT %s def\n"
5031 (ebnf-format-float ebnf-non-terminal-border-width
))
5032 (ebnf-format-color "/BorderColorNT %s def %% %s\n"
5033 ebnf-non-terminal-border-color
5035 (format "/ShapeNT %d def\n"
5036 (ebnf-shape-value ebnf-non-terminal-shape
5037 ebnf-terminal-shape-alist
))
5038 (format "/ShadowNT %s def\n"
5039 (ebnf-boolean ebnf-non-terminal-shadow
))
5041 (format "/fS %s /%s DefFont\n"
5042 (ebnf-format-float (ebnf-font-size ebnf-special-font
))
5043 (ebnf-font-name-select ebnf-special-font
))
5044 (ebnf-format-color "/ForegroundS %s def %% %s\n"
5045 (ebnf-font-foreground ebnf-special-font
)
5047 (ebnf-format-color "/BackgroundS %s def %% %s\n"
5048 (ebnf-font-background ebnf-special-font
)
5050 (format "/EffectS %d def\n"
5051 (ebnf-font-attributes ebnf-special-font
))
5052 (format "/BorderWidthS %s def\n"
5053 (ebnf-format-float ebnf-special-border-width
))
5054 (ebnf-format-color "/BorderColorS %s def %% %s\n"
5055 ebnf-special-border-color
5057 (format "/ShapeS %d def\n"
5058 (ebnf-shape-value ebnf-special-shape
5059 ebnf-terminal-shape-alist
))
5060 (format "/ShadowS %s def\n"
5061 (ebnf-boolean ebnf-special-shadow
))
5063 (format "/fE %s /%s DefFont\n"
5064 (ebnf-format-float (ebnf-font-size ebnf-except-font
))
5065 (ebnf-font-name-select ebnf-except-font
))
5066 (ebnf-format-color "/ForegroundE %s def %% %s\n"
5067 (ebnf-font-foreground ebnf-except-font
)
5069 (ebnf-format-color "/BackgroundE %s def %% %s\n"
5070 (ebnf-font-background ebnf-except-font
)
5072 (format "/EffectE %d def\n"
5073 (ebnf-font-attributes ebnf-except-font
))
5074 (format "/BorderWidthE %s def\n"
5075 (ebnf-format-float ebnf-except-border-width
))
5076 (ebnf-format-color "/BorderColorE %s def %% %s\n"
5077 ebnf-except-border-color
5079 (format "/ShapeE %d def\n"
5080 (ebnf-shape-value ebnf-except-shape
5081 ebnf-terminal-shape-alist
))
5082 (format "/ShadowE %s def\n"
5083 (ebnf-boolean ebnf-except-shadow
))
5085 (format "/fR %s /%s DefFont\n"
5086 (ebnf-format-float (ebnf-font-size ebnf-repeat-font
))
5087 (ebnf-font-name-select ebnf-repeat-font
))
5088 (ebnf-format-color "/ForegroundR %s def %% %s\n"
5089 (ebnf-font-foreground ebnf-repeat-font
)
5091 (ebnf-format-color "/BackgroundR %s def %% %s\n"
5092 (ebnf-font-background ebnf-repeat-font
)
5094 (format "/EffectR %d def\n"
5095 (ebnf-font-attributes ebnf-repeat-font
))
5096 (format "/BorderWidthR %s def\n"
5097 (ebnf-format-float ebnf-repeat-border-width
))
5098 (ebnf-format-color "/BorderColorR %s def %% %s\n"
5099 ebnf-repeat-border-color
5101 (format "/ShapeR %d def\n"
5102 (ebnf-shape-value ebnf-repeat-shape
5103 ebnf-terminal-shape-alist
))
5104 (format "/ShadowR %s def\n"
5105 (ebnf-boolean ebnf-repeat-shadow
))
5107 (format "/ExtraWidth %s def\n"
5108 (ebnf-format-float ebnf-arrow-extra-width
))
5109 (format "/ArrowScale %s def\n"
5110 (ebnf-format-float ebnf-arrow-scale
))
5111 (format "/DefaultWidth %s def\n"
5112 (ebnf-format-float ebnf-default-width
))
5113 (format "/LineWidth %s def\n"
5114 (ebnf-format-float ebnf-line-width
))
5115 (ebnf-format-color "/LineColor %s def %% %s\n"
5118 (format "/ArrowShape %d def\n"
5119 (ebnf-shape-value ebnf-arrow-shape
5120 ebnf-arrow-shape-alist
))
5121 (format "/ChartShape %d def\n"
5122 (ebnf-shape-value ebnf-chart-shape
5123 ebnf-terminal-shape-alist
))
5124 (format "/UserArrow{%s}def\n"
5125 (let ((arrow (eval ebnf-user-arrow
)))
5129 "\n% === end EBNF settings\n\n"
5130 (and ebnf-debug-ps ebnf-debug
))))
5134 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5135 ;; Adjusting dimensions
5138 (defun ebnf-dimensions (tree)
5139 (let ((ebnf-total (length tree
))
5141 (mapcar 'ebnf-production-dimension tree
))
5145 ;; [empty width-fun dim-fun entry height width]
5146 ;;(defun ebnf-empty-dimension (empty)
5150 ;; [production width-fun dim-fun entry height width name production action]
5151 (defun ebnf-production-dimension (production)
5152 (ebnf-message-info "Calculating dimensions")
5153 (ebnf-node-dimension-func (ebnf-node-production production
))
5154 (let* ((prod (ebnf-node-production production
))
5155 (height (+ (if ebnf-production-name-p
5158 ebnf-line-width ebnf-line-width
5160 (ebnf-node-height prod
))))
5161 (ebnf-node-entry production height
)
5162 (ebnf-node-height production height
)
5163 (ebnf-node-width production
(+ (ebnf-node-width prod
)
5165 ebnf-horizontal-space
))))
5168 ;; [terminal width-fun dim-fun entry height width name]
5169 (defun ebnf-terminal-dimension (terminal)
5170 (ebnf-terminal-dimension1 terminal
5176 ;; [non-terminal width-fun dim-fun entry height width name]
5177 (defun ebnf-non-terminal-dimension (non-terminal)
5178 (ebnf-terminal-dimension1 non-terminal
5184 ;; [special width-fun dim-fun entry height width name]
5185 (defun ebnf-special-dimension (special)
5186 (ebnf-terminal-dimension1 special
5192 (defun ebnf-terminal-dimension1 (node font-height font-width space
)
5193 (let ((height (+ space font-height space
))
5194 (len (length (ebnf-node-name node
))))
5195 (ebnf-node-entry node
(* height
0.5))
5196 (ebnf-node-height node height
)
5197 (ebnf-node-width node
(+ ebnf-basic-width ebnf-arrow-extra-width space
5199 space ebnf-basic-width
))))
5202 (defconst ebnf-null-vector
(vector t t t
0.0 0.0 0.0))
5205 ;; [repeat width-fun dim-fun entry height width times element]
5206 (defun ebnf-repeat-dimension (repeat)
5207 (let ((times (ebnf-node-name repeat
))
5208 (element (ebnf-node-separator repeat
)))
5210 (ebnf-node-dimension-func element
)
5211 (setq element ebnf-null-vector
))
5212 (ebnf-node-entry repeat
(+ (ebnf-node-entry element
)
5214 (ebnf-node-height repeat
(+ (max (ebnf-node-height element
)
5216 ebnf-space-R ebnf-space-R
))
5217 (ebnf-node-width repeat
(+ (ebnf-node-width element
)
5218 ebnf-arrow-extra-width
5219 ebnf-space-R ebnf-space-R ebnf-space-R
5220 ebnf-horizontal-space
5221 (* (length times
) ebnf-font-width-R
)))))
5224 ;; [except width-fun dim-fun entry height width element element]
5225 (defun ebnf-except-dimension (except)
5226 (let ((factor (ebnf-node-list except
))
5227 (element (ebnf-node-separator except
)))
5228 (ebnf-node-dimension-func factor
)
5230 (ebnf-node-dimension-func element
)
5231 (setq element ebnf-null-vector
))
5232 (ebnf-node-entry except
(+ (max (ebnf-node-entry factor
)
5233 (ebnf-node-entry element
))
5235 (ebnf-node-height except
(+ (max (ebnf-node-height factor
)
5236 (ebnf-node-height element
))
5237 ebnf-space-E ebnf-space-E
))
5238 (ebnf-node-width except
(+ (ebnf-node-width factor
)
5239 (ebnf-node-width element
)
5240 ebnf-arrow-extra-width
5241 ebnf-space-E ebnf-space-E
5242 ebnf-space-E ebnf-space-E
5244 ebnf-horizontal-space
))))
5247 ;; [alternative width-fun dim-fun entry height width list]
5248 (defun ebnf-alternative-dimension (alternative)
5249 (let ((body (ebnf-node-list alternative
))
5250 (lis (ebnf-node-list alternative
)))
5252 (ebnf-node-dimension-func (car lis
))
5253 (setq lis
(cdr lis
)))
5257 (tail (car (last body
)))
5258 (entry (ebnf-node-entry (car body
)))
5261 (setq node
(car alt
)
5263 height
(+ (ebnf-node-height node
) height
)
5264 width
(max (ebnf-node-width node
) width
)))
5265 (ebnf-adjust-width body width
)
5266 (setq height
(+ height
(* (1- (length body
)) ebnf-vertical-space
)))
5267 (ebnf-node-entry alternative
(+ entry
5270 (- (ebnf-node-height tail
)
5271 (ebnf-node-entry tail
))))))
5272 (ebnf-node-height alternative height
)
5273 (ebnf-node-width alternative
(+ width ebnf-horizontal-space
))
5274 (ebnf-node-list alternative body
))))
5277 ;; [optional width-fun dim-fun entry height width element]
5278 (defun ebnf-optional-dimension (optional)
5279 (let ((body (ebnf-node-list optional
)))
5280 (ebnf-node-dimension-func body
)
5281 (ebnf-node-entry optional
(ebnf-node-entry body
))
5282 (ebnf-node-height optional
(+ (ebnf-node-height body
)
5283 ebnf-vertical-space
))
5284 (ebnf-node-width optional
(+ (ebnf-node-width body
)
5285 ebnf-horizontal-space
))))
5288 ;; [one-or-more width-fun dim-fun entry height width element separator]
5289 (defun ebnf-one-or-more-dimension (or-more)
5290 (let ((list-part (ebnf-node-list or-more
))
5291 (sep-part (ebnf-node-separator or-more
)))
5292 (ebnf-node-dimension-func list-part
)
5294 (ebnf-node-dimension-func sep-part
))
5295 (let ((height (+ (if sep-part
5296 (ebnf-node-height sep-part
)
5299 (ebnf-node-height list-part
)))
5300 (width (max (if sep-part
5301 (ebnf-node-width sep-part
)
5303 (ebnf-node-width list-part
))))
5305 (ebnf-adjust-width list-part width
)
5306 (ebnf-adjust-width sep-part width
))
5307 (ebnf-node-entry or-more
(+ (- height
(ebnf-node-height list-part
))
5308 (ebnf-node-entry list-part
)))
5309 (ebnf-node-height or-more height
)
5310 (ebnf-node-width or-more
(+ width ebnf-horizontal-space
)))))
5313 ;; [zero-or-more width-fun dim-fun entry height width element separator]
5314 (defun ebnf-zero-or-more-dimension (or-more)
5315 (let ((list-part (ebnf-node-list or-more
))
5316 (sep-part (ebnf-node-separator or-more
)))
5317 (ebnf-node-dimension-func list-part
)
5319 (ebnf-node-dimension-func sep-part
))
5320 (let ((height (+ (if sep-part
5321 (ebnf-node-height sep-part
)
5324 (ebnf-node-height list-part
)
5325 ebnf-vertical-space
))
5326 (width (max (if sep-part
5327 (ebnf-node-width sep-part
)
5329 (ebnf-node-width list-part
))))
5331 (ebnf-adjust-width list-part width
)
5332 (ebnf-adjust-width sep-part width
))
5333 (ebnf-node-entry or-more height
)
5334 (ebnf-node-height or-more height
)
5335 (ebnf-node-width or-more
(+ width ebnf-horizontal-space
)))))
5338 ;; [sequence width-fun dim-fun entry height width list]
5339 (defun ebnf-sequence-dimension (sequence)
5343 (lis (ebnf-node-list sequence
))
5346 (setq node
(car lis
)
5348 (ebnf-node-dimension-func node
)
5349 (setq entry
(ebnf-node-entry node
)
5350 above
(max above entry
)
5351 below
(max below
(- (ebnf-node-height node
) entry
))
5352 width
(+ width
(ebnf-node-width node
))))
5353 (ebnf-node-entry sequence above
)
5354 (ebnf-node-height sequence
(+ above below
))
5355 (ebnf-node-width sequence width
)))
5358 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5362 (defun ebnf-adjust-width (node width
)
5368 (setcar node
(ebnf-adjust-width (car node
) width
))
5369 (setq node
(cdr node
)))))
5372 ;; nothing to be done
5373 ((= width
(ebnf-node-width node
))
5375 ;; left justify term
5376 ((eq ebnf-justify-sequence
'left
)
5377 (ebnf-adjust-empty node width nil
))
5378 ;; right justify terms
5379 ((eq ebnf-justify-sequence
'right
)
5380 (ebnf-adjust-empty node width t
))
5383 (ebnf-node-width-func node width
)
5384 (ebnf-node-width node width
)
5392 (defun ebnf-adjust-empty (node width last-p
)
5393 (if (eq (ebnf-node-kind node
) 'ebnf-generate-empty
)
5395 (ebnf-node-width node width
)
5397 (let ((empty (ebnf-make-empty (- width
(ebnf-node-width node
)))))
5398 (ebnf-make-dup-sequence node
5401 (list node empty
))))))
5404 ;; [terminal width-fun dim-fun entry height width name]
5405 ;; [non-terminal width-fun dim-fun entry height width name]
5406 ;; [empty width-fun dim-fun entry height width]
5407 ;; [special width-fun dim-fun entry height width name]
5408 ;; [repeat width-fun dim-fun entry height width times element]
5409 ;; [except width-fun dim-fun entry height width element element]
5410 ;;(defun ebnf-terminal-width (terminal width)
5414 ;; [alternative width-fun dim-fun entry height width list]
5415 ;; [optional width-fun dim-fun entry height width element]
5416 (defun ebnf-alternative-width (alternative width
)
5417 (ebnf-adjust-width (ebnf-node-list alternative
)
5418 (- width ebnf-horizontal-space
)))
5421 ;; [one-or-more width-fun dim-fun entry height width element separator]
5422 ;; [zero-or-more width-fun dim-fun entry height width element separator]
5423 (defun ebnf-element-width (or-more width
)
5424 (setq width
(- width ebnf-horizontal-space
))
5425 (ebnf-node-list or-more
5426 (ebnf-justify-list or-more
5427 (ebnf-node-list or-more
)
5429 (ebnf-node-separator or-more
5430 (ebnf-justify-list or-more
5431 (ebnf-node-separator or-more
)
5435 ;; [sequence width-fun dim-fun entry height width list]
5436 (defun ebnf-sequence-width (sequence width
)
5437 (ebnf-node-list sequence
5438 (ebnf-justify-list sequence
5439 (ebnf-node-list sequence
)
5443 (defun ebnf-justify-list (node seq width
)
5444 (let ((seq-width (ebnf-node-width node
)))
5445 (if (= width seq-width
)
5448 ;; left justify terms
5449 ((eq ebnf-justify-sequence
'left
)
5450 (ebnf-justify node seq seq-width width t
))
5451 ;; right justify terms
5452 ((eq ebnf-justify-sequence
'right
)
5453 (ebnf-justify node seq seq-width width nil
))
5454 ;; centralize terms -- element
5456 (ebnf-adjust-width seq width
))
5457 ;; centralize terms -- list
5459 (let ((the-width (/ (- width seq-width
) (length seq
)))
5462 (ebnf-adjust-width (car lis
)
5463 (+ (ebnf-node-width (car lis
))
5465 (setq lis
(cdr lis
)))
5470 (defun ebnf-justify (node seq seq-width width last-p
)
5471 (let ((term (car (if last-p
(last seq
) seq
))))
5473 ;; adjust empty term
5474 ((eq (ebnf-node-kind term
) 'ebnf-generate-empty
)
5475 (ebnf-node-width term
(+ (- width seq-width
)
5476 (ebnf-node-width term
)))
5478 ;; insert empty at end ==> left justify
5481 (list (ebnf-make-empty (- width seq-width
)))))
5482 ;; insert empty at beginning ==> right justify
5484 (cons (ebnf-make-empty (- width seq-width
))
5489 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5490 ;; Functions used by parsers
5493 (defun ebnf-eps-add-context (name)
5494 (let ((filename (ebnf-eps-filename name
)))
5495 (if (member filename ebnf-eps-context
)
5496 (error "Try to open an already opened EPS file: %s" filename
)
5497 (setq ebnf-eps-context
(cons filename ebnf-eps-context
)))))
5500 (defun ebnf-eps-remove-context (name)
5501 (let ((filename (ebnf-eps-filename name
)))
5502 (if (member filename ebnf-eps-context
)
5503 (setq ebnf-eps-context
(delete filename ebnf-eps-context
))
5504 (error "Try to close a not opened EPS file: %s" filename
))))
5507 (defun ebnf-eps-add-production (header)
5508 (and ebnf-eps-executing
5510 (let ((prod (assoc header ebnf-eps-production-list
)))
5512 (setcdr prod
(append ebnf-eps-context
(cdr prod
)))
5513 (setq ebnf-eps-production-list
5514 (cons (cons header
(ebnf-dup-list ebnf-eps-context
))
5515 ebnf-eps-production-list
))))))
5518 (defun ebnf-dup-list (old)
5521 (setq new
(cons (car old
) new
)
5526 (defun ebnf-buffer-substring (chars)
5527 (buffer-substring-no-properties
5530 (skip-chars-forward chars ebnf-limit
)
5534 ;; replace the range "\240-\377" (see `ebnf-range-regexp').
5535 (defconst ebnf-8-bit-chars
(ebnf-range-regexp "" ?
\240 ?
\377))
5538 (defun ebnf-string (chars eos-char kind
)
5540 (buffer-substring-no-properties
5543 ;;(skip-chars-forward (concat chars "\240-\377") ebnf-limit)
5544 (skip-chars-forward (concat chars ebnf-8-bit-chars
) ebnf-limit
)
5545 (if (or (eobp) (/= (following-char) eos-char
))
5546 (error "Invalid %s: missing `%c'" kind eos-char
)
5551 (defun ebnf-get-string ()
5553 (buffer-substring-no-properties (point) (ebnf-end-of-string)))
5556 (defun ebnf-end-of-string ()
5558 (while (> (logand n
1) 0)
5559 (skip-chars-forward "^\"" ebnf-limit
)
5560 (setq n
(- (skip-chars-backward "\\\\")))
5561 (goto-char (+ (point) n
1))))
5562 (if (= (preceding-char) ?
\")
5564 (error "Missing `\"'")))
5567 (defun ebnf-trim-right (str)
5568 (let* ((len (1- (length str
)))
5570 (while (and (> index
0) (= (aref str index
) ?\s
))
5571 (setq index
(1- index
)))
5574 (substring str
0 (1+ index
)))))
5577 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5581 (defun ebnf-make-empty (&optional width
)
5582 (vector 'ebnf-generate-empty
5587 (or width ebnf-horizontal-space
)))
5590 (defun ebnf-make-terminal (name)
5591 (ebnf-make-terminal1 name
5592 'ebnf-generate-terminal
5593 'ebnf-terminal-dimension
))
5596 (defun ebnf-make-non-terminal (name)
5597 (ebnf-make-terminal1 name
5598 'ebnf-generate-non-terminal
5599 'ebnf-non-terminal-dimension
))
5602 (defun ebnf-make-special (name)
5603 (ebnf-make-terminal1 name
5604 'ebnf-generate-special
5605 'ebnf-special-dimension
))
5608 (defun ebnf-make-terminal1 (name gen-func dim-func
)
5615 (let ((len (length name
)))
5616 (cond ((> len
3) name
)
5617 ((= len
3) (concat name
" "))
5618 ((= len
2) (concat " " name
" "))
5619 ((= len
1) (concat " " name
" "))
5624 (defun ebnf-make-one-or-more (list-part &optional sep-part
)
5625 (ebnf-make-or-more1 'ebnf-generate-one-or-more
5626 'ebnf-one-or-more-dimension
5631 (defun ebnf-make-zero-or-more (list-part &optional sep-part
)
5632 (ebnf-make-or-more1 'ebnf-generate-zero-or-more
5633 'ebnf-zero-or-more-dimension
5638 (defun ebnf-make-or-more1 (gen-func dim-func list-part sep-part
)
5645 (if (listp list-part
)
5646 (ebnf-make-sequence list-part
)
5648 (if (and sep-part
(listp sep-part
))
5649 (ebnf-make-sequence sep-part
)
5653 (defun ebnf-make-production (name prod action
)
5654 (vector 'ebnf-generate-production
5656 'ebnf-production-dimension
5665 (defun ebnf-make-alternative (body)
5666 (vector 'ebnf-generate-alternative
5667 'ebnf-alternative-width
5668 'ebnf-alternative-dimension
5675 (defun ebnf-make-optional (body)
5676 (vector 'ebnf-generate-optional
5677 'ebnf-alternative-width
5678 'ebnf-optional-dimension
5685 (defun ebnf-make-except (factor exception
)
5686 (vector 'ebnf-generate-except
5688 'ebnf-except-dimension
5696 (defun ebnf-make-repeat (times primary
&optional upper
)
5697 (vector 'ebnf-generate-repeat
5699 'ebnf-repeat-dimension
5703 (cond ((and times upper
) ; L * U, L * L
5704 (if (string= times upper
)
5705 (if (string= times
"")
5708 (concat times
" * " upper
)))
5710 (concat times
" *"))
5712 (concat "* " upper
))
5718 (defun ebnf-make-sequence (seq)
5719 (vector 'ebnf-generate-sequence
5720 'ebnf-sequence-width
5721 'ebnf-sequence-dimension
5728 (defun ebnf-make-dup-sequence (node seq
)
5729 (vector 'ebnf-generate-sequence
5730 'ebnf-sequence-width
5731 'ebnf-sequence-dimension
5732 (ebnf-node-entry node
)
5733 (ebnf-node-height node
)
5734 (ebnf-node-width node
)
5738 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5739 ;; Optimizers used by parsers
5742 (defun ebnf-token-except (element exception
)
5745 (setq exception
(cdr exception
)))
5746 (and element
; EMPTY - A ==> EMPTY
5747 (let ((kind (ebnf-node-kind element
)))
5750 ((and (null exception
)
5751 (eq kind
'ebnf-generate-optional
))
5752 (ebnf-node-list element
))
5753 ;; { A }- ==> { A }+
5754 ((and (null exception
)
5755 (eq kind
'ebnf-generate-zero-or-more
))
5756 (ebnf-node-kind element
'ebnf-generate-one-or-more
)
5757 (ebnf-node-dimension-func element
'ebnf-one-or-more-dimension
)
5759 ;; ( A | EMPTY )- ==> A
5760 ;; ( A | B | EMPTY )- ==> A | B
5761 ((and (null exception
)
5762 (eq kind
'ebnf-generate-alternative
)
5764 (car (last (ebnf-node-list element
))))
5765 'ebnf-generate-empty
))
5766 (let ((elt (ebnf-node-list element
))
5772 ;; this should not happen!!?!
5773 (setq element
(ebnf-make-empty
5774 (ebnf-node-width element
)))
5776 (setq elt
(ebnf-node-list element
))
5777 (and (= (length elt
) 1)
5778 (setq element
(car elt
))))
5782 (ebnf-make-except element exception
))
5786 (defun ebnf-token-repeat (times repeat
&optional upper
)
5787 (if (null (cdr repeat
))
5788 ;; n * EMPTY ==> EMPTY
5792 (ebnf-make-repeat times
(cdr repeat
) upper
))))
5795 (defun ebnf-token-optional (body)
5796 (let ((kind (ebnf-node-kind body
)))
5798 ;; [ EMPTY ] ==> EMPTY
5799 ((eq kind
'ebnf-generate-empty
)
5801 ;; [ { A }* ] ==> { A }*
5802 ((eq kind
'ebnf-generate-zero-or-more
)
5804 ;; [ { A }+ ] ==> { A }*
5805 ((eq kind
'ebnf-generate-one-or-more
)
5806 (ebnf-node-kind body
'ebnf-generate-zero-or-more
)
5808 ;; [ A | B ] ==> A | B | EMPTY
5809 ((eq kind
'ebnf-generate-alternative
)
5810 (ebnf-node-list body
(nconc (ebnf-node-list body
)
5811 (list (ebnf-make-empty))))
5815 (ebnf-make-optional body
))
5819 (defun ebnf-token-alternative (body sequence
)
5823 (cons (car sequence
)
5825 (cons (car sequence
)
5826 (let ((seq (cdr sequence
)))
5827 (if (and (= (length body
) 1) (null seq
))
5829 (ebnf-make-alternative (nreverse (if seq
5834 (defun ebnf-token-sequence (sequence)
5839 ;; sequence with only one element
5840 ((= (length sequence
) 1)
5844 (ebnf-make-sequence (nreverse sequence
)))
5848 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5849 ;; Variables used by parsers
5852 (defconst ebnf-comment-table
5853 (let ((table (make-vector 256 nil
)))
5854 ;; Override special comment character:
5855 (aset table ?
< 'newline
)
5856 (aset table ?
> 'keep-line
)
5857 (aset table ?^
'form-feed
)
5859 "Vector used to map characters to a special comment token.")
5862 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5863 ;; To make this file smaller, some commands go in a separate file.
5864 ;; But autoload them here to make the separation invisible.
5866 (autoload 'ebnf-abn-parser
"ebnf-abn"
5869 (autoload 'ebnf-abn-initialize
"ebnf-abn"
5870 "Initialize ABNF token table.")
5872 (autoload 'ebnf-bnf-parser
"ebnf-bnf"
5875 (autoload 'ebnf-bnf-initialize
"ebnf-bnf"
5876 "Initialize EBNF token table.")
5878 (autoload 'ebnf-iso-parser
"ebnf-iso"
5881 (autoload 'ebnf-iso-initialize
"ebnf-iso"
5882 "Initialize ISO EBNF token table.")
5884 (autoload 'ebnf-yac-parser
"ebnf-yac"
5885 "Yacc/Bison parser.")
5887 (autoload 'ebnf-yac-initialize
"ebnf-yac"
5888 "Initializations for Yacc/Bison parser.")
5890 (autoload 'ebnf-ebx-parser
"ebnf-ebx"
5893 (autoload 'ebnf-ebx-initialize
"ebnf-ebx"
5894 "Initializations for EBNFX parser.")
5896 (autoload 'ebnf-dtd-parser
"ebnf-dtd"
5899 (autoload 'ebnf-dtd-initialize
"ebnf-dtd"
5900 "Initializations for DTD parser.")
5903 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5908 ;;; arch-tag: 148bc8af-5398-468b-b922-eeb7afef3e4f
5909 ;;; ebnf2ps.el ends here