1 ;;; ebnf2ps.el --- translate an EBNF to a syntatic chart on PostScript
3 ;; Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
5 ;; Author: Vinicius Jose Latorre <vinicius@cpqd.com.br>
6 ;; Maintainer: Vinicius Jose Latorre <vinicius@cpqd.com.br>
7 ;; Keywords: wp, ebnf, PostScript
8 ;; Time-stamp: <2001/09/24 10:31:13 vinicius>
10 ;; X-URL: http://www.cpqd.com.br/~vinicius/emacs/
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 2, 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., 59 Temple Place - Suite 330,
27 ;; Boston, MA 02111-1307, USA.
29 (defconst ebnf-version
"3.6.1"
30 "ebnf2ps.el, v 3.6.1 <2001/09/24 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 <vinicius@cpqd.com.br>.
42 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
47 ;; This package translates an EBNF to a syntatic 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 six commands for generating PostScript syntatic chart
73 ;; images of Emacs buffers:
82 ;; These commands all perform essentially the same function: they generate
83 ;; PostScript syntatic chart images suitable for printing on a PostScript
84 ;; printer or displaying with GhostScript. These commands are collectively
85 ;; referred to as "ebnf- commands".
87 ;; The word "print", "spool" and "eps" in the command name determines when the
88 ;; PostScript image is sent to the printer (or file):
90 ;; print - The PostScript image is immediately sent to the printer;
92 ;; spool - The PostScript image is saved temporarily in an Emacs buffer.
93 ;; Many images may be spooled locally before printing them. To
94 ;; send the spooled images to the printer, use the command
97 ;; eps - The PostScript image is immediately sent to a EPS file.
99 ;; The spooling mechanism is the same as used by ps-print and was designed for
100 ;; printing lots of small files to save paper that would otherwise be wasted on
101 ;; banner pages, and to make it easier to find your output at the printer (it's
102 ;; easier to pick up one 50-page printout than to find 50 single-page
103 ;; printouts). As ebnf2ps and ps-print use the same Emacs buffer to spool
104 ;; images, you can intermix the spooling of ebnf2ps and ps-print images.
106 ;; ebnf2ps use the same hook of ps-print in the `kill-emacs-hook' so that you
107 ;; won't accidentally quit from Emacs while you have unprinted PostScript
108 ;; waiting in the spool buffer. If you do attempt to exit with spooled
109 ;; PostScript, you'll be asked if you want to print it, and if you decline,
110 ;; you'll be asked to confirm the exit; this is modeled on the confirmation
111 ;; that Emacs uses for modified buffers.
113 ;; The word "buffer" or "region" in the command name determines how much of the
114 ;; buffer is printed:
116 ;; buffer - Print the entire buffer.
118 ;; region - Print just the current region.
120 ;; Two ebnf- command examples:
122 ;; ebnf-print-buffer - translate and print the entire buffer, and send it
123 ;; immediately to the printer.
125 ;; ebnf-spool-region - translate and print just the current region, and
126 ;; spool the image in Emacs to send to the printer
129 ;; Note that `ebnf-eps-buffer' and `ebnf-eps-region' never spool the EPS image,
130 ;; so they don't use the ps-print spooling mechanism. See section "Actions in
131 ;; Comments" for an explanation about EPS file generation.
137 ;; To translate and print your buffer, type
139 ;; M-x ebnf-print-buffer
141 ;; or substitute one of the other four ebnf- commands. The command will
142 ;; generate the PostScript image and print or spool it as specified. By giving
143 ;; the command a prefix argument
145 ;; C-u M-x ebnf-print-buffer
147 ;; it will save the PostScript image to a file instead of sending it to the
148 ;; printer; you will be prompted for the name of the file to save the image to.
149 ;; The prefix argument is ignored by the commands that spool their images, but
150 ;; you may save the spooled images to a file by giving a prefix argument to
153 ;; C-u M-x ebnf-despool
155 ;; When invoked this way, `ebnf-despool' will prompt you for the name of the
158 ;; The prefix argument is also ignored by `ebnf-eps-buffer' and
159 ;; `ebnf-eps-region'.
161 ;; Any of the `ebnf-' commands can be bound to keys. Here are some examples:
163 ;; (global-set-key 'f22 'ebnf-print-buffer) ;f22 is prsc
164 ;; (global-set-key '(shift f22) 'ebnf-print-region)
165 ;; (global-set-key '(control f22) 'ebnf-despool)
171 ;; The current EBNF that ebnf2ps accepts has the following constructions:
173 ;; ; comment (until end of line)
177 ;; $A default non-terminal (see text below)
178 ;; $"C" default terminal (see text below)
179 ;; $?C? default special (see text below)
180 ;; A = B. production (A is the header and B the body)
181 ;; C D sequence (C occurs before D)
182 ;; C | D alternative (C or D occurs)
183 ;; A - B exception (A excluding B, B without any non-terminal)
184 ;; n * A repetition (A repeats n (integer) times)
185 ;; (C) group (expression C is grouped together)
186 ;; [C] optional (C may or not occurs)
187 ;; C+ one or more occurrences of C
188 ;; {C}+ one or more occurrences of C
189 ;; {C}* zero or more occurrences of C
190 ;; {C} zero or more occurrences of C
191 ;; C / D equivalent to: C {D C}*
192 ;; {C || D}+ equivalent to: C {D C}*
193 ;; {C || D}* equivalent to: [C {D C}*]
194 ;; {C || D} equivalent to: [C {D C}*]
196 ;; The EBNF syntax written using the notation above is:
198 ;; EBNF = {production}+.
200 ;; production = non_terminal "=" body ".". ;; production
202 ;; body = {sequence || "|"}*. ;; alternative
204 ;; sequence = {exception}*. ;; sequence
206 ;; exception = repeat [ "-" repeat]. ;; exception
208 ;; repeat = [ integer "*" ] term. ;; repetition
211 ;; | [factor] "+" ;; one-or-more
212 ;; | [factor] "/" [factor] ;; one-or-more
215 ;; factor = [ "$" ] "\"" terminal "\"" ;; terminal
216 ;; | [ "$" ] non_terminal ;; non-terminal
217 ;; | [ "$" ] "?" special "?" ;; special
218 ;; | "(" body ")" ;; group
219 ;; | "[" body "]" ;; zero-or-one
220 ;; | "{" body [ "||" body ] "}+" ;; one-or-more
221 ;; | "{" body [ "||" body ] "}*" ;; zero-or-more
222 ;; | "{" body [ "||" body ] "}" ;; zero-or-more
225 ;; non_terminal = "[!#%&'*-,0-:<>@-Z\\\\^-z~\\240-\\377]+".
227 ;; terminal = "\\([^\"\\]\\|\\\\[ -~\\240-\\377]\\)+".
229 ;; special = "[^?\\n\\000-\\010\\016-\\037\\177-\\237]*".
231 ;; integer = "[0-9]+".
233 ;; comment = ";" "[^\\n\\000-\\010\\016-\\037\\177-\\237]*" "\\n".
235 ;; Try to use the above EBNF to test ebnf2ps.
237 ;; The `default' terminal, non-terminal and special is a way to indicate a
238 ;; default path in a production. For example, the production:
240 ;; X = [ $A ( B | $C ) | D ].
242 ;; Indicates that the default meaning for "X" is "A C" if "X" is empty.
244 ;; The terminal name is controlled by `ebnf-terminal-regexp' and
245 ;; `ebnf-case-fold-search', so it's possible to match other kind of terminal
246 ;; name besides that enclosed by `"'.
248 ;; Let's see an example:
250 ;; (setq ebnf-terminal-regexp "[A-Z][_A-Z]*") ; upper case name
251 ;; (setq ebnf-case-fold-search nil) ; exact matching
253 ;; If you have the production:
255 ;; Logical = "(" Expression ( OR | AND | "XOR" ) Expression ")".
257 ;; The names are classified as:
259 ;; Logical Expression non-terminal
260 ;; "(" OR AND "XOR" ")" terminal
262 ;; The line comment is controlled by `ebnf-lex-comment-char'. The default
263 ;; value is ?\; (character `;').
265 ;; The end of production is controlled by `ebnf-lex-eop-char'. The default
266 ;; value is ?. (character `.').
268 ;; The variable `ebnf-syntax' specifies which syntax to recognize:
270 ;; `ebnf' ebnf2ps recognizes the syntax described above.
271 ;; The following variables *ONLY* have effect with this
273 ;; `ebnf-terminal-regexp', `ebnf-case-fold-search',
274 ;; `ebnf-lex-comment-char' and `ebnf-lex-eop-char'.
276 ;; `iso-ebnf' ebnf2ps recognizes the syntax described in the URL:
277 ;; `http://www.cl.cam.ac.uk/~mgk25/iso-ebnf.html'
278 ;; ("International Standard of the ISO EBNF Notation").
279 ;; The following variables *ONLY* have effect with this
281 ;; `ebnf-iso-alternative-p' and `ebnf-iso-normalize-p'.
283 ;; `yacc' ebnf2ps recognizes the Yacc/Bison syntax.
284 ;; The following variable *ONLY* has effect with this
286 ;; `ebnf-yac-ignore-error-recovery'.
288 ;; Any other value is treated as `ebnf'.
290 ;; The default value is `ebnf'.
296 ;; The following EBNF optimizations are done:
298 ;; [ { A }* ] ==> { A }*
299 ;; [ { A }+ ] ==> { A }*
300 ;; [ A ] + ==> { A }*
301 ;; { A }* + ==> { A }*
302 ;; { A }+ + ==> { A }+
305 ;; ( A | EMPTY )- ==> A
306 ;; ( A | B | EMPTY )- ==> A | B
307 ;; [ A | B ] ==> A | B | EMPTY
308 ;; n * EMPTY ==> EMPTY
310 ;; EMPTY / EMPTY ==> EMPTY
311 ;; EMPTY - A ==> EMPTY
313 ;; The following optimizations are done when `ebnf-optimize' is non-nil:
316 ;; 1. A = B | A C. ==> A = B {C}*.
317 ;; 2. A = B | A B. ==> A = {B}+.
318 ;; 3. A = | A B. ==> A = {B}*.
319 ;; 4. A = B | A C B. ==> A = {B || C}+.
320 ;; 5. A = B | D | A C | A E. ==> A = ( B | D ) { C | E }*.
323 ;; 6. A = B | . ==> A = [B].
324 ;; 7. A = | B . ==> A = [B].
327 ;; 8. A = B C | B D. ==> A = B (C | D).
328 ;; 9. A = C B | D B. ==> A = (C | D) B.
329 ;; 10. A = B C E | B D E. ==> A = B (C | D) E.
331 ;; The above optimizations are specially useful when `ebnf-syntax' is `yacc'.
337 ;; You may use form feed (^L \014) to force a production to start on a new
338 ;; page, for example:
347 ;; c) A = B ^L^L^L | C.^L
351 ;; In all examples above, only the production X will start on a new page.
354 ;; Actions in Comments
355 ;; -------------------
357 ;; ebnf2ps accepts the following actions in comments:
359 ;; ;> the next production starts in the same line as the current one.
360 ;; It is useful when `ebnf-horizontal-orientation' is nil.
362 ;; ;< the next production starts in the next line.
363 ;; It is useful when `ebnf-horizontal-orientation' is non-nil.
365 ;; ;[EPS open a new EPS file. The EPS file name has the form:
366 ;; <PREFIX><NAME>.eps
367 ;; where <PREFIX> is given by variable `ebnf-eps-prefix' and
368 ;; <NAME> is the string given by ;[ action comment, this string is
369 ;; mapped to form a valid file name (see documentation for
370 ;; `ebnf-eps-buffer' or `ebnf-eps-region').
371 ;; It has effect only during `ebnf-eps-buffer' or
372 ;; `ebnf-eps-region' execution.
373 ;; It's an error to try to open an already opened EPS file.
375 ;; ;]EPS close an opened EPS file.
376 ;; It has effect only during `ebnf-eps-buffer' or
377 ;; `ebnf-eps-region' execution.
378 ;; It's an error to try to close a not opened EPS file.
382 ;; (setq ebnf-horizontal-orientation nil)
386 ;; ;> C and B are drawn in the same line
390 ;; The graphical result is:
396 ;; +---------+ +-----+
408 ;; Note that if ascending production sort is used, the productions A and B will
409 ;; be drawn in the same line instead of C and B.
411 ;; If consecutive actions occur, only the last one takes effect, so if you
420 ;; Only the ;> will take effect, that is, A and B will be drawn in the same
423 ;; In ISO EBNF the above actions are specified as (*>*), (*<*), (*[EPS*) and
424 ;; (*]EPS*). The first example above should be written:
428 ;; (*> C and B are drawn in the same line *)
432 ;; For an example of EPS action when executing `ebnf-eps-buffer' or
433 ;; `ebnf-eps-region':
452 ;; The following table summarizes the results:
454 ;; EPS FILE NAME NO SORT ASCENDING SORT DESCENDING SORT
455 ;; ebnf--AA.eps A C A C C A
456 ;; ebnf--BB.eps C B B C C B
457 ;; ebnf--CC.eps A C B F A B C F F C B A
463 ;; As you can see if EPS actions is not used, each single production is
464 ;; generated per EPS file. To avoid overriding EPS files, use names in ;[ that
465 ;; it's not an existing production name.
467 ;; In the following case:
475 ;; The production A is generated in both files ebnf--AA.eps and ebnf--BB.eps.
481 ;; Some tools are provided to help you.
483 ;; `ebnf-setup' returns the current setup.
485 ;; `ebnf-syntax-buffer' does a syntatic analysis of your EBNF in the current
488 ;; `ebnf-syntax-region' does a syntatic analysis of your EBNF in the current
491 ;; `ebnf-customize' activates a customization buffer for ebnf2ps options.
493 ;; `ebnf-syntax-buffer', `ebnf-syntax-region' and `ebnf-customize' can be bound
494 ;; to keys in the same way as `ebnf-' commands.
500 ;; ebn2ps has the following hook variables:
503 ;; It is evaluated once before any ebnf2ps process.
505 ;; `ebnf-production-hook'
506 ;; It is evaluated on each beginning of production.
509 ;; It is evaluated on each beginning of page.
515 ;; Below it's shown a brief description of ebnf2ps options, please, see the
516 ;; options declaration in the code for a long documentation.
518 ;; `ebnf-horizontal-orientation' Non-nil means productions are drawn
521 ;; `ebnf-horizontal-max-height' Non-nil means to use maximum production
522 ;; height in horizontal orientation.
524 ;; `ebnf-production-horizontal-space' Specify horizontal space in points
525 ;; between productions.
527 ;; `ebnf-production-vertical-space' Specify vertical space in points
528 ;; between productions.
530 ;; `ebnf-justify-sequence' Specify justification of terms in a
531 ;; sequence inside alternatives.
533 ;; `ebnf-terminal-regexp' Specify how it's a terminal name.
535 ;; `ebnf-case-fold-search' Non-nil means ignore case on matching.
537 ;; `ebnf-terminal-font' Specify terminal font.
539 ;; `ebnf-terminal-shape' Specify terminal box shape.
541 ;; `ebnf-terminal-shadow' Non-nil means terminal box will have a
544 ;; `ebnf-terminal-border-width' Specify border width for terminal box.
546 ;; `ebnf-terminal-border-color' Specify border color for terminal box.
548 ;; `ebnf-sort-production' Specify how productions are sorted.
550 ;; `ebnf-production-font' Specify production font.
552 ;; `ebnf-non-terminal-font' Specify non-terminal font.
554 ;; `ebnf-non-terminal-shape' Specify non-terminal box shape.
556 ;; `ebnf-non-terminal-shadow' Non-nil means non-terminal box will
559 ;; `ebnf-non-terminal-border-width' Specify border width for non-terminal
562 ;; `ebnf-non-terminal-border-color' Specify border color for non-terminal
565 ;; `ebnf-special-font' Specify special font.
567 ;; `ebnf-special-shape' Specify special box shape.
569 ;; `ebnf-special-shadow' Non-nil means special box will have a
572 ;; `ebnf-special-border-width' Specify border width for special box.
574 ;; `ebnf-special-border-color' Specify border color for special box.
576 ;; `ebnf-except-font' Specify except font.
578 ;; `ebnf-except-shape' Specify except box shape.
580 ;; `ebnf-except-shadow' Non-nil means except box will have a
583 ;; `ebnf-except-border-width' Specify border width for except box.
585 ;; `ebnf-except-border-color' Specify border color for except box.
587 ;; `ebnf-repeat-font' Specify repeat font.
589 ;; `ebnf-repeat-shape' Specify repeat box shape.
591 ;; `ebnf-repeat-shadow' Non-nil means repeat box will have a
594 ;; `ebnf-repeat-border-width' Specify border width for repeat box.
596 ;; `ebnf-repeat-border-color' Specify border color for repeat box.
598 ;; `ebnf-entry-percentage' Specify entry height on alternatives.
600 ;; `ebnf-arrow-shape' Specify the arrow shape.
602 ;; `ebnf-chart-shape' Specify chart flow shape.
604 ;; `ebnf-color-p' Non-nil means use color.
606 ;; `ebnf-line-width' Specify flow line width.
608 ;; `ebnf-line-color' Specify flow line color.
610 ;; `ebnf-user-arrow' Specify a sexp for user arrow shape (a
613 ;; `ebnf-debug-ps' Non-nil means to generate PostScript
616 ;; `ebnf-lex-comment-char' Specify the line comment character.
618 ;; `ebnf-lex-eop-char' Specify the end of production
621 ;; `ebnf-syntax' Specify syntax to be recognized.
623 ;; `ebnf-iso-alternative-p' Non-nil means use alternative ISO EBNF.
625 ;; `ebnf-iso-normalize-p' Non-nil means normalize ISO EBNF syntax
628 ;; `ebnf-default-width' Specify additional border width over
629 ;; default terminal, non-terminal or
632 ;; `ebnf-eps-prefix' Specify EPS prefix file name.
634 ;; `ebnf-use-float-format' Non-nil means use `%f' float format.
636 ;; `ebnf-yac-ignore-error-recovery' Non-nil means ignore error recovery.
638 ;; `ebnf-ignore-empty-rule' Non-nil means ignore empty rules.
640 ;; `ebnf-optimize' Non-nil means optimize syntatic chart
643 ;; To set the above options you may:
645 ;; a) insert the code in your ~/.emacs, like:
647 ;; (setq ebnf-terminal-shape 'bevel)
649 ;; This way always keep your default settings when you enter a new Emacs
652 ;; b) or use `set-variable' in your Emacs session, like:
654 ;; M-x set-variable RET ebnf-terminal-shape RET bevel RET
656 ;; This way keep your settings only during the current Emacs session.
658 ;; c) or use customization, for example:
659 ;; click on menu-bar *Help* option,
660 ;; then click on *Customize*,
661 ;; then click on *Browse Customization Groups*,
662 ;; expand *PostScript* group,
663 ;; expand *Ebnf2ps* group
664 ;; and then customize ebnf2ps options.
665 ;; Through this way, you may choose if the settings are kept or not when
666 ;; you leave out the current Emacs session.
668 ;; d) or see the option value:
670 ;; C-h v ebnf-terminal-shape RET
672 ;; and click the *customize* hypertext button.
673 ;; Through this way, you may choose if the settings are kept or not when
674 ;; you leave out the current Emacs session.
678 ;; M-x ebnf-customize RET
680 ;; and then customize ebnf2ps options.
681 ;; Through this way, you may choose if the settings are kept or not when
682 ;; you leave out the current Emacs session.
688 ;; Sometimes you need to change the EBNF style you are using, for example,
689 ;; change the shapes and colors. These changes may force you to set some
690 ;; variables and after use, set back the variables to the old values.
692 ;; To help to handle this situation, ebnf2ps has the following commands to
695 ;; `ebnf-insert-style' Insert a new style NAME with inheritance INHERITS and
698 ;; `ebnf-merge-style' Merge values of style NAME with style VALUES.
700 ;; `ebnf-apply-style' Set STYLE to current style.
702 ;; `ebnf-reset-style' Reset current style.
704 ;; `ebnf-push-style' Push the current style and set STYLE to current style.
706 ;; `ebnf-pop-style' Pop a style and set it to current style.
708 ;; These commands helps to put together a lot of variable settings in a group
709 ;; and name this group. So when you wish to apply these settings it's only
710 ;; needed to give the name.
712 ;; There is also a notion of simple inheritance of style; so if you declare
713 ;; that a style A inherits from a style B, all settings of B is applied first
714 ;; and then the settings of A is applied. This is useful when you wish to
715 ;; modify some aspects of an existing style, but at same time wish to keep it
718 ;; See documentation for `ebnf-style-database'.
724 ;; Below it is the layout of minimum area to draw each element, and it's used
725 ;; the following terms:
727 ;; font height is given by:
728 ;; (terminal font height + non-terminal font height) / 2
730 ;; entry is the vertical position used to know where it should
731 ;; be drawn the flow line in the current element.
734 ;; * SPECIAL, TERMINAL and NON-TERMINAL
736 ;; +==============+...................................
737 ;; | | } font height / 2 } entry }
738 ;; | XXXXXXXX...|....... } }
739 ;; ====+ XXXXXXXX +==== } text height ...... } height
740 ;; : | XXXXXXXX...|...:... }
741 ;; : | : : | : } font height / 2 }
742 ;; : +==============+...:...............................
744 ;; : : : : : :......................
745 ;; : : : : : } font height }
746 ;; : : : : :....... }
747 ;; : : : : } font height / 2 }
748 ;; : : : :........... }
749 ;; : : : } text width } width
750 ;; : : :.................. }
751 ;; : : } font height / 2 }
752 ;; : :...................... }
754 ;; :.............................................
759 ;; +==========+.....................................
763 ;; ===+===+ +===+===... } element height } height
766 ;; : | +==========+.|................. }
767 ;; : | : : | : } font height }
768 ;; : +==============+...................................
770 ;; : : : :......................
771 ;; : : : } font height * 2 }
773 ;; : : } element width } width
774 ;; : :..................... }
775 ;; : } font height * 2 }
776 ;; :...............................................
781 ;; +===+...................................
782 ;; +==+ A +==+ } A height } }
783 ;; | +===+..|........ } entry }
784 ;; + + } font height } }
785 ;; / +===+...\....... } }
786 ;; ===+====+ B +====+=== } B height ..... } height
787 ;; : \ +===+.../....... }
788 ;; : + + : } font height }
789 ;; : | +===+..|........ }
790 ;; : +==+ C +==+ : } C height }
791 ;; : : +===+...................................
793 ;; : : : :......................
794 ;; : : : } font height * 2 }
796 ;; : : } max width } width
797 ;; : :................. }
798 ;; : } font height * 2 }
799 ;; :..........................................
802 ;; 1. An empty alternative has zero of height.
804 ;; 2. The variable `ebnf-entry-percentage' is used to determine the
810 ;; +===========+...............................
811 ;; +=+ separator +=+ } separator height }
812 ;; / +===========+..\........ }
814 ;; | | } font height }
816 ;; \ +===========+../........ } height = entry
817 ;; +=+ element +=+ } element height }
818 ;; /: +===========+..\........ }
820 ;; + : : + } font height }
822 ;; ==+=======================+==.......................
824 ;; : : : :.......................
825 ;; : : : } font height * 2 }
827 ;; : : } max width } width
828 ;; : :......................... }
829 ;; : } font height * 2 }
830 ;; :...................................................
835 ;; +===========+......................................
836 ;; +=+ separator +=+ } separator height } }
837 ;; / +===========+..\...... } }
839 ;; | | } font height } } height
841 ;; \ +===========+../...... } }
842 ;; ===+=+ element +=+=== } element height .... }
843 ;; : : +===========+......................................
845 ;; : : : :........................
846 ;; : : : } font height * 2 }
848 ;; : : } max width } width
849 ;; : :....................... }
850 ;; : } font height * 2 }
851 ;; :..............................................
856 ;; XXXXXX:......................................
857 ;; XXXXXX: } production font height }
858 ;; XXXXXX:............ }
860 ;; +======+....... } height = entry
862 ;; ====+ +==== } element height }
864 ;; : +======+.................................
866 ;; : : : :......................
867 ;; : : : } font height * 2 }
869 ;; : : } element width } width
870 ;; : :.............. }
871 ;; : } font height * 2 }
872 ;; :.....................................
877 ;; +================+...................................
878 ;; | | } font height / 2 } entry }
879 ;; | +===+...|....... } }
880 ;; ====+ N * | X | +==== } X height ......... } height
881 ;; : | : : +===+...|...:... }
882 ;; : | : : : : | : } font height / 2 }
883 ;; : +================+...:...............................
885 ;; : : : : : : : :......................
886 ;; : : : : : : : } font height }
887 ;; : : : : : : :....... }
888 ;; : : : : : : } font height / 2 }
889 ;; : : : : : :........... }
890 ;; : : : : : } X width }
891 ;; : : : : :............... }
892 ;; : : : : } font height / 2 } width
893 ;; : : : :.................. }
894 ;; : : : } text width }
895 ;; : : :..................... }
896 ;; : : } font height / 2 }
897 ;; : :........................ }
899 ;; :...............................................
904 ;; +==================+...................................
905 ;; | | } font height / 2 } entry }
906 ;; | +===+ +===+...|....... } }
907 ;; ====+ | X | - | y | +==== } max height ....... } height
908 ;; : | +===+ +===+...|...:... }
909 ;; : | : : : : | : } font height / 2 }
910 ;; : +==================+...:...............................
912 ;; : : : : : : : :......................
913 ;; : : : : : : : } font height }
914 ;; : : : : : : :....... }
915 ;; : : : : : : } font height / 2 }
916 ;; : : : : : :........... }
917 ;; : : : : : } Y width }
918 ;; : : : : :............... }
919 ;; : : : : } font height } width
920 ;; : : : :................... }
922 ;; : : :....................... }
923 ;; : : } font height / 2 }
924 ;; : :.......................... }
926 ;; :.................................................
928 ;; NOTE: If Y element is empty, it's draw nothing at Y place.
931 ;; Internal Structures
932 ;; -------------------
934 ;; ebnf2ps has two passes. The first pass does a lexical and syntatic analysis
935 ;; of current buffer and generates an intermediate representation. The second
936 ;; pass uses the intermediate representation to generate the PostScript
939 ;; The intermediate representation is a list of vectors, the vector element
940 ;; represents a syntatic chart element. Below is a vector representation for
941 ;; each syntatic chart element.
943 ;; [production WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH NAME PRODUCTION ACTION]
944 ;; [alternative WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH LIST]
945 ;; [sequence WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH LIST]
946 ;; [terminal WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH NAME DEFAULT]
947 ;; [non-terminal WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH NAME DEFAULT]
948 ;; [special WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH NAME DEFAULT]
949 ;; [empty WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH]
950 ;; [optional WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH ELEMENT]
951 ;; [one-or-more WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH ELEMENT SEPARATOR]
952 ;; [zero-or-more WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH ELEMENT SEPARATOR]
953 ;; [repeat WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH TIMES ELEMENT]
954 ;; [except WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH ELEMENT ELEMENT]
956 ;; The first vector position is a function symbol used to generate PostScript
958 ;; WIDTH-FUN is a function symbol called to adjust the element width.
959 ;; DIM-FUN is a function symbol called to set the element dimensions.
960 ;; ENTRY is the element entry point.
961 ;; HEIGHT and WIDTH are the element height and width, respectively.
962 ;; NAME is a string that it's the element name.
963 ;; DEFAULT is a boolean that indicates if it's a `default' element.
964 ;; PRODUCTION and ELEMENT are vectors that represents sub-elements of current
966 ;; LIST is a list of vector that represents the list part for alternatives and
968 ;; SEPARATOR is a vector that represents the sub-element used to separate the
970 ;; TIMES is a string representing the number of times that ELEMENT is repeated
971 ;; on a repeat construction.
972 ;; ACTION indicates some action that should be done before production is
973 ;; generated. The current actions are:
977 ;; form-feed current production starts on a new page.
979 ;; newline current production starts on next line, this is useful
980 ;; when `ebnf-horizontal-orientation' is non-nil.
982 ;; keep-line current production continues on the current line, this
983 ;; is useful when `ebnf-horizontal-orientation' is nil.
989 ;; . Handle situations when syntatic chart is out of paper.
990 ;; . Use other alphabet than ascii.
991 ;; . Optimizations...
997 ;; Thanks to all who emailed comments.
1000 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1007 (and (string< ps-print-version
"5.2.3")
1008 (error "`ebnf2ps' requires `ps-print' package version 5.2.3 or later"))
1011 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1015 ;;; Interface to the command system
1017 (defgroup postscript nil
1023 (defgroup ebnf2ps nil
1024 "Translate an EBNF to a syntatic chart on PostScript"
1030 (defgroup ebnf-special nil
1031 "Special customization"
1037 (defgroup ebnf-except nil
1038 "Except customization"
1044 (defgroup ebnf-repeat nil
1045 "Repeat customization"
1051 (defgroup ebnf-terminal nil
1052 "Terminal customization"
1058 (defgroup ebnf-non-terminal nil
1059 "Non-Terminal customization"
1065 (defgroup ebnf-production nil
1066 "Production customization"
1072 (defgroup ebnf-shape nil
1073 "Shapes customization"
1079 (defgroup ebnf-displacement nil
1080 "Displacement customization"
1086 (defgroup ebnf-syntatic nil
1087 "Syntatic customization"
1093 (defgroup ebnf-optimization nil
1094 "Optimization customization"
1100 (defcustom ebnf-horizontal-orientation nil
1101 "*Non-nil means productions are drawn horizontally."
1103 :group
'ebnf-displacement
)
1106 (defcustom ebnf-horizontal-max-height nil
1107 "*Non-nil means to use maximum production height in horizontal orientation.
1109 It is only used when `ebnf-horizontal-orientation' is non-nil."
1111 :group
'ebnf-displacement
)
1114 (defcustom ebnf-production-horizontal-space
0.0 ; use ebnf2ps default value
1115 "*Specify horizontal space in points between productions.
1117 Value less or equal to zero forces ebnf2ps to set a proper default value."
1119 :group
'ebnf-displacement
)
1122 (defcustom ebnf-production-vertical-space
0.0 ; use ebnf2ps default value
1123 "*Specify vertical space in points between productions.
1125 Value less or equal to zero forces ebnf2ps to set a proper default value."
1127 :group
'ebnf-displacement
)
1130 (defcustom ebnf-justify-sequence
'center
1131 "*Specify justification of terms in a sequence inside alternatives.
1135 `left' left justification
1136 `right' right justification
1137 any other value centralize"
1138 :type
'(radio :tag
"Sequence Justification"
1139 (const left
) (const right
) (other :tag
"center" center
))
1140 :group
'ebnf-displacement
)
1143 (defcustom ebnf-special-font
'(7 Courier
"Black" "Gray95" bold italic
)
1144 "*Specify special font.
1146 See documentation for `ebnf-production-font'."
1147 :type
'(list :tag
"Special Font"
1148 (number :tag
"Font Size")
1149 (symbol :tag
"Font Name")
1150 (choice :tag
"Foreground Color"
1151 (string :tag
"Name")
1152 (other :tag
"Default" nil
))
1153 (choice :tag
"Background Color"
1154 (string :tag
"Name")
1155 (other :tag
"Default" nil
))
1156 (repeat :tag
"Font Attributes" :inline t
1157 (choice (const bold
) (const italic
)
1158 (const underline
) (const strikeout
)
1159 (const overline
) (const shadow
)
1160 (const box
) (const outline
))))
1161 :group
'ebnf-special
)
1164 (defcustom ebnf-special-shape
'bevel
1165 "*Specify special box shape.
1167 See documentation for `ebnf-non-terminal-shape'."
1168 :type
'(radio :tag
"Special Shape"
1169 (const miter
) (const round
) (const bevel
))
1170 :group
'ebnf-special
)
1173 (defcustom ebnf-special-shadow nil
1174 "*Non-nil means special box will have a shadow."
1176 :group
'ebnf-special
)
1179 (defcustom ebnf-special-border-width
0.5
1180 "*Specify border width for special box."
1182 :group
'ebnf-special
)
1185 (defcustom ebnf-special-border-color
"Black"
1186 "*Specify border color for special box."
1188 :group
'ebnf-special
)
1191 (defcustom ebnf-except-font
'(7 Courier
"Black" "Gray90" bold italic
)
1192 "*Specify except font.
1194 See documentation for `ebnf-production-font'."
1195 :type
'(list :tag
"Except Font"
1196 (number :tag
"Font Size")
1197 (symbol :tag
"Font Name")
1198 (choice :tag
"Foreground Color"
1199 (string :tag
"Name")
1200 (other :tag
"Default" nil
))
1201 (choice :tag
"Background Color"
1202 (string :tag
"Name")
1203 (other :tag
"Default" nil
))
1204 (repeat :tag
"Font Attributes" :inline t
1205 (choice (const bold
) (const italic
)
1206 (const underline
) (const strikeout
)
1207 (const overline
) (const shadow
)
1208 (const box
) (const outline
))))
1209 :group
'ebnf-except
)
1212 (defcustom ebnf-except-shape
'bevel
1213 "*Specify except box shape.
1215 See documentation for `ebnf-non-terminal-shape'."
1216 :type
'(radio :tag
"Except Shape"
1217 (const miter
) (const round
) (const bevel
))
1218 :group
'ebnf-except
)
1221 (defcustom ebnf-except-shadow nil
1222 "*Non-nil means except box will have a shadow."
1224 :group
'ebnf-except
)
1227 (defcustom ebnf-except-border-width
0.25
1228 "*Specify border width for except box."
1230 :group
'ebnf-except
)
1233 (defcustom ebnf-except-border-color
"Black"
1234 "*Specify border color for except box."
1236 :group
'ebnf-except
)
1239 (defcustom ebnf-repeat-font
'(7 Courier
"Black" "Gray85" bold italic
)
1240 "*Specify repeat font.
1242 See documentation for `ebnf-production-font'."
1243 :type
'(list :tag
"Repeat Font"
1244 (number :tag
"Font Size")
1245 (symbol :tag
"Font Name")
1246 (choice :tag
"Foreground Color"
1247 (string :tag
"Name")
1248 (other :tag
"Default" nil
))
1249 (choice :tag
"Background Color"
1250 (string :tag
"Name")
1251 (other :tag
"Default" nil
))
1252 (repeat :tag
"Font Attributes" :inline t
1253 (choice (const bold
) (const italic
)
1254 (const underline
) (const strikeout
)
1255 (const overline
) (const shadow
)
1256 (const box
) (const outline
))))
1257 :group
'ebnf-repeat
)
1260 (defcustom ebnf-repeat-shape
'bevel
1261 "*Specify repeat box shape.
1263 See documentation for `ebnf-non-terminal-shape'."
1264 :type
'(radio :tag
"Repeat Shape"
1265 (const miter
) (const round
) (const bevel
))
1266 :group
'ebnf-repeat
)
1269 (defcustom ebnf-repeat-shadow nil
1270 "*Non-nil means repeat box will have a shadow."
1272 :group
'ebnf-repeat
)
1275 (defcustom ebnf-repeat-border-width
0.0
1276 "*Specify border width for repeat box."
1278 :group
'ebnf-repeat
)
1281 (defcustom ebnf-repeat-border-color
"Black"
1282 "*Specify border color for repeat box."
1284 :group
'ebnf-repeat
)
1287 (defcustom ebnf-terminal-font
'(7 Courier
"Black" "White")
1288 "*Specify terminal font.
1290 See documentation for `ebnf-production-font'."
1291 :type
'(list :tag
"Terminal Font"
1292 (number :tag
"Font Size")
1293 (symbol :tag
"Font Name")
1294 (choice :tag
"Foreground Color"
1295 (string :tag
"Name")
1296 (other :tag
"Default" nil
))
1297 (choice :tag
"Background Color"
1298 (string :tag
"Name")
1299 (other :tag
"Default" nil
))
1300 (repeat :tag
"Font Attributes" :inline t
1301 (choice (const bold
) (const italic
)
1302 (const underline
) (const strikeout
)
1303 (const overline
) (const shadow
)
1304 (const box
) (const outline
))))
1305 :group
'ebnf-terminal
)
1308 (defcustom ebnf-terminal-shape
'miter
1309 "*Specify terminal box shape.
1311 See documentation for `ebnf-non-terminal-shape'."
1312 :type
'(radio :tag
"Terminal Shape"
1313 (const miter
) (const round
) (const bevel
))
1314 :group
'ebnf-terminal
)
1317 (defcustom ebnf-terminal-shadow nil
1318 "*Non-nil means terminal box will have a shadow."
1320 :group
'ebnf-terminal
)
1323 (defcustom ebnf-terminal-border-width
1.0
1324 "*Specify border width for terminal box."
1326 :group
'ebnf-terminal
)
1329 (defcustom ebnf-terminal-border-color
"Black"
1330 "*Specify border color for terminal box."
1332 :group
'ebnf-terminal
)
1335 (defcustom ebnf-sort-production nil
1336 "*Specify how productions are sorted.
1340 nil don't sort productions.
1341 `ascending' ascending sort.
1342 any other value descending sort."
1343 :type
'(radio :tag
"Production Sort"
1344 (const :tag
"Ascending" ascending
)
1345 (const :tag
"Descending" descending
)
1346 (other :tag
"No Sort" nil
))
1347 :group
'ebnf-production
)
1350 (defcustom ebnf-production-font
'(10 Helvetica
"Black" "White" bold
)
1351 "*Specify production header font.
1353 It is a list with the following form:
1355 (SIZE NAME FOREGROUND BACKGROUND ATTRIBUTE...)
1358 SIZE is the font size.
1359 NAME is the font name symbol.
1360 ATTRIBUTE is one of the following symbols:
1361 bold - use bold font.
1362 italic - use italic font.
1363 underline - put a line under text.
1364 strikeout - like underline, but the line is in middle of text.
1365 overline - like underline, but the line is over the text.
1366 shadow - text will have a shadow.
1367 box - text will be surrounded by a box.
1368 outline - print characters as hollow outlines.
1369 FOREGROUND is a foreground string color name; if it's nil, the default color is
1371 BACKGROUND is a background string color name; if it's nil, the default color is
1374 See `ps-font-info-database' for valid font name."
1375 :type
'(list :tag
"Production Font"
1376 (number :tag
"Font Size")
1377 (symbol :tag
"Font Name")
1378 (choice :tag
"Foreground Color"
1379 (string :tag
"Name")
1380 (other :tag
"Default" nil
))
1381 (choice :tag
"Background Color"
1382 (string :tag
"Name")
1383 (other :tag
"Default" nil
))
1384 (repeat :tag
"Font Attributes" :inline t
1385 (choice (const bold
) (const italic
)
1386 (const underline
) (const strikeout
)
1387 (const overline
) (const shadow
)
1388 (const box
) (const outline
))))
1389 :group
'ebnf-production
)
1392 (defcustom ebnf-non-terminal-font
'(7 Helvetica
"Black" "White")
1393 "*Specify non-terminal font.
1395 See documentation for `ebnf-production-font'."
1396 :type
'(list :tag
"Non-Terminal Font"
1397 (number :tag
"Font Size")
1398 (symbol :tag
"Font Name")
1399 (choice :tag
"Foreground Color"
1400 (string :tag
"Name")
1401 (other :tag
"Default" nil
))
1402 (choice :tag
"Background Color"
1403 (string :tag
"Name")
1404 (other :tag
"Default" nil
))
1405 (repeat :tag
"Font Attributes" :inline t
1406 (choice (const bold
) (const italic
)
1407 (const underline
) (const strikeout
)
1408 (const overline
) (const shadow
)
1409 (const box
) (const outline
))))
1410 :group
'ebnf-non-terminal
)
1413 (defcustom ebnf-non-terminal-shape
'round
1414 "*Specify non-terminal box shape.
1430 Any other value is treated as `miter'."
1431 :type
'(radio :tag
"Non-Terminal Shape"
1432 (const miter
) (const round
) (const bevel
))
1433 :group
'ebnf-non-terminal
)
1436 (defcustom ebnf-non-terminal-shadow nil
1437 "*Non-nil means non-terminal box will have a shadow."
1439 :group
'ebnf-non-terminal
)
1442 (defcustom ebnf-non-terminal-border-width
1.0
1443 "*Specify border width for non-terminal box."
1445 :group
'ebnf-non-terminal
)
1448 (defcustom ebnf-non-terminal-border-color
"Black"
1449 "*Specify border color for non-terminal box."
1451 :group
'ebnf-non-terminal
)
1454 (defcustom ebnf-arrow-shape
'hollow
1455 "*Specify the arrow shape.
1461 `semi-up' * `transparent' *
1469 `semi-down' =====* `hollow' *
1485 `user' See also documentation for variable `ebnf-user-arrow'.
1487 Any other value is treated as `none'."
1488 :type
'(radio :tag
"Arrow Shape"
1489 (const none
) (const semi-up
)
1490 (const semi-down
) (const simple
)
1491 (const transparent
) (const hollow
)
1492 (const full
) (const user
))
1496 (defcustom ebnf-chart-shape
'round
1497 "*Specify chart flow shape.
1499 See documentation for `ebnf-non-terminal-shape'."
1500 :type
'(radio :tag
"Chart Flow Shape"
1501 (const miter
) (const round
) (const bevel
))
1505 (defcustom ebnf-user-arrow nil
1506 "*Specify a sexp for user arrow shape (a PostScript code).
1508 When evaluated, the sexp should return nil or a string containing PostScript
1509 code. PostScript code should draw a right arrow.
1511 The anatomy of a right arrow is:
1513 ...... Initial position
1515 : *.................
1519 ======+======*... } hT2
1523 : *.................
1529 :.......................
1531 Where `hT', `hT2' and `hT4' are predefined PostScript variable names that can
1532 be used to generate your own arrow. As these variables are used along
1533 PostScript execution, *DON'T* modify the values of them. Instead, copy the
1534 values, if you need to modify them.
1536 The relation between these variables is: hT = 2 * hT2 = 4 * hT4.
1538 The variable `ebnf-user-arrow' is only used when `ebnf-arrow-shape' is set to
1540 :type
'(sexp :tag
"User Arrow Shape")
1544 (defcustom ebnf-syntax
'ebnf
1545 "*Specify syntax to be recognized.
1549 `ebnf' ebnf2ps recognizes the syntax described in ebnf2ps
1551 The following variables *ONLY* have effect with this
1553 `ebnf-terminal-regexp', `ebnf-case-fold-search',
1554 `ebnf-lex-comment-char' and `ebnf-lex-eop-char'.
1556 `iso-ebnf' ebnf2ps recognizes the syntax described in the URL:
1557 `http://www.cl.cam.ac.uk/~mgk25/iso-ebnf.html'
1558 (\"International Standard of the ISO EBNF Notation\").
1559 The following variables *ONLY* have effect with this
1561 `ebnf-iso-alternative-p' and `ebnf-iso-normalize-p'.
1563 `yacc' ebnf2ps recognizes the Yacc/Bison syntax.
1564 The following variable *ONLY* has effect with this
1566 `ebnf-yac-ignore-error-recovery'.
1568 Any other value is treated as `ebnf'."
1569 :type
'(radio :tag
"Syntax"
1570 (const ebnf
) (const iso-ebnf
) (const yacc
))
1571 :group
'ebnf-syntatic
)
1574 (defcustom ebnf-lex-comment-char ?\
;
1575 "*Specify the line comment character.
1577 It's used only when `ebnf-syntax' is `ebnf'."
1579 :group
'ebnf-syntatic
)
1582 (defcustom ebnf-lex-eop-char ?.
1583 "*Specify the end of production character.
1585 It's used only when `ebnf-syntax' is `ebnf'."
1587 :group
'ebnf-syntatic
)
1590 (defcustom ebnf-terminal-regexp nil
1591 "*Specify how it's a terminal name.
1593 If it's nil, the terminal name must be enclosed by `\"'.
1594 If it's a string, it should be a regexp that it'll be used to determine a
1595 terminal name; terminal name may also be enclosed by `\"'.
1597 It's used only when `ebnf-syntax' is `ebnf'."
1598 :type
'(radio :tag
"Terminal Name"
1600 :group
'ebnf-syntatic
)
1603 (defcustom ebnf-case-fold-search nil
1604 "*Non-nil means ignore case on matching.
1606 It's only used when `ebnf-terminal-regexp' is non-nil and when `ebnf-syntax' is
1609 :group
'ebnf-syntatic
)
1612 (defcustom ebnf-iso-alternative-p nil
1613 "*Non-nil means use alternative ISO EBNF.
1615 It's only used when `ebnf-syntax' is `iso-ebnf'.
1617 This variable affects the following symbol set:
1619 STANDARD ALTERNATIVE
1627 :group
'ebnf-syntatic
)
1630 (defcustom ebnf-iso-normalize-p nil
1631 "*Non-nil means normalize ISO EBNF syntax names.
1633 Normalize a name means that several contiguous spaces inside name become a
1634 single space, so \"A B C\" is normalized to \"A B C\".
1636 It's only used when `ebnf-syntax' is `iso-ebnf'."
1638 :group
'ebnf-syntatic
)
1641 (defcustom ebnf-eps-prefix
"ebnf--"
1642 "*Specify EPS prefix file name.
1644 See `ebnf-eps-buffer' and `ebnf-eps-region' commands."
1649 (defcustom ebnf-entry-percentage
0.5 ; middle
1650 "*Specify entry height on alternatives.
1652 It must be a float between 0.0 (top) and 1.0 (bottom)."
1657 (defcustom ebnf-default-width
0.6
1658 "*Specify additional border width over default terminal, non-terminal or
1664 ;; Printing color requires x-color-values.
1665 (defcustom ebnf-color-p
(or (fboundp 'x-color-values
) ; Emacs
1666 (fboundp 'color-instance-rgb-components
)) ; XEmacs
1667 "*Non-nil means use color."
1672 (defcustom ebnf-line-width
1.0
1673 "*Specify flow line width."
1678 (defcustom ebnf-line-color
"Black"
1679 "*Specify flow line color."
1684 (defcustom ebnf-debug-ps nil
1685 "*Non-nil means to generate PostScript debug procedures.
1687 It is intended to help PostScript programmers in debugging."
1692 (defcustom ebnf-use-float-format t
1693 "*Non-nil means use `%f' float format.
1695 The advantage of using float format is that ebnf2ps generates a little short
1698 If it occurs the error message:
1700 Invalid format operation %f
1702 when executing ebnf2ps, set `ebnf-use-float-format' to nil."
1707 (defcustom ebnf-yac-ignore-error-recovery nil
1708 "*Non-nil means ignore error recovery.
1710 It's only used when `ebnf-syntax' is `yacc'."
1712 :group
'ebnf-syntatic
)
1715 (defcustom ebnf-ignore-empty-rule nil
1716 "*Non-nil means ignore empty rules.
1718 It's interesting to set this variable if your Yacc/Bison grammar has a lot of
1719 middle action rule."
1721 :group
'ebnf-optimization
)
1724 (defcustom ebnf-optimize nil
1725 "*Non-nil means optimize syntatic chart of rules.
1727 The following optimizations are done:
1730 1. A = B | A C. ==> A = B {C}*.
1731 2. A = B | A B. ==> A = {B}+.
1732 3. A = | A B. ==> A = {B}*.
1733 4. A = B | A C B. ==> A = {B || C}+.
1734 5. A = B | D | A C | A E. ==> A = ( B | D ) { C | E }*.
1737 6. A = B | . ==> A = [B].
1738 7. A = | B . ==> A = [B].
1741 8. A = B C | B D. ==> A = B (C | D).
1742 9. A = C B | D B. ==> A = (C | D) B.
1743 10. A = B C E | B D E. ==> A = B (C | D) E.
1745 The above optimizations are specially useful when `ebnf-syntax' is `yacc'."
1747 :group
'ebnf-optimization
)
1750 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1755 (defun ebnf-customize ()
1756 "Customization for ebnf group."
1758 (customize-group 'ebnf2ps
))
1761 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1766 (defun ebnf-print-buffer (&optional filename
)
1767 "Generate and print a PostScript syntatic chart image of the buffer.
1769 When called with a numeric prefix argument (C-u), prompts the user for
1770 the name of a file to save the PostScript image in, instead of sending
1773 More specifically, the FILENAME argument is treated as follows: if it
1774 is nil, send the image to the printer. If FILENAME is a string, save
1775 the PostScript image in a file with that name. If FILENAME is a
1776 number, prompt the user for the name of the file to save in."
1777 (interactive (list (ps-print-preprint current-prefix-arg
)))
1778 (ebnf-print-region (point-min) (point-max) filename
))
1782 (defun ebnf-print-region (from to
&optional filename
)
1783 "Generate and print a PostScript syntatic chart image of the region.
1784 Like `ebnf-print-buffer', but prints just the current region."
1785 (interactive (list (point) (mark) (ps-print-preprint current-prefix-arg
)))
1786 (run-hooks 'ebnf-hook
)
1787 (or (ebnf-spool-region from to
)
1788 (ps-do-despool filename
)))
1792 (defun ebnf-spool-buffer ()
1793 "Generate and spool a PostScript syntatic chart image of the buffer.
1794 Like `ebnf-print-buffer' except that the PostScript image is saved in a
1795 local buffer to be sent to the printer later.
1797 Use the command `ebnf-despool' to send the spooled images to the printer."
1799 (ebnf-spool-region (point-min) (point-max)))
1803 (defun ebnf-spool-region (from to
)
1804 "Generate a PostScript syntatic chart image of the region and spool locally.
1805 Like `ebnf-spool-buffer', but spools just the current region.
1807 Use the command `ebnf-despool' to send the spooled images to the printer."
1809 (ebnf-generate-region from to
'ebnf-generate
))
1813 (defun ebnf-eps-buffer ()
1814 "Generate a PostScript syntatic chart image of the buffer in a EPS file.
1816 Indeed, for each production is generated a EPS file.
1817 The EPS file name has the following form:
1819 <PREFIX><PRODUCTION>.eps
1821 <PREFIX> is given by variable `ebnf-eps-prefix'.
1822 The default value is \"ebnf--\".
1824 <PRODUCTION> is the production name.
1825 The production name is mapped to form a valid file name.
1826 For example, the production name \"A/B + C\" is mapped to
1827 \"A_B_+_C\" and the EPS file name used is \"ebnf--A_B_+_C.eps\".
1829 WARNING: It's *NOT* asked any confirmation to override an existing file."
1831 (ebnf-eps-region (point-min) (point-max)))
1835 (defun ebnf-eps-region (from to
)
1836 "Generate a PostScript syntatic chart image of the region in a EPS file.
1838 Indeed, for each production is generated a EPS file.
1839 The EPS file name has the following form:
1841 <PREFIX><PRODUCTION>.eps
1843 <PREFIX> is given by variable `ebnf-eps-prefix'.
1844 The default value is \"ebnf--\".
1846 <PRODUCTION> is the production name.
1847 The production name is mapped to form a valid file name.
1848 For example, the production name \"A/B + C\" is mapped to
1849 \"A_B_+_C\" and the EPS file name used is \"ebnf--A_B_+_C.eps\".
1851 WARNING: It's *NOT* asked any confirmation to override an existing file."
1853 (let ((ebnf-eps-executing t
))
1854 (ebnf-generate-region from to
'ebnf-generate-eps
)))
1858 (defalias 'ebnf-despool
'ps-despool
)
1862 (defun ebnf-syntax-buffer ()
1863 "Does a syntatic analysis of the current buffer."
1865 (ebnf-syntax-region (point-min) (point-max)))
1869 (defun ebnf-syntax-region (from to
)
1870 "Does a syntatic analysis of a region."
1872 (ebnf-generate-region from to nil
))
1875 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1880 (defun ebnf-setup ()
1881 "Return the current ebnf2ps setup."
1884 ;;; ebnf2ps.el version %s
1886 \(setq ebnf-special-font %s
1887 ebnf-special-shape %s
1888 ebnf-special-shadow %S
1889 ebnf-special-border-width %S
1890 ebnf-special-border-color %S
1892 ebnf-except-shape %s
1893 ebnf-except-shadow %S
1894 ebnf-except-border-width %S
1895 ebnf-except-border-color %S
1897 ebnf-repeat-shape %s
1898 ebnf-repeat-shadow %S
1899 ebnf-repeat-border-width %S
1900 ebnf-repeat-border-color %S
1901 ebnf-terminal-regexp %S
1902 ebnf-case-fold-search %S
1903 ebnf-terminal-font %s
1904 ebnf-terminal-shape %s
1905 ebnf-terminal-shadow %S
1906 ebnf-terminal-border-width %S
1907 ebnf-terminal-border-color %S
1908 ebnf-non-terminal-font %s
1909 ebnf-non-terminal-shape %s
1910 ebnf-non-terminal-shadow %S
1911 ebnf-non-terminal-border-width %S
1912 ebnf-non-terminal-border-color %S
1913 ebnf-sort-production %s
1914 ebnf-production-font %s
1918 ebnf-horizontal-orientation %S
1919 ebnf-horizontal-max-height %S
1920 ebnf-production-horizontal-space %S
1921 ebnf-production-vertical-space %S
1922 ebnf-justify-sequence %s
1923 ebnf-lex-comment-char ?\\%03o
1924 ebnf-lex-eop-char ?\\%03o
1926 ebnf-iso-alternative-p %S
1927 ebnf-iso-normalize-p %S
1929 ebnf-entry-percentage %S
1934 ebnf-use-float-format %S
1935 ebnf-yac-ignore-error-recovery %S
1936 ebnf-ignore-empty-rule %S
1939 ;;; ebnf2ps.el - end of settings
1942 (ps-print-quote ebnf-special-font
)
1943 (ps-print-quote ebnf-special-shape
)
1945 ebnf-special-border-width
1946 ebnf-special-border-color
1947 (ps-print-quote ebnf-except-font
)
1948 (ps-print-quote ebnf-except-shape
)
1950 ebnf-except-border-width
1951 ebnf-except-border-color
1952 (ps-print-quote ebnf-repeat-font
)
1953 (ps-print-quote ebnf-repeat-shape
)
1955 ebnf-repeat-border-width
1956 ebnf-repeat-border-color
1957 ebnf-terminal-regexp
1958 ebnf-case-fold-search
1959 (ps-print-quote ebnf-terminal-font
)
1960 (ps-print-quote ebnf-terminal-shape
)
1961 ebnf-terminal-shadow
1962 ebnf-terminal-border-width
1963 ebnf-terminal-border-color
1964 (ps-print-quote ebnf-non-terminal-font
)
1965 (ps-print-quote ebnf-non-terminal-shape
)
1966 ebnf-non-terminal-shadow
1967 ebnf-non-terminal-border-width
1968 ebnf-non-terminal-border-color
1969 (ps-print-quote ebnf-sort-production
)
1970 (ps-print-quote ebnf-production-font
)
1971 (ps-print-quote ebnf-arrow-shape
)
1972 (ps-print-quote ebnf-chart-shape
)
1973 (ps-print-quote ebnf-user-arrow
)
1974 ebnf-horizontal-orientation
1975 ebnf-horizontal-max-height
1976 ebnf-production-horizontal-space
1977 ebnf-production-vertical-space
1978 (ps-print-quote ebnf-justify-sequence
)
1979 ebnf-lex-comment-char
1981 (ps-print-quote ebnf-syntax
)
1982 ebnf-iso-alternative-p
1983 ebnf-iso-normalize-p
1985 ebnf-entry-percentage
1990 ebnf-use-float-format
1991 ebnf-yac-ignore-error-recovery
1992 ebnf-ignore-empty-rule
1996 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2000 (defvar ebnf-stack-style nil
2001 "Used in functions `ebnf-reset-style', `ebnf-push-style' and
2005 (defvar ebnf-current-style
'default
2006 "Used in functions `ebnf-apply-style' and `ebnf-push-style'.")
2009 (defconst ebnf-style-custom-list
2013 ebnf-special-border-width
2014 ebnf-special-border-color
2018 ebnf-except-border-width
2019 ebnf-except-border-color
2023 ebnf-repeat-border-width
2024 ebnf-repeat-border-color
2025 ebnf-terminal-regexp
2026 ebnf-case-fold-search
2029 ebnf-terminal-shadow
2030 ebnf-terminal-border-width
2031 ebnf-terminal-border-color
2032 ebnf-non-terminal-font
2033 ebnf-non-terminal-shape
2034 ebnf-non-terminal-shadow
2035 ebnf-non-terminal-border-width
2036 ebnf-non-terminal-border-color
2037 ebnf-sort-production
2038 ebnf-production-font
2042 ebnf-horizontal-orientation
2043 ebnf-horizontal-max-height
2044 ebnf-production-horizontal-space
2045 ebnf-production-vertical-space
2046 ebnf-justify-sequence
2047 ebnf-lex-comment-char
2050 ebnf-iso-alternative-p
2051 ebnf-iso-normalize-p
2053 ebnf-entry-percentage
2058 ebnf-use-float-format
2059 ebnf-yac-ignore-error-recovery
2060 ebnf-ignore-empty-rule
2062 "List of valid symbol custom variable.")
2065 (defvar ebnf-style-database
2069 (ebnf-special-font .
'(7 Courier
"Black" "Gray95" bold italic
))
2070 (ebnf-special-shape .
'bevel
)
2071 (ebnf-special-shadow . nil
)
2072 (ebnf-special-border-width .
0.5)
2073 (ebnf-special-border-color .
"Black")
2074 (ebnf-except-font .
'(7 Courier
"Black" "Gray90" bold italic
))
2075 (ebnf-except-shape .
'bevel
)
2076 (ebnf-except-shadow . nil
)
2077 (ebnf-except-border-width .
0.25)
2078 (ebnf-except-border-color .
"Black")
2079 (ebnf-repeat-font .
'(7 Courier
"Black" "Gray85" bold italic
))
2080 (ebnf-repeat-shape .
'bevel
)
2081 (ebnf-repeat-shadow . nil
)
2082 (ebnf-repeat-border-width .
0.0)
2083 (ebnf-repeat-border-color .
"Black")
2084 (ebnf-terminal-regexp . nil
)
2085 (ebnf-case-fold-search . nil
)
2086 (ebnf-terminal-font .
'(7 Courier
"Black" "White"))
2087 (ebnf-terminal-shape .
'miter
)
2088 (ebnf-terminal-shadow . nil
)
2089 (ebnf-terminal-border-width .
1.0)
2090 (ebnf-terminal-border-color .
"Black")
2091 (ebnf-non-terminal-font .
'(7 Helvetica
"Black" "White"))
2092 (ebnf-non-terminal-shape .
'round
)
2093 (ebnf-non-terminal-shadow . nil
)
2094 (ebnf-non-terminal-border-width .
1.0)
2095 (ebnf-non-terminal-border-color .
"Black")
2096 (ebnf-sort-production . nil
)
2097 (ebnf-production-font .
'(10 Helvetica
"Black" "White" bold
))
2098 (ebnf-arrow-shape .
'hollow
)
2099 (ebnf-chart-shape .
'round
)
2100 (ebnf-user-arrow . nil
)
2101 (ebnf-horizontal-orientation . nil
)
2102 (ebnf-horizontal-max-height . nil
)
2103 (ebnf-production-horizontal-space .
0.0)
2104 (ebnf-production-vertical-space .
0.0)
2105 (ebnf-justify-sequence .
'center
)
2106 (ebnf-lex-comment-char . ?\
;)
2107 (ebnf-lex-eop-char . ?.
)
2108 (ebnf-syntax .
'ebnf
)
2109 (ebnf-iso-alternative-p . nil
)
2110 (ebnf-iso-normalize-p . nil
)
2111 (ebnf-eps-prefix .
"ebnf--")
2112 (ebnf-entry-percentage .
0.5)
2113 (ebnf-color-p .
(or (fboundp 'x-color-values
) ; Emacs
2114 (fboundp 'color-instance-rgb-components
))) ; XEmacs
2115 (ebnf-line-width .
1.0)
2116 (ebnf-line-color .
"Black")
2117 (ebnf-debug-ps . nil
)
2118 (ebnf-use-float-format . t
)
2119 (ebnf-yac-ignore-error-recovery . nil
)
2120 (ebnf-ignore-empty-rule . nil
)
2121 (ebnf-optimize . nil
))
2122 ;; Happy EBNF default
2125 (ebnf-justify-sequence .
'left
)
2126 (ebnf-lex-comment-char . ?\
#)
2127 (ebnf-lex-eop-char . ?\
;))
2131 (ebnf-syntax .
'iso-ebnf
))
2132 ;; Yacc/Bison default
2135 (ebnf-syntax .
'yacc
))
2139 Each element has the following form:
2141 (CUSTOM INHERITS (VAR . VALUE)...)
2143 CUSTOM is a symbol name style.
2144 INHERITS is a symbol name style from which the current style inherits the
2145 context. If INHERITS is nil, means that there is no inheritance.
2146 VAR is a valid ebnf2ps symbol custom variable. See `ebnf-style-custom-list'
2147 for valid symbol variable.
2148 VALUE is a sexp which it'll be evaluated to set the value to VAR. So, don't
2149 forget to quote symbols and constant lists. See `default' style for an
2152 Don't handle this variable directly. Use functions `ebnf-insert-style' and
2153 `ebnf-merge-style'.")
2156 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2161 (defun ebnf-insert-style (name inherits
&rest values
)
2162 "Insert a new style NAME with inheritance INHERITS and values VALUES."
2164 (and (assoc name ebnf-style-database
)
2165 (error "Style name already exists: %s" name
))
2166 (or (assoc inherits ebnf-style-database
)
2167 (error "Style inheritance name does'nt exist: %s" inherits
))
2168 (setq ebnf-style-database
2169 (cons (cons name
(cons inherits
(ebnf-check-style-values values
)))
2170 ebnf-style-database
)))
2174 (defun ebnf-merge-style (name &rest values
)
2175 "Merge values of style NAME with style VALUES."
2177 (let ((style (or (assoc name ebnf-style-database
)
2178 (error "Style name does'nt exist: %s" name
)))
2179 (merge (ebnf-check-style-values values
))
2181 ;; modify value of existing variables
2182 (setq val
(nthcdr 2 style
))
2184 (setq check
(car merge
)
2186 elt
(assoc (car check
) val
))
2188 (setcdr elt
(cdr check
))
2189 (setq new
(cons check new
))))
2190 ;; insert new variables
2191 (nconc style
(nreverse new
))))
2195 (defun ebnf-apply-style (style)
2196 "Set STYLE to current style.
2198 It returns the old style symbol."
2202 (and (ebnf-apply-style1 style
)
2203 (setq ebnf-current-style style
))))
2207 (defun ebnf-reset-style (&optional style
)
2208 "Reset current style.
2210 It returns the old style symbol."
2212 (setq ebnf-stack-style nil
)
2213 (ebnf-apply-style (or style
'default
)))
2217 (defun ebnf-push-style (&optional style
)
2218 "Push the current style and set STYLE to current style.
2220 It returns the old style symbol."
2224 (setq ebnf-stack-style
(cons ebnf-current-style ebnf-stack-style
))
2226 (ebnf-apply-style style
))))
2230 (defun ebnf-pop-style ()
2231 "Pop a style and set it to current style.
2233 It returns the old style symbol."
2236 (ebnf-apply-style (car ebnf-stack-style
))
2237 (setq ebnf-stack-style
(cdr ebnf-stack-style
))))
2240 (defun ebnf-apply-style1 (style)
2241 (let ((value (cdr (assoc style ebnf-style-database
))))
2244 (and (car value
) (ebnf-apply-style1 (car value
)))
2245 (while (setq value
(cdr value
))
2246 (set (caar value
) (eval (cdar value
)))))))
2249 (defun ebnf-check-style-values (values)
2252 (and (memq (car values
) ebnf-style-custom-list
)
2253 (setq style
(cons (car values
) style
)))
2254 (setq values
(cdr values
)))
2258 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2259 ;; Internal variables
2262 (defvar ebnf-eps-buffer-name
" *EPS*")
2263 (defvar ebnf-parser-func nil
)
2264 (defvar ebnf-eps-executing nil
)
2265 (defvar ebnf-eps-upper-x
0.0)
2266 (make-variable-buffer-local 'ebnf-eps-upper-x
)
2267 (defvar ebnf-eps-upper-y
0.0)
2268 (make-variable-buffer-local 'ebnf-eps-upper-y
)
2269 (defvar ebnf-eps-prod-width
0.0)
2270 (make-variable-buffer-local 'ebnf-eps-prod-width
)
2271 (defvar ebnf-eps-max-height
0.0)
2272 (make-variable-buffer-local 'ebnf-eps-max-height
)
2273 (defvar ebnf-eps-max-width
0.0)
2274 (make-variable-buffer-local 'ebnf-eps-max-width
)
2277 (defvar ebnf-eps-context nil
2278 "List of EPS file name during parsing.
2280 See section \"Actions in Comments\" in ebnf2ps documentation.")
2283 (defvar ebnf-eps-production-list nil
2284 "Alist associating production name with EPS file name list.
2286 Each element has the following form:
2288 (PRODUCTION EPS-FILENAME...)
2290 PRODUCTION is the production name.
2291 EPS-FILENAME is the EPS file name.
2293 It's generated during parsing and used during EPS generation.
2295 See `ebnf-eps-context' and section \"Actions in Comments\" in ebnf2ps
2299 (defconst ebnf-arrow-shape-alist
2308 "Alist associating values for `ebnf-arrow-shape'.
2310 See documentation for `ebnf-arrow-shape'.")
2313 (defconst ebnf-terminal-shape-alist
2317 "Alist associating values from `ebnf-terminal-shape' to a bit vector.
2319 See documentation for `ebnf-terminal-shape', `ebnf-non-terminal-shape' and
2320 `ebnf-chart-shape'.")
2323 (defvar ebnf-limit nil
)
2324 (defvar ebnf-action nil
)
2325 (defvar ebnf-action-list nil
)
2328 (defvar ebnf-default-p nil
)
2331 (defvar ebnf-font-height-P
0)
2332 (defvar ebnf-font-height-T
0)
2333 (defvar ebnf-font-height-NT
0)
2334 (defvar ebnf-font-height-S
0)
2335 (defvar ebnf-font-height-E
0)
2336 (defvar ebnf-font-height-R
0)
2337 (defvar ebnf-font-width-P
0)
2338 (defvar ebnf-font-width-T
0)
2339 (defvar ebnf-font-width-NT
0)
2340 (defvar ebnf-font-width-S
0)
2341 (defvar ebnf-font-width-E
0)
2342 (defvar ebnf-font-width-R
0)
2343 (defvar ebnf-space-T
0)
2344 (defvar ebnf-space-NT
0)
2345 (defvar ebnf-space-S
0)
2346 (defvar ebnf-space-E
0)
2347 (defvar ebnf-space-R
0)
2350 (defvar ebnf-basic-width
0)
2351 (defvar ebnf-basic-height
0)
2352 (defvar ebnf-vertical-space
0)
2353 (defvar ebnf-horizontal-space
0)
2356 (defvar ebnf-settings nil
)
2357 (defvar ebnf-fonts-required nil
)
2360 (defconst ebnf-debug
2362 % === begin EBNF procedures to help debugging
2364 % Mark visually current point: string debug
2368 gsave -s- show grestore
2380 % Show number value: number string debug-number
2383 20 0 rmoveto show ([) show 60 string cvs show (]) show
2387 % === end EBNF procedures to help debugging
2390 "This is intended to help debugging PostScript programming.")
2393 (defconst ebnf-prologue
2395 % === begin EBNF engine
2397 % --- Basic Definitions
2400 /SpaceS FontHeight 0.5 mul def
2401 /HeightS FontHeight FontHeight add def
2404 /SpaceE FontHeight 0.5 mul def
2405 /HeightE FontHeight FontHeight add def
2408 /SpaceR FontHeight 0.5 mul def
2409 /HeightR FontHeight FontHeight add def
2412 /SpaceT FontHeight 0.5 mul def
2413 /HeightT FontHeight FontHeight add def
2416 /SpaceNT FontHeight 0.5 mul def
2417 /HeightNT FontHeight FontHeight add def
2419 /T HeightT HeightNT add 0.5 mul def
2422 /hT4 hT 0.25 mul def
2424 /Er 0.1 def % Error factor
2427 /c{currentpoint}bind def
2428 /xyi{/xi c /yi exch def def}bind def
2429 /xyo{/xo c /yo exch def def}bind def
2430 /xyp{/xp c /yp exch def def}bind def
2431 /xyt{/xt c /yt exch def def}bind def
2433 % vertical movement: x y height vm
2434 /vm{add moveto}bind def
2436 % horizontal movement: x y width hm
2437 /hm{3 -1 roll exch add exch moveto}bind def
2439 % set color: [R G B] SetRGB
2440 /SetRGB{aload pop setrgbcolor}bind def
2442 % filling gray area: gray-scale FillGray
2443 /FillGray{gsave setgray fill grestore}bind def
2445 % filling color area: [R G B] FillRGB
2446 /FillRGB{gsave SetRGB fill grestore}bind def
2448 /Stroke{LineWidth setlinewidth LineColor SetRGB stroke}bind def
2449 /StrokeShape{borderwidth setlinewidth bordercolor SetRGB stroke}bind def
2450 /Gstroke{gsave Stroke grestore}bind def
2452 % Empty Line: width EL
2453 /EL{0 rlineto Gstroke}bind def
2457 /Down{hT2 neg hT4 neg rlineto}bind def
2460 {hT2 neg hT4 rmoveto
2465 /ArrowPath{c newpath moveto Arrow closepath}bind def
2473 {hT2 neg hT4 rlineto} % 1 - semi-up
2474 {Down} % 2 - semi-down
2475 {Arrow} % 3 - simple
2476 {Gstroke ArrowPath} % 4 - transparent
2477 {Gstroke ArrowPath 1 FillGray} % 5 - hollow
2478 {Gstroke ArrowPath LineColor FillRGB} % 6 - full
2479 {Gstroke gsave UserArrow grestore} % 7 - user
2485 RA-vector ArrowShape get exec
2490 % rotation DrawArrow
2505 /LA{180 DrawArrow}def
2512 /UA{90 DrawArrow}def
2519 /DA{270 DrawArrow}def
2523 %>corner Right Descendent: height arrow corner_RD
2525 % / height > 0 | 0 - none
2527 % * ---------- | 2 - left
2546 h 0 gt{DA}{UA}ifelse
2551 [{cRD0-vector arrow get exec} % 0 - miter
2552 {0 0 0 h hT h rcurveto} % 1 - rounded
2553 {hT h rlineto} % 2 - bevel
2557 {/arrow exch def /h exch def
2558 cRD-vector ChartShape get exec
2562 %>corner Right Ascendent: height arrow corner_RA
2564 % | height > 0 | 0 - none
2566 % *- ---------- | 2 - left
2584 h 0 gt{DA}{UA}ifelse
2590 [{cRA0-vector arrow get exec} % 0 - miter
2591 {0 0 hT 0 hT h rcurveto} % 1 - rounded
2592 {hT h rlineto} % 2 - bevel
2596 {/arrow exch def /h exch def
2597 cRA-vector ChartShape get exec
2601 %>corner Left Descendent: height arrow corner_LD
2603 % \\ height > 0 | 0 - none
2605 % * ---------- | 2 - left
2614 {hT neg h rmoveto xyi
2622 {hT neg h rmoveto xyi
2624 h 0 gt{DA}{UA}ifelse
2629 [{cLD0-vector arrow get exec} % 0 - miter
2630 {0 0 0 h hT neg h rcurveto} % 1 - rounded
2631 {hT neg h rlineto} % 2 - bevel
2635 {/arrow exch def /h exch def
2636 cLD-vector ChartShape get exec
2640 %>corner Left Ascendent: height arrow corner_LA
2642 % | height > 0 | 0 - none
2644 % -* ---------- | 2 - left
2653 {hT neg h rmoveto xyi
2661 {hT neg h rmoveto xyi
2662 h 0 gt{DA}{UA}ifelse
2668 [{cLA0-vector arrow get exec} % 0 - miter
2669 {0 0 hT neg 0 hT neg h rcurveto} % 1 - rounded
2670 {hT neg h rlineto} % 2 - bevel
2674 {/arrow exch def /h exch def
2675 cLA-vector ChartShape get exec
2681 % height prepare_height |- line_height corner_height corner_height
2685 {T add hT neg}ifelse
2689 %>Left Alternative: height LAlt
2716 %>Left Loop: height LLoop
2735 %>Right Alternative: height RAlt
2749 {T neg exch rlineto}
2762 %>Right Loop: height RLoop
2781 % --- Terminal, Non-terminal and Special Basics
2783 % string width prepare-width |- string
2786 dup stringwidth pop space add space add width exch sub 0.5 mul
2790 % string width begin-right
2800 {xo width add Er add yo moveto
2805 % string width begin-left
2814 {xo width add Er add yo moveto
2827 {/half YY yy sub 0.5 mul abs def
2828 xx half add YY moveto
2829 0 0 half neg 0 half neg half neg rcurveto
2830 0 0 0 half neg half half neg rcurveto
2831 XX xx sub abs half sub half sub 0 rlineto
2832 0 0 half 0 half half rcurveto
2833 0 0 0 half half neg half rcurveto}
2835 {/quarter YY yy sub 0.25 mul abs def
2836 xx quarter add YY moveto
2837 quarter neg quarter neg rlineto
2838 0 quarter quarter add neg rlineto
2839 quarter quarter neg rlineto
2840 XX xx sub abs quarter sub quarter sub 0 rlineto
2841 quarter quarter rlineto
2842 0 quarter quarter add rlineto
2843 quarter neg quarter rlineto}
2848 ShapePath-vector shape get exec
2854 Xshadow Xshadow add Xshadow add
2855 Yshadow Yshadow add Yshadow add translate
2869 % string SBound |- string
2871 {/xx c dup /yy exch def
2872 FontHeight add /YY exch def def
2873 dup stringwidth pop xx add /XX exch def
2875 {/yy yy YShadow add def
2876 /XX XX XShadow add def
2885 /XX XX space add space add def
2886 /YY YY space add def
2887 /yy yy space sub def
2888 shadow{doShapeShadow}if
2890 space Descent abs rmoveto
2897 % TeRminal: string TR
2899 {/Effect EffectT def
2901 /shapecolor BackgroundT def
2902 /borderwidth BorderWidthT def
2903 /bordercolor BorderColorT def
2904 /foreground ForegroundT def
2909 %>Right Terminal: string width RT |- x y
2920 %>Left Terminal: string width LT |- x y
2931 %>Right Terminal Default: string width RTD |- x y
2933 {/-save- BorderWidthT def
2934 /BorderWidthT BorderWidthT DefaultWidth add def
2936 /BorderWidthT -save- def
2939 %>Left Terminal Default: string width LTD |- x y
2941 {/-save- BorderWidthT def
2942 /BorderWidthT BorderWidthT DefaultWidth add def
2944 /BorderWidthT -save- def
2949 % Non-Terminal: string NT
2951 {/Effect EffectNT def
2953 /shapecolor BackgroundNT def
2954 /borderwidth BorderWidthNT def
2955 /bordercolor BorderColorNT def
2956 /foreground ForegroundNT def
2957 /shadow ShadowNT def
2961 %>Right Non-Terminal: string width RNT |- x y
2972 %>Left Non-Terminal: string width LNT |- x y
2983 %>Right Non-Terminal Default: string width RNTD |- x y
2985 {/-save- BorderWidthNT def
2986 /BorderWidthNT BorderWidthNT DefaultWidth add def
2988 /BorderWidthNT -save- def
2991 %>Left Non-Terminal Default: string width LNTD |- x y
2993 {/-save- BorderWidthNT def
2994 /BorderWidthNT BorderWidthNT DefaultWidth add def
2996 /BorderWidthNT -save- def
3001 % SPecial: string SP
3003 {/Effect EffectS def
3005 /shapecolor BackgroundS def
3006 /borderwidth BorderWidthS def
3007 /bordercolor BorderColorS def
3008 /foreground ForegroundS def
3013 %>Right SPecial: string width RSP |- x y
3024 %>Left SPecial: string width LSP |- x y
3035 %>Right SPecial Default: string width RSPD |- x y
3037 {/-save- BorderWidthS def
3038 /BorderWidthS BorderWidthS DefaultWidth add def
3040 /BorderWidthS -save- def
3043 %>Left SPecial Default: string width LSPD |- x y
3045 {/-save- BorderWidthS def
3046 /BorderWidthS BorderWidthS DefaultWidth add def
3048 /BorderWidthS -save- def
3051 % --- Repeat and Except basics
3054 {/w width rwidth sub 0.5 mul def
3059 /xx c entry add /YY exch def def
3060 /yy YY height sub def
3061 /XX xx rwidth add def
3062 shadow{doShapeShadow}if
3085 % entry height width rwidth begin-repeat
3095 /shapecolor BackgroundR def
3096 /borderwidth BorderWidthR def
3097 /bordercolor BorderColorR def
3098 /foreground ForegroundR def
3103 % string end-repeat |- x y
3106 space Descent rmoveto
3110 exch space add exch moveto
3114 %>Right RePeat: string entry height width rwidth RRP |- x y
3115 /RRP{begin-repeat right-direction end-repeat}def
3117 %>Left RePeat: string entry height width rwidth LRP |- x y
3118 /LRP{begin-repeat left-direction end-repeat}def
3122 % entry height width rwidth begin-except
3132 /shapecolor BackgroundE def
3133 /borderwidth BorderWidthE def
3134 /bordercolor BorderColorE def
3135 /foreground ForegroundE def
3140 % x-width end-except |- x y
3143 space space add add Descent rmoveto
3144 (-) foreground SetRGB S
3150 %>Right EXcept: x-width entry height width rwidth REX |- x y
3151 /REX{begin-except right-direction end-except}def
3153 %>Left EXcept: x-width entry height width rwidth LEX |- x y
3154 /LEX{begin-except left-direction end-except}def
3158 %>Beginning Of Sequence: BOS |- x y
3159 /BOS{currentpoint}bind def
3161 %>End Of Sequence: x y x1 y1 EOS |- x y
3162 /EOS{pop pop}bind def
3166 %>Beginning Of Production: string width height BOP |- y x
3169 neg yp add /yw exch def
3170 xp add T sub /xw exch def
3172 /fP F ForegroundP SetRGB BackgroundP aload pop true BG S
3182 %>End Of Production: y x delta EOP
3183 /EOPH{add exch moveto}bind def % horizontal
3184 /EOPV{exch pop sub 0 exch moveto}bind def % vertical
3186 % --- Empty Alternative
3188 %>Empty Alternative: width EA |- x y
3199 %>AlTernative: h1 h2 ... hn n width AT |- x y
3201 {xyo xo add /xw exch def
3213 %>OPtional: height width OP |- x y
3230 %>One or More: height width OM |- x y
3244 %>Zero or More: h2 h1 width ZM |- x y
3254 yo add xo T add exch moveto
3258 % === end EBNF engine
3261 "EBNF PostScript prologue")
3264 (defconst ebnf-eps-prologue
3266 /#ebnf2ps#dict 230 dict def
3269 % Initiliaze variables to avoid name-conflicting with document variables.
3270 % This is the case when using `bind' operator.
3271 /-fillp- 0 def /h 0 def
3272 /-ox- 0 def /half 0 def
3273 /-oy- 0 def /height 0 def
3274 /-save- 0 def /ow 0 def
3275 /Ascent 0 def /quarter 0 def
3276 /Descent 0 def /rXX 0 def
3277 /Effect 0 def /rYY 0 def
3278 /FontHeight 0 def /rwidth 0 def
3279 /LineThickness 0 def /rxx 0 def
3280 /OverlinePosition 0 def /ryy 0 def
3281 /SpaceBackground 0 def /shadow 0 def
3282 /StrikeoutPosition 0 def /shape 0 def
3283 /UnderlinePosition 0 def /shapecolor 0 def
3284 /XBox 0 def /space 0 def
3285 /XX 0 def /st 1 string def
3286 /Xshadow 0 def /w 0 def
3287 /YBox 0 def /width 0 def
3289 /Yshadow 0 def /xo 0 def
3290 /arrow 0 def /xp 0 def
3291 /bg false def /xt 0 def
3292 /bgcolor 0 def /xw 0 def
3293 /bordercolor 0 def /xx 0 def
3294 /borderwidth 0 def /yi 0 def
3296 /entry 0 def /yp 0 def
3297 /foreground 0 def /yt 0 def
3301 % ISOLatin1Encoding stolen from ps_init.ps in GhostScript 2.6.1.4:
3302 /ISOLatin1Encoding where
3304 {% -- The ISO Latin-1 encoding vector isn't known, so define it.
3305 % -- The first half is the same as the standard encoding,
3306 % -- except for minus instead of hyphen at code 055.
3308 StandardEncoding 0 45 getinterval aload pop
3310 StandardEncoding 46 82 getinterval aload pop
3311 %*** NOTE: the following are missing in the Adobe documentation,
3312 %*** but appear in the displayed table:
3313 %*** macron at 0225, dieresis at 0230, cedilla at 0233, space at 0240.
3315 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
3316 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
3317 /dotlessi /grave /acute /circumflex /tilde /macron /breve /dotaccent
3318 /dieresis /.notdef /ring /cedilla /.notdef /hungarumlaut /ogonek /caron
3320 /space /exclamdown /cent /sterling
3321 /currency /yen /brokenbar /section
3322 /dieresis /copyright /ordfeminine /guillemotleft
3323 /logicalnot /hyphen /registered /macron
3324 /degree /plusminus /twosuperior /threesuperior
3325 /acute /mu /paragraph /periodcentered
3326 /cedilla /onesuperior /ordmasculine /guillemotright
3327 /onequarter /onehalf /threequarters /questiondown
3329 /Agrave /Aacute /Acircumflex /Atilde
3330 /Adieresis /Aring /AE /Ccedilla
3331 /Egrave /Eacute /Ecircumflex /Edieresis
3332 /Igrave /Iacute /Icircumflex /Idieresis
3333 /Eth /Ntilde /Ograve /Oacute
3334 /Ocircumflex /Otilde /Odieresis /multiply
3335 /Oslash /Ugrave /Uacute /Ucircumflex
3336 /Udieresis /Yacute /Thorn /germandbls
3338 /agrave /aacute /acircumflex /atilde
3339 /adieresis /aring /ae /ccedilla
3340 /egrave /eacute /ecircumflex /edieresis
3341 /igrave /iacute /icircumflex /idieresis
3342 /eth /ntilde /ograve /oacute
3343 /ocircumflex /otilde /odieresis /divide
3344 /oslash /ugrave /uacute /ucircumflex
3345 /udieresis /yacute /thorn /ydieresis
3349 /reencodeFontISO %def
3351 length 12 add dict % Make a new font (a new dict the same size
3352 % as the old one) with room for our new symbols.
3354 begin % Make the new font the current dictionary.
3356 {def}{pop pop}ifelse
3357 }forall % Copy each of the symbols from the old dictionary
3358 % to the new one except for the font ID.
3360 currentdict /FontType get 0 ne
3361 {/Encoding ISOLatin1Encoding def}if % Override the encoding with
3362 % the ISOLatin1 encoding.
3364 % Use the font's bounding box to determine the ascent, descent,
3365 % and overall height; don't forget that these values have to be
3366 % transformed using the font's matrix.
3373 % | | | | Ascent (usually > 0)
3375 % (0 0) -> +--+----+-------->
3377 % | | v Descent (usually < 0)
3378 % (x1 y1) --> +----+ - -
3380 currentdict /FontType get 0 ne
3381 {/FontBBox load aload pop % -- x1 y1 x2 y2
3382 FontMatrix transform /Ascent exch def pop
3383 FontMatrix transform /Descent exch def pop}
3384 {/PrimaryFont FDepVector 0 get def
3385 PrimaryFont /FontBBox get aload pop
3386 PrimaryFont /FontMatrix get transform /Ascent exch def pop
3387 PrimaryFont /FontMatrix get transform /Descent exch def pop
3390 /FontHeight Ascent Descent sub def % use `sub' because descent < 0
3392 % Define these in case they're not in the FontInfo
3393 % (also, here they're easier to get to).
3394 /UnderlinePosition Descent 0.70 mul def
3395 /OverlinePosition Descent UnderlinePosition sub Ascent add def
3396 /StrikeoutPosition Ascent 0.30 mul def
3397 /LineThickness FontHeight 0.05 mul def
3398 /Xshadow FontHeight 0.08 mul def
3399 /Yshadow FontHeight -0.09 mul def
3400 /SpaceBackground Descent neg UnderlinePosition add def
3401 /XBox Descent neg def
3402 /YBox LineThickness 0.7 mul def
3404 currentdict % Leave the new font on the stack
3405 end % Stop using the font as the current dictionary
3406 definefont % Put the font into the font dictionary
3407 pop % Discard the returned font
3411 /DefFont{findfont exch scalefont reencodeFontISO}def
3416 dup /Ascent get /Ascent exch def
3417 dup /Descent get /Descent exch def
3418 dup /FontHeight get /FontHeight exch def
3419 dup /UnderlinePosition get /UnderlinePosition exch def
3420 dup /OverlinePosition get /OverlinePosition exch def
3421 dup /StrikeoutPosition get /StrikeoutPosition exch def
3422 dup /LineThickness get /LineThickness exch def
3423 dup /Xshadow get /Xshadow exch def
3424 dup /Yshadow get /Yshadow exch def
3425 dup /SpaceBackground get /SpaceBackground exch def
3426 dup /XBox get /XBox exch def
3427 dup /YBox get /YBox exch def
3440 /FillBgColor{bgcolor aload pop setrgbcolor fill}bind def
3442 % stack: fill-or-not lower-x lower-y upper-x upper-y |- --
3455 % top of stack: fill-or-not
3457 {LineThickness setlinewidth stroke}
3462 % stack: string fill-or-not |- --
3465 /-ox- currentpoint /-oy- exch def def
3467 LineThickness setlinewidth
3469 st dup true charpath
3470 -fillp- {gsave FillBgColor grestore}if
3472 -oy- add /-oy- exch def
3473 -ox- add /-ox- exch def
3480 % stack: fill-or-not delta |- --
3483 xx XBox sub dd sub yy YBox sub dd sub
3484 XX XBox add dd add YY YBox add dd add
3488 % stack: string |- --
3491 Xshadow Yshadow rmoveto
3496 % stack: position |- --
3498 {currentpoint exch pop add dup
3504 LineThickness setlinewidth stroke
3508 % stack: string |- --
3509 % effect: 1 - underline 2 - strikeout 4 - overline
3510 % 8 - shadow 16 - box 32 - outline
3512 {/xx currentpoint dup Descent add /yy exch def
3513 Ascent add /YY exch def def
3514 dup stringwidth pop xx add /XX exch def
3516 {/yy yy Yshadow add def
3517 /XX XX Xshadow add def
3522 {SpaceBackground doBox}
3523 {xx yy XX YY doRect}
3526 Effect 16 and 0 ne{false 0 doBox}if % box
3527 Effect 8 and 0 ne{dup doShadow}if % shadow
3529 {true doOutline} % outline
3530 {show} % normal text
3532 Effect 1 and 0 ne{UnderlinePosition Hline}if % underline
3533 Effect 2 and 0 ne{StrikeoutPosition Hline}if % strikeout
3534 Effect 4 and 0 ne{OverlinePosition Hline}if % overline
3538 "EBNF EPS prologue")
3541 (defconst ebnf-eps-begin
3545 % x y #ebnf2ps#begin
3547 {#ebnf2ps#dict begin /#ebnf2ps#save save def
3548 moveto false BG 0.0 0.0 0.0 setrgbcolor}def
3550 /#ebnf2ps#end{showpage #ebnf2ps#save restore end}def
3557 (defconst ebnf-eps-end
3564 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3568 (defvar ebnf-format-float
"%1.3f")
3571 (defun ebnf-format-float (&rest floats
)
3574 (format ebnf-format-float float
))
3579 (defun ebnf-format-color (format-str color default
)
3580 (let* ((the-color (or color default
))
3581 (rgb (ps-color-scale the-color
)))
3584 (ebnf-format-float (nth 0 rgb
) (nth 1 rgb
) (nth 2 rgb
))
3589 (defvar ebnf-message-float
"%3.2f")
3592 (defsubst ebnf-message-float
(format-str value
)
3594 (format ebnf-message-float value
)))
3597 (defsubst ebnf-message-info
(messag)
3598 (message "%s...%3d%%"
3600 (round (/ (* (setq ebnf-nprod
(1+ ebnf-nprod
)) 100.0) ebnf-total
))))
3603 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3607 (defmacro ebnf-node-kind
(vec &optional value
)
3609 `(aset ,vec
0 ,value
)
3613 (defmacro ebnf-node-width-func
(node width
)
3614 `(funcall (aref ,node
1) ,node
,width
))
3617 (defmacro ebnf-node-dimension-func
(node &optional value
)
3619 `(aset ,node
2 ,value
)
3620 `(funcall (aref ,node
2) ,node
)))
3623 (defmacro ebnf-node-entry
(vec &optional value
)
3625 `(aset ,vec
3 ,value
)
3629 (defmacro ebnf-node-height
(vec &optional value
)
3631 `(aset ,vec
4 ,value
)
3635 (defmacro ebnf-node-width
(vec &optional value
)
3637 `(aset ,vec
5 ,value
)
3641 (defmacro ebnf-node-name
(vec)
3645 (defmacro ebnf-node-list
(vec &optional value
)
3647 `(aset ,vec
6 ,value
)
3651 (defmacro ebnf-node-default
(vec)
3655 (defmacro ebnf-node-production
(vec &optional value
)
3657 `(aset ,vec
7 ,value
)
3661 (defmacro ebnf-node-separator
(vec &optional value
)
3663 `(aset ,vec
7 ,value
)
3667 (defmacro ebnf-node-action
(vec &optional value
)
3669 `(aset ,vec
8 ,value
)
3673 (defmacro ebnf-node-generation
(node)
3674 `(funcall (ebnf-node-kind ,node
) ,node
))
3677 (defmacro ebnf-max-width
(prod)
3678 `(max (ebnf-node-width ,prod
)
3679 (+ (* (length (ebnf-node-name ,prod
))
3681 ebnf-production-horizontal-space
)))
3684 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3685 ;; PostScript generation
3688 (defun ebnf-generate-eps (ebnf-tree)
3689 (let* ((ps-color-p (and ebnf-color-p
(ps-color-device)))
3690 (ps-print-color-scale (if ps-color-p
3691 (float (car (ps-color-values "white")))
3693 (ebnf-total (length ebnf-tree
))
3695 (old-ps-output (symbol-function 'ps-output
))
3696 (old-ps-output-string (symbol-function 'ps-output-string
))
3697 (eps-buffer (get-buffer-create ebnf-eps-buffer-name
))
3698 ebnf-debug-ps error-msg horizontal
3699 prod prod-name prod-width prod-height prod-list file-list
)
3700 ;; redefines `ps-output' and `ps-output-string'
3701 (defalias 'ps-output
'ebnf-eps-output
)
3702 (defalias 'ps-output-string
'ps-output-string-prim
)
3703 ;; generate EPS file
3705 (condition-case data
3708 (setq prod
(car ebnf-tree
)
3709 prod-name
(ebnf-node-name prod
)
3710 prod-width
(ebnf-max-width prod
)
3711 prod-height
(ebnf-node-height prod
)
3712 horizontal
(memq (ebnf-node-action prod
)
3714 ;; generate production in EPS buffer
3716 (set-buffer eps-buffer
)
3717 (setq ebnf-eps-upper-x
0.0
3718 ebnf-eps-upper-y
0.0
3719 ebnf-eps-max-width prod-width
3720 ebnf-eps-max-height prod-height
)
3721 (ebnf-generate-production prod
))
3722 (if (setq prod-list
(cdr (assoc prod-name
3723 ebnf-eps-production-list
)))
3724 ;; insert EPS buffer in all buffer associated with production
3725 (ebnf-eps-production-list prod-list
'file-list horizontal
3726 prod-width prod-height eps-buffer
)
3727 ;; write EPS file for production
3728 (ebnf-eps-finish-and-write eps-buffer
3729 (ebnf-eps-filename prod-name
)))
3730 ;; prepare for next loop
3732 (set-buffer eps-buffer
)
3734 (setq ebnf-tree
(cdr ebnf-tree
)))
3735 ;; write and kill temporary buffers
3736 (ebnf-eps-write-kill-temp file-list t
)
3737 (setq file-list nil
))
3740 (setq error-msg
(error-message-string data
)))))
3741 ;; restore `ps-output' and `ps-output-string'
3742 (defalias 'ps-output old-ps-output
)
3743 (defalias 'ps-output-string old-ps-output-string
)
3744 ;; kill temporary buffers
3745 (kill-buffer eps-buffer
)
3746 (ebnf-eps-write-kill-temp file-list nil
)
3747 (and error-msg
(error error-msg
))
3751 ;; write and kill temporary buffers
3752 (defun ebnf-eps-write-kill-temp (file-list write-p
)
3754 (let ((buffer (get-buffer (concat " *" (car file-list
) "*"))))
3757 (ebnf-eps-finish-and-write buffer
(car file-list
)))
3758 (kill-buffer buffer
)))
3759 (setq file-list
(cdr file-list
))))
3762 ;; insert EPS buffer in all buffer associated with production
3763 (defun ebnf-eps-production-list (prod-list file-list-sym horizontal
3764 prod-width prod-height eps-buffer
)
3766 (add-to-list file-list-sym
(car prod-list
))
3768 (set-buffer (get-buffer-create (concat " *" (car prod-list
) "*")))
3769 (goto-char (point-max))
3772 ((zerop (buffer-size))
3773 (setq ebnf-eps-upper-x
0.0
3774 ebnf-eps-upper-y
0.0
3775 ebnf-eps-max-width prod-width
3776 ebnf-eps-max-height prod-height
))
3779 (ebnf-eop-horizontal ebnf-eps-prod-width
)
3780 (setq ebnf-eps-max-width
(+ ebnf-eps-max-width
3781 ebnf-production-horizontal-space
3783 ebnf-eps-max-height
(max ebnf-eps-max-height prod-height
)))
3786 (ebnf-eop-vertical ebnf-eps-max-height
)
3787 (setq ebnf-eps-upper-x
(max ebnf-eps-upper-x ebnf-eps-max-width
)
3788 ebnf-eps-upper-y
(if (zerop ebnf-eps-upper-y
)
3791 ebnf-production-vertical-space
3792 ebnf-eps-max-height
))
3793 ebnf-eps-max-width prod-width
3794 ebnf-eps-max-height prod-height
))
3796 (setq ebnf-eps-prod-width prod-width
)
3797 (insert-buffer eps-buffer
))
3798 (setq prod-list
(cdr prod-list
))))
3801 (defun ebnf-generate (ebnf-tree)
3802 (let* ((ps-color-p (and ebnf-color-p
(ps-color-device)))
3803 (ps-print-color-scale (if ps-color-p
3804 (float (car (ps-color-values "white")))
3806 ps-zebra-stripes ps-line-number ps-razzle-dazzle
3808 ps-print-begin-sheet-hook
3809 ps-print-begin-page-hook
3810 ps-print-begin-column-hook
)
3811 (ps-generate (current-buffer) (point-min) (point-max)
3812 'ebnf-generate-postscript
)))
3815 (defvar ebnf-tree nil
)
3816 (defvar ebnf-direction
"R")
3817 (defvar ebnf-total
0)
3818 (defvar ebnf-nprod
0)
3821 (defun ebnf-generate-postscript (from to
)
3823 (if ebnf-horizontal-max-height
3824 (ebnf-generate-with-max-height)
3825 (ebnf-generate-without-max-height))
3829 (defun ebnf-generate-with-max-height ()
3830 (let ((ebnf-total (length ebnf-tree
))
3832 next-line max-height prod the-width
)
3834 ;; find next line point
3835 (setq next-line ebnf-tree
3836 prod
(car ebnf-tree
)
3837 max-height
(ebnf-node-height prod
))
3838 (ebnf-begin-line prod
(ebnf-max-width prod
))
3839 (while (and (setq next-line
(cdr next-line
))
3840 (setq prod
(car next-line
))
3841 (memq (ebnf-node-action prod
) ebnf-action-list
)
3842 (setq the-width
(ebnf-max-width prod
))
3843 (<= the-width ps-width-remaining
))
3844 (setq max-height
(max max-height
(ebnf-node-height prod
))
3845 ps-width-remaining
(- ps-width-remaining
3847 ebnf-production-horizontal-space
))))
3848 ;; generate current line
3849 (ebnf-newline max-height
)
3850 (setq prod
(car ebnf-tree
))
3851 (ebnf-generate-production prod
)
3852 (while (not (eq (setq ebnf-tree
(cdr ebnf-tree
)) next-line
))
3853 (ebnf-eop-horizontal (ebnf-max-width prod
))
3854 (setq prod
(car ebnf-tree
))
3855 (ebnf-generate-production prod
))
3856 (ebnf-eop-vertical max-height
))))
3859 (defun ebnf-generate-without-max-height ()
3860 (let ((ebnf-total (length ebnf-tree
))
3862 max-height prod bef-width cur-width
)
3864 ;; generate current line
3865 (setq prod
(car ebnf-tree
)
3866 max-height
(ebnf-node-height prod
)
3867 bef-width
(ebnf-max-width prod
))
3868 (ebnf-begin-line prod bef-width
)
3869 (ebnf-generate-production prod
)
3870 (while (and (setq ebnf-tree
(cdr ebnf-tree
))
3871 (setq prod
(car ebnf-tree
))
3872 (memq (ebnf-node-action prod
) ebnf-action-list
)
3873 (setq cur-width
(ebnf-max-width prod
))
3874 (<= cur-width ps-width-remaining
)
3875 (<= (ebnf-node-height prod
) ps-height-remaining
))
3876 (ebnf-eop-horizontal bef-width
)
3877 (ebnf-generate-production prod
)
3878 (setq bef-width cur-width
3879 max-height
(max max-height
(ebnf-node-height prod
))
3880 ps-width-remaining
(- ps-width-remaining
3882 ebnf-production-horizontal-space
))))
3883 (ebnf-eop-vertical max-height
)
3884 ;; prepare next line
3885 (ebnf-newline max-height
))))
3888 (defun ebnf-begin-line (prod width
)
3889 (and (or (eq (ebnf-node-action prod
) 'form-feed
)
3890 (> (ebnf-node-height prod
) ps-height-remaining
))
3892 (setq ps-width-remaining
(- ps-width-remaining
3894 ebnf-production-horizontal-space
))))
3897 (defun ebnf-newline (height)
3898 (and (> height ps-height-remaining
)
3900 (setq ps-width-remaining ps-print-width
3901 ps-height-remaining
(- ps-height-remaining
3903 ebnf-production-vertical-space
))))
3906 ;; [production width-fun dim-fun entry height width name production action]
3907 (defun ebnf-generate-production (production)
3908 (ebnf-message-info "Generating")
3909 (run-hooks 'ebnf-production-hook
)
3910 (ps-output-string (ebnf-node-name production
))
3913 (ebnf-node-width production
)
3914 (+ ebnf-basic-height
3915 (ebnf-node-entry (ebnf-node-production production
))))
3917 (ebnf-node-generation (ebnf-node-production production
))
3918 (ps-output "EOS\n"))
3921 ;; [alternative width-fun dim-fun entry height width list]
3922 (defun ebnf-generate-alternative (alternative)
3923 (let ((alt (ebnf-node-list alternative
))
3924 (entry (ebnf-node-entry alternative
))
3926 alt-height alt-entry
)
3928 (ps-output (ebnf-format-float (- entry
(ebnf-node-entry (car alt
))))
3930 (setq entry
(- entry
(ebnf-node-height (car alt
)) ebnf-vertical-space
)
3933 (ps-output (format "%d " nlist
)
3934 (ebnf-format-float (ebnf-node-width alternative
))
3936 (setq alt
(ebnf-node-list alternative
))
3938 (ebnf-node-generation (car alt
))
3939 (setq alt-height
(- (ebnf-node-height (car alt
))
3940 (ebnf-node-entry (car alt
)))))
3941 (while (setq alt
(cdr alt
))
3942 (setq alt-entry
(ebnf-node-entry (car alt
)))
3943 (ebnf-vertical-movement
3944 (- (+ alt-height ebnf-vertical-space alt-entry
)))
3945 (ebnf-node-generation (car alt
))
3946 (setq alt-height
(- (ebnf-node-height (car alt
)) alt-entry
))))
3947 (ps-output "EOS\n"))
3950 ;; [sequence width-fun dim-fun entry height width list]
3951 (defun ebnf-generate-sequence (sequence)
3953 (let ((seq (ebnf-node-list sequence
))
3956 (ebnf-node-generation (car seq
))
3957 (setq seq-width
(ebnf-node-width (car seq
))))
3958 (while (setq seq
(cdr seq
))
3959 (ebnf-horizontal-movement seq-width
)
3960 (ebnf-node-generation (car seq
))
3961 (setq seq-width
(ebnf-node-width (car seq
)))))
3962 (ps-output "EOS\n"))
3965 ;; [terminal width-fun dim-fun entry height width name]
3966 (defun ebnf-generate-terminal (terminal)
3967 (ebnf-gen-terminal terminal
"T"))
3970 ;; [non-terminal width-fun dim-fun entry height width name]
3971 (defun ebnf-generate-non-terminal (non-terminal)
3972 (ebnf-gen-terminal non-terminal
"NT"))
3975 ;; [empty width-fun dim-fun entry height width]
3976 (defun ebnf-generate-empty (empty)
3977 (ebnf-empty-alternative (ebnf-node-width empty
)))
3980 ;; [optional width-fun dim-fun entry height width element]
3981 (defun ebnf-generate-optional (optional)
3982 (let ((the-optional (ebnf-node-list optional
)))
3983 (ps-output (ebnf-format-float
3984 (+ (- (ebnf-node-height the-optional
)
3985 (ebnf-node-entry optional
))
3986 ebnf-vertical-space
)
3987 (ebnf-node-width optional
))
3989 (ebnf-node-generation the-optional
)
3990 (ps-output "EOS\n")))
3993 ;; [one-or-more width-fun dim-fun entry height width element separator]
3994 (defun ebnf-generate-one-or-more (one-or-more)
3995 (let* ((width (ebnf-node-width one-or-more
))
3996 (sep (ebnf-node-separator one-or-more
))
3997 (entry (- (ebnf-node-entry one-or-more
)
3999 (ebnf-node-entry sep
)
4001 (ps-output (ebnf-format-float entry width
)
4003 (ebnf-node-generation (ebnf-node-list one-or-more
))
4004 (ebnf-vertical-movement entry
)
4006 (let ((ebnf-direction "L"))
4007 (ebnf-node-generation sep
))
4008 (ebnf-empty-alternative (- width ebnf-horizontal-space
))))
4009 (ps-output "EOS\n"))
4012 ;; [zero-or-more width-fun dim-fun entry height width element separator]
4013 (defun ebnf-generate-zero-or-more (zero-or-more)
4014 (let* ((width (ebnf-node-width zero-or-more
))
4015 (node-list (ebnf-node-list zero-or-more
))
4016 (list-entry (ebnf-node-entry node-list
))
4017 (node-sep (ebnf-node-separator zero-or-more
))
4018 (entry (+ list-entry
4021 (- (ebnf-node-height node-sep
)
4022 (ebnf-node-entry node-sep
))
4024 (ps-output (ebnf-format-float entry
4025 (+ (- (ebnf-node-height node-list
)
4027 ebnf-vertical-space
)
4030 (ebnf-node-generation (ebnf-node-list zero-or-more
))
4031 (ebnf-vertical-movement entry
)
4032 (if (ebnf-node-separator zero-or-more
)
4033 (let ((ebnf-direction "L"))
4034 (ebnf-node-generation (ebnf-node-separator zero-or-more
)))
4035 (ebnf-empty-alternative (- width ebnf-horizontal-space
))))
4036 (ps-output "EOS\n"))
4039 ;; [special width-fun dim-fun entry height width name]
4040 (defun ebnf-generate-special (special)
4041 (ebnf-gen-terminal special
"SP"))
4044 ;; [repeat width-fun dim-fun entry height width times element]
4045 (defun ebnf-generate-repeat (repeat)
4046 (let ((times (ebnf-node-name repeat
))
4047 (element (ebnf-node-separator repeat
)))
4048 (ps-output-string times
)
4051 (ebnf-node-entry repeat
)
4052 (ebnf-node-height repeat
)
4053 (ebnf-node-width repeat
)
4055 (+ (ebnf-node-width element
)
4056 ebnf-space-R ebnf-space-R ebnf-space-R
4057 (* (length times
) ebnf-font-width-R
))
4059 " " ebnf-direction
"RP\n")
4061 (ebnf-node-generation element
)))
4062 (ps-output "EOS\n"))
4065 ;; [except width-fun dim-fun entry height width element element]
4066 (defun ebnf-generate-except (except)
4067 (let* ((element (ebnf-node-list except
))
4068 (exception (ebnf-node-separator except
))
4069 (width (ebnf-node-width element
)))
4070 (ps-output (ebnf-format-float
4072 (ebnf-node-entry except
)
4073 (ebnf-node-height except
)
4074 (ebnf-node-width except
)
4076 ebnf-space-E ebnf-space-E ebnf-space-E
4079 (+ (ebnf-node-width exception
) ebnf-space-E
)
4081 " " ebnf-direction
"EX\n")
4082 (ebnf-node-generation (ebnf-node-list except
))
4084 (ebnf-horizontal-movement (+ width ebnf-space-E
4085 ebnf-font-width-E ebnf-space-E
))
4086 (ebnf-node-generation exception
)))
4087 (ps-output "EOS\n"))
4090 (defun ebnf-gen-terminal (node code
)
4091 (ps-output-string (ebnf-node-name node
))
4092 (ps-output " " (ebnf-format-float (ebnf-node-width node
))
4093 " " ebnf-direction code
4094 (if (ebnf-node-default node
)
4099 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4100 ;; Internal functions
4103 ;; function `ebnf-range-regexp' is used to avoid a bug of `skip-chars-forward'
4104 ;; on version 20.4.1, that is, it doesn't accept ranges like "\240-\377" (or
4105 ;; "\177-\237"), but it accepts the character sequence from \240 to \377 (or
4106 ;; from \177 to \237). It seems that version 20.7 has the same problem.
4107 (defun ebnf-range-regexp (prefix from to
)
4110 (setq str
(concat str
(char-to-string from
))
4112 (concat prefix str
)))
4115 (defvar ebnf-map-name
4116 (let ((map (make-vector 256 ?\_
)))
4117 (mapcar #'(lambda (char)
4118 (aset map char char
))
4119 (concat "#$%&+-.0123456789=?@~"
4120 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
4121 "abcdefghijklmnopqrstuvwxyz"))
4125 (defun ebnf-eps-filename (str)
4126 (let* ((len (length str
))
4128 (new (make-string len ?\
)))
4130 (aset new stri
(aref ebnf-map-name
(aref str stri
)))
4131 (setq stri
(1+ stri
)))
4132 (concat ebnf-eps-prefix new
".eps")))
4135 (defun ebnf-eps-output (&rest args
)
4138 (setq args
(cdr args
))))
4141 (defun ebnf-generate-region (from to gen-func
)
4142 (run-hooks 'ebnf-hook
)
4143 (let ((ebnf-limit (max from to
))
4148 (condition-case data
4149 (let ((tree (ebnf-parse-and-sort (min from to
))))
4154 (ebnf-eliminate-empty-rules tree
))))))
4158 (setq the-point
(max (1- (point)) (point-min)))
4159 (message (error-message-string data
)))))))
4162 (goto-char the-point
))
4166 (message "EBNF syntatic analysis: NO ERRORS.")))))
4169 (defun ebnf-parse-and-sort (start)
4171 (let ((tree (funcall ebnf-parser-func start
)))
4172 (if ebnf-sort-production
4174 (message "Sorting...")
4176 (if (eq ebnf-sort-production
'ascending
)
4177 'ebnf-sorter-ascending
4178 'ebnf-sorter-descending
)))
4182 (defun ebnf-sorter-ascending (first second
)
4183 (string< (ebnf-node-name first
)
4184 (ebnf-node-name second
)))
4187 (defun ebnf-sorter-descending (first second
)
4188 (string< (ebnf-node-name second
)
4189 (ebnf-node-name first
)))
4192 (defun ebnf-empty-alternative (width)
4193 (ps-output (ebnf-format-float width
) " EA\n"))
4196 (defun ebnf-vertical-movement (height)
4197 (ps-output (ebnf-format-float height
) " vm\n"))
4200 (defun ebnf-horizontal-movement (width)
4201 (ps-output (ebnf-format-float width
) " hm\n"))
4204 (defun ebnf-entry (height)
4205 (* height ebnf-entry-percentage
))
4208 (defun ebnf-eop-vertical (height)
4209 (ps-output (ebnf-format-float (+ height ebnf-production-vertical-space
))
4213 (defun ebnf-eop-horizontal (width)
4214 (ps-output (ebnf-format-float (+ width ebnf-production-horizontal-space
))
4218 (defun ebnf-new-page ()
4219 (when (< ps-height-remaining ps-print-height
)
4220 (run-hooks 'ebnf-page-hook
)
4225 (defsubst ebnf-font-size
(font) (nth 0 font
))
4226 (defsubst ebnf-font-name
(font) (nth 1 font
))
4227 (defsubst ebnf-font-foreground
(font) (nth 2 font
))
4228 (defsubst ebnf-font-background
(font) (nth 3 font
))
4229 (defsubst ebnf-font-list
(font) (nthcdr 4 font
))
4230 (defsubst ebnf-font-attributes
(font)
4231 (lsh (ps-extension-bit (cdr font
)) -
2))
4234 (defconst ebnf-font-name-select
4235 (vector 'normal
'bold
'italic
'bold-italic
))
4238 (defun ebnf-font-name-select (font)
4239 (let* ((font-list (ebnf-font-list font
))
4240 (font-index (+ (if (memq 'bold font-list
) 1 0)
4241 (if (memq 'italic font-list
) 2 0)))
4242 (name (ebnf-font-name font
))
4243 (database (cdr (assoc name ps-font-info-database
)))
4244 (info-list (or (cdr (assoc 'fonts database
))
4245 (error "Invalid font: %s" name
))))
4246 (or (cdr (assoc (aref ebnf-font-name-select font-index
)
4248 (error "Invalid attributes for font %s" name
))))
4251 (defun ebnf-font-select (font select
)
4252 (let* ((name (ebnf-font-name font
))
4253 (database (cdr (assoc name ps-font-info-database
)))
4254 (size (cdr (assoc 'size database
)))
4255 (base (cdr (assoc select database
))))
4257 (/ (* (ebnf-font-size font
) base
)
4259 (error "Invalid font: %s" name
))))
4262 (defsubst ebnf-font-width
(font)
4263 (ebnf-font-select font
'avg-char-width
))
4264 (defsubst ebnf-font-height
(font)
4265 (ebnf-font-select font
'line-height
))
4268 (defun ebnf-begin-job ()
4269 (ps-printing-region nil nil
)
4270 (if ebnf-use-float-format
4271 (setq ebnf-format-float
"%1.3f"
4272 ebnf-message-float
"%3.2f")
4273 (setq ebnf-format-float
"%s"
4274 ebnf-message-float
"%s"))
4275 (ebnf-otz-initialize)
4276 ;; to avoid compilation gripes when calling autoloaded functions
4277 (funcall (cond ((eq ebnf-syntax
'iso-ebnf
)
4278 (setq ebnf-parser-func
'ebnf-iso-parser
)
4279 'ebnf-iso-initialize
)
4280 ((eq ebnf-syntax
'yacc
)
4281 (setq ebnf-parser-func
'ebnf-yac-parser
)
4282 'ebnf-yac-initialize
)
4284 (setq ebnf-parser-func
'ebnf-bnf-parser
)
4285 'ebnf-bnf-initialize
)))
4286 (and ebnf-terminal-regexp
; ensures that it's a string or nil
4287 (not (stringp ebnf-terminal-regexp
))
4288 (setq ebnf-terminal-regexp nil
))
4289 (or (and ebnf-eps-prefix
; ensures that it's a string
4290 (stringp ebnf-eps-prefix
))
4291 (setq ebnf-eps-prefix
"ebnf--"))
4292 (setq ebnf-entry-percentage
; ensures value between 0.0 and 1.0
4293 (min (max ebnf-entry-percentage
0.0) 1.0)
4294 ebnf-action-list
(if ebnf-horizontal-orientation
4298 ebnf-fonts-required nil
4301 ebnf-eps-context nil
4302 ebnf-eps-production-list nil
4303 ebnf-eps-upper-x
0.0
4304 ebnf-eps-upper-y
0.0
4305 ebnf-font-height-P
(ebnf-font-height ebnf-production-font
)
4306 ebnf-font-height-T
(ebnf-font-height ebnf-terminal-font
)
4307 ebnf-font-height-NT
(ebnf-font-height ebnf-non-terminal-font
)
4308 ebnf-font-height-S
(ebnf-font-height ebnf-special-font
)
4309 ebnf-font-height-E
(ebnf-font-height ebnf-except-font
)
4310 ebnf-font-height-R
(ebnf-font-height ebnf-repeat-font
)
4311 ebnf-font-width-P
(ebnf-font-width ebnf-production-font
)
4312 ebnf-font-width-T
(ebnf-font-width ebnf-terminal-font
)
4313 ebnf-font-width-NT
(ebnf-font-width ebnf-non-terminal-font
)
4314 ebnf-font-width-S
(ebnf-font-width ebnf-special-font
)
4315 ebnf-font-width-E
(ebnf-font-width ebnf-except-font
)
4316 ebnf-font-width-R
(ebnf-font-width ebnf-repeat-font
)
4317 ebnf-space-T
(* ebnf-font-height-T
0.5)
4318 ebnf-space-NT
(* ebnf-font-height-NT
0.5)
4319 ebnf-space-S
(* ebnf-font-height-S
0.5)
4320 ebnf-space-E
(* ebnf-font-height-E
0.5)
4321 ebnf-space-R
(* ebnf-font-height-R
0.5))
4322 (let ((basic (+ ebnf-font-height-T ebnf-font-height-NT
)))
4323 (setq ebnf-basic-width
(* basic
0.5)
4324 ebnf-horizontal-space
(+ basic basic
)
4325 ebnf-basic-height ebnf-basic-width
4326 ebnf-vertical-space ebnf-basic-width
)
4327 ;; ensures value is greater than zero
4328 (or (and (numberp ebnf-production-horizontal-space
)
4329 (> ebnf-production-horizontal-space
0.0))
4330 (setq ebnf-production-horizontal-space basic
))
4331 ;; ensures value is greater than zero
4332 (or (and (numberp ebnf-production-vertical-space
)
4333 (> ebnf-production-vertical-space
0.0))
4334 (setq ebnf-production-vertical-space basic
))))
4337 (defsubst ebnf-shape-value
(sym alist
)
4338 (or (cdr (assq sym alist
)) 0))
4341 (defsubst ebnf-boolean
(value)
4342 (if value
"true" "false"))
4345 (defun ebnf-begin-file ()
4348 (set-buffer ps-spool-buffer
)
4349 (goto-char (point-min))
4350 (and (search-forward "%%Creator: " nil t
)
4351 (not (search-forward "& ebnf2ps v"
4352 (save-excursion (end-of-line) (point))
4355 ;; adjust creator comment
4358 (insert " & ebnf2ps v" ebnf-version
)
4359 ;; insert ebnf settings & engine
4360 (goto-char (point-max))
4361 (search-backward "\n%%EndProlog\n")
4362 (ebnf-insert-ebnf-prologue)
4363 (ps-output "\n")))))
4366 (defun ebnf-eps-finish-and-write (buffer filename
)
4369 (setq ebnf-eps-upper-x
(max ebnf-eps-upper-x ebnf-eps-max-width
)
4370 ebnf-eps-upper-y
(if (zerop ebnf-eps-upper-y
)
4373 ebnf-production-vertical-space
4374 ebnf-eps-max-height
)))
4376 (goto-char (point-min))
4378 "%!PS-Adobe-3.0 EPSF-3.0"
4379 "\n%%BoundingBox: 0 0 "
4380 (format "%d %d" (1+ ebnf-eps-upper-x
) (1+ ebnf-eps-upper-y
))
4381 "\n%%Title: " filename
4382 "\n%%CreationDate: " (format-time-string "%T %b %d %Y")
4383 "\n%%Creator: " (user-full-name) " (using ebnf2ps v" ebnf-version
")"
4384 "\n%%DocumentNeededResources: font "
4385 (or ebnf-fonts-required
4386 (setq ebnf-fonts-required
4387 (mapconcat 'identity
4388 (ps-remove-duplicates
4389 (mapcar 'ebnf-font-name-select
4390 (list ebnf-production-font
4392 ebnf-non-terminal-font
4397 "\n%%Pages: 0\n%%EndComments\n\n%%BeginProlog\n"
4399 (ebnf-insert-ebnf-prologue)
4400 (insert ebnf-eps-begin
4401 "\n0 " (ebnf-format-float
4402 (- ebnf-eps-upper-y
(* ebnf-font-height-P
0.7)))
4403 " #ebnf2ps#begin\n")
4405 (goto-char (point-max))
4406 (insert ebnf-eps-end
)
4408 (message "Saving...")
4409 (setq filename
(expand-file-name filename
))
4410 (let ((coding-system-for-write 'raw-text-unix
))
4411 (write-region (point-min) (point-max) filename
))
4412 (message "Wrote %s" filename
)))
4415 (defun ebnf-insert-ebnf-prologue ()
4420 "\n\n% === begin EBNF settings\n\n"
4422 (format "/fP %s /%s DefFont\n"
4423 (ebnf-format-float (ebnf-font-size ebnf-production-font
))
4424 (ebnf-font-name-select ebnf-production-font
))
4425 (ebnf-format-color "/ForegroundP %s def %% %s\n"
4426 (ebnf-font-foreground ebnf-production-font
)
4428 (ebnf-format-color "/BackgroundP %s def %% %s\n"
4429 (ebnf-font-background ebnf-production-font
)
4431 (format "/EffectP %d def\n"
4432 (ebnf-font-attributes ebnf-production-font
))
4434 (format "/fT %s /%s DefFont\n"
4435 (ebnf-format-float (ebnf-font-size ebnf-terminal-font
))
4436 (ebnf-font-name-select ebnf-terminal-font
))
4437 (ebnf-format-color "/ForegroundT %s def %% %s\n"
4438 (ebnf-font-foreground ebnf-terminal-font
)
4440 (ebnf-format-color "/BackgroundT %s def %% %s\n"
4441 (ebnf-font-background ebnf-terminal-font
)
4443 (format "/EffectT %d def\n"
4444 (ebnf-font-attributes ebnf-terminal-font
))
4445 (format "/BorderWidthT %s def\n"
4446 (ebnf-format-float ebnf-terminal-border-width
))
4447 (ebnf-format-color "/BorderColorT %s def %% %s\n"
4448 ebnf-terminal-border-color
4450 (format "/ShapeT %d def\n"
4451 (ebnf-shape-value ebnf-terminal-shape
4452 ebnf-terminal-shape-alist
))
4453 (format "/ShadowT %s def\n"
4454 (ebnf-boolean ebnf-terminal-shadow
))
4456 (format "/fNT %s /%s DefFont\n"
4458 (ebnf-font-size ebnf-non-terminal-font
))
4459 (ebnf-font-name-select ebnf-non-terminal-font
))
4460 (ebnf-format-color "/ForegroundNT %s def %% %s\n"
4461 (ebnf-font-foreground ebnf-non-terminal-font
)
4463 (ebnf-format-color "/BackgroundNT %s def %% %s\n"
4464 (ebnf-font-background ebnf-non-terminal-font
)
4466 (format "/EffectNT %d def\n"
4467 (ebnf-font-attributes ebnf-non-terminal-font
))
4468 (format "/BorderWidthNT %s def\n"
4469 (ebnf-format-float ebnf-non-terminal-border-width
))
4470 (ebnf-format-color "/BorderColorNT %s def %% %s\n"
4471 ebnf-non-terminal-border-color
4473 (format "/ShapeNT %d def\n"
4474 (ebnf-shape-value ebnf-non-terminal-shape
4475 ebnf-terminal-shape-alist
))
4476 (format "/ShadowNT %s def\n"
4477 (ebnf-boolean ebnf-non-terminal-shadow
))
4479 (format "/fS %s /%s DefFont\n"
4480 (ebnf-format-float (ebnf-font-size ebnf-special-font
))
4481 (ebnf-font-name-select ebnf-special-font
))
4482 (ebnf-format-color "/ForegroundS %s def %% %s\n"
4483 (ebnf-font-foreground ebnf-special-font
)
4485 (ebnf-format-color "/BackgroundS %s def %% %s\n"
4486 (ebnf-font-background ebnf-special-font
)
4488 (format "/EffectS %d def\n"
4489 (ebnf-font-attributes ebnf-special-font
))
4490 (format "/BorderWidthS %s def\n"
4491 (ebnf-format-float ebnf-special-border-width
))
4492 (ebnf-format-color "/BorderColorS %s def %% %s\n"
4493 ebnf-special-border-color
4495 (format "/ShapeS %d def\n"
4496 (ebnf-shape-value ebnf-special-shape
4497 ebnf-terminal-shape-alist
))
4498 (format "/ShadowS %s def\n"
4499 (ebnf-boolean ebnf-special-shadow
))
4501 (format "/fE %s /%s DefFont\n"
4502 (ebnf-format-float (ebnf-font-size ebnf-except-font
))
4503 (ebnf-font-name-select ebnf-except-font
))
4504 (ebnf-format-color "/ForegroundE %s def %% %s\n"
4505 (ebnf-font-foreground ebnf-except-font
)
4507 (ebnf-format-color "/BackgroundE %s def %% %s\n"
4508 (ebnf-font-background ebnf-except-font
)
4510 (format "/EffectE %d def\n"
4511 (ebnf-font-attributes ebnf-except-font
))
4512 (format "/BorderWidthE %s def\n"
4513 (ebnf-format-float ebnf-except-border-width
))
4514 (ebnf-format-color "/BorderColorE %s def %% %s\n"
4515 ebnf-except-border-color
4517 (format "/ShapeE %d def\n"
4518 (ebnf-shape-value ebnf-except-shape
4519 ebnf-terminal-shape-alist
))
4520 (format "/ShadowE %s def\n"
4521 (ebnf-boolean ebnf-except-shadow
))
4523 (format "/fR %s /%s DefFont\n"
4524 (ebnf-format-float (ebnf-font-size ebnf-repeat-font
))
4525 (ebnf-font-name-select ebnf-repeat-font
))
4526 (ebnf-format-color "/ForegroundR %s def %% %s\n"
4527 (ebnf-font-foreground ebnf-repeat-font
)
4529 (ebnf-format-color "/BackgroundR %s def %% %s\n"
4530 (ebnf-font-background ebnf-repeat-font
)
4532 (format "/EffectR %d def\n"
4533 (ebnf-font-attributes ebnf-repeat-font
))
4534 (format "/BorderWidthR %s def\n"
4535 (ebnf-format-float ebnf-repeat-border-width
))
4536 (ebnf-format-color "/BorderColorR %s def %% %s\n"
4537 ebnf-repeat-border-color
4539 (format "/ShapeR %d def\n"
4540 (ebnf-shape-value ebnf-repeat-shape
4541 ebnf-terminal-shape-alist
))
4542 (format "/ShadowR %s def\n"
4543 (ebnf-boolean ebnf-repeat-shadow
))
4545 (format "/DefaultWidth %s def\n"
4546 (ebnf-format-float ebnf-default-width
))
4547 (format "/LineWidth %s def\n"
4548 (ebnf-format-float ebnf-line-width
))
4549 (ebnf-format-color "/LineColor %s def %% %s\n"
4552 (format "/ArrowShape %d def\n"
4553 (ebnf-shape-value ebnf-arrow-shape
4554 ebnf-arrow-shape-alist
))
4555 (format "/ChartShape %d def\n"
4556 (ebnf-shape-value ebnf-chart-shape
4557 ebnf-terminal-shape-alist
))
4558 (format "/UserArrow{%s}def\n"
4559 (let ((arrow (eval ebnf-user-arrow
)))
4563 "\n% === end EBNF settings\n\n"
4564 (and ebnf-debug-ps ebnf-debug
))))
4568 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4569 ;; Adjusting dimensions
4572 (defun ebnf-dimensions (tree)
4573 (let ((ebnf-total (length tree
))
4575 (mapcar 'ebnf-production-dimension tree
))
4579 ;; [empty width-fun dim-fun entry height width]
4580 ;;(defun ebnf-empty-dimension (empty)
4584 ;; [production width-fun dim-fun entry height width name production action]
4585 (defun ebnf-production-dimension (production)
4586 (ebnf-message-info "Calculating dimensions")
4587 (ebnf-node-dimension-func (ebnf-node-production production
))
4588 (let* ((prod (ebnf-node-production production
))
4589 (height (+ ebnf-font-height-P
4591 (ebnf-node-height prod
))))
4592 (ebnf-node-entry production height
)
4593 (ebnf-node-height production height
)
4594 (ebnf-node-width production
(+ (ebnf-node-width prod
)
4595 ebnf-horizontal-space
))))
4598 ;; [terminal width-fun dim-fun entry height width name]
4599 (defun ebnf-terminal-dimension (terminal)
4600 (ebnf-terminal-dimension1 terminal
4606 ;; [non-terminal width-fun dim-fun entry height width name]
4607 (defun ebnf-non-terminal-dimension (non-terminal)
4608 (ebnf-terminal-dimension1 non-terminal
4614 ;; [special width-fun dim-fun entry height width name]
4615 (defun ebnf-special-dimension (special)
4616 (ebnf-terminal-dimension1 special
4622 (defun ebnf-terminal-dimension1 (node font-height font-width space
)
4623 (let ((height (+ space font-height space
))
4624 (len (length (ebnf-node-name node
))))
4625 (ebnf-node-entry node
(* height
0.5))
4626 (ebnf-node-height node height
)
4627 (ebnf-node-width node
(+ ebnf-basic-width space
4629 space ebnf-basic-width
))))
4632 (defconst ebnf-null-vector
(vector t t t
0.0 0.0 0.0))
4635 ;; [repeat width-fun dim-fun entry height width times element]
4636 (defun ebnf-repeat-dimension (repeat)
4637 (let ((times (ebnf-node-name repeat
))
4638 (element (ebnf-node-separator repeat
)))
4640 (ebnf-node-dimension-func element
)
4641 (setq element ebnf-null-vector
))
4642 (ebnf-node-entry repeat
(+ (ebnf-node-entry element
)
4644 (ebnf-node-height repeat
(+ (max (ebnf-node-height element
)
4646 ebnf-space-R ebnf-space-R
))
4647 (ebnf-node-width repeat
(+ (ebnf-node-width element
)
4648 ebnf-space-R ebnf-space-R ebnf-space-R
4649 ebnf-horizontal-space
4650 (* (length times
) ebnf-font-width-R
)))))
4653 ;; [except width-fun dim-fun entry height width element element]
4654 (defun ebnf-except-dimension (except)
4655 (let ((factor (ebnf-node-list except
))
4656 (element (ebnf-node-separator except
)))
4657 (ebnf-node-dimension-func factor
)
4659 (ebnf-node-dimension-func element
)
4660 (setq element ebnf-null-vector
))
4661 (ebnf-node-entry except
(+ (max (ebnf-node-entry factor
)
4662 (ebnf-node-entry element
))
4664 (ebnf-node-height except
(+ (max (ebnf-node-height factor
)
4665 (ebnf-node-height element
))
4666 ebnf-space-E ebnf-space-E
))
4667 (ebnf-node-width except
(+ (ebnf-node-width factor
)
4668 (ebnf-node-width element
)
4669 ebnf-space-E ebnf-space-E
4670 ebnf-space-E ebnf-space-E
4672 ebnf-horizontal-space
))))
4675 ;; [alternative width-fun dim-fun entry height width list]
4676 (defun ebnf-alternative-dimension (alternative)
4677 (let ((body (ebnf-node-list alternative
))
4678 (lis (ebnf-node-list alternative
)))
4680 (ebnf-node-dimension-func (car lis
))
4681 (setq lis
(cdr lis
)))
4685 (tail (car (last body
)))
4686 (entry (ebnf-node-entry (car body
)))
4689 (setq node
(car alt
)
4691 height
(+ (ebnf-node-height node
) height
)
4692 width
(max (ebnf-node-width node
) width
)))
4693 (ebnf-adjust-width body width
)
4694 (setq height
(+ height
(* (1- (length body
)) ebnf-vertical-space
)))
4695 (ebnf-node-entry alternative
(+ entry
4698 (- (ebnf-node-height tail
)
4699 (ebnf-node-entry tail
))))))
4700 (ebnf-node-height alternative height
)
4701 (ebnf-node-width alternative
(+ width ebnf-horizontal-space
))
4702 (ebnf-node-list alternative body
))))
4705 ;; [optional width-fun dim-fun entry height width element]
4706 (defun ebnf-optional-dimension (optional)
4707 (let ((body (ebnf-node-list optional
)))
4708 (ebnf-node-dimension-func body
)
4709 (ebnf-node-entry optional
(ebnf-node-entry body
))
4710 (ebnf-node-height optional
(+ (ebnf-node-height body
)
4711 ebnf-vertical-space
))
4712 (ebnf-node-width optional
(+ (ebnf-node-width body
)
4713 ebnf-horizontal-space
))))
4716 ;; [one-or-more width-fun dim-fun entry height width element separator]
4717 (defun ebnf-one-or-more-dimension (or-more)
4718 (let ((list-part (ebnf-node-list or-more
))
4719 (sep-part (ebnf-node-separator or-more
)))
4720 (ebnf-node-dimension-func list-part
)
4722 (ebnf-node-dimension-func sep-part
))
4723 (let ((height (+ (if sep-part
4724 (ebnf-node-height sep-part
)
4727 (ebnf-node-height list-part
)))
4728 (width (max (if sep-part
4729 (ebnf-node-width sep-part
)
4731 (ebnf-node-width list-part
))))
4733 (ebnf-adjust-width list-part width
)
4734 (ebnf-adjust-width sep-part width
))
4735 (ebnf-node-entry or-more
(+ (- height
(ebnf-node-height list-part
))
4736 (ebnf-node-entry list-part
)))
4737 (ebnf-node-height or-more height
)
4738 (ebnf-node-width or-more
(+ width ebnf-horizontal-space
)))))
4741 ;; [zero-or-more width-fun dim-fun entry height width element separator]
4742 (defun ebnf-zero-or-more-dimension (or-more)
4743 (let ((list-part (ebnf-node-list or-more
))
4744 (sep-part (ebnf-node-separator or-more
)))
4745 (ebnf-node-dimension-func list-part
)
4747 (ebnf-node-dimension-func sep-part
))
4748 (let ((height (+ (if sep-part
4749 (ebnf-node-height sep-part
)
4752 (ebnf-node-height list-part
)
4753 ebnf-vertical-space
))
4754 (width (max (if sep-part
4755 (ebnf-node-width sep-part
)
4757 (ebnf-node-width list-part
))))
4759 (ebnf-adjust-width list-part width
)
4760 (ebnf-adjust-width sep-part width
))
4761 (ebnf-node-entry or-more height
)
4762 (ebnf-node-height or-more height
)
4763 (ebnf-node-width or-more
(+ width ebnf-horizontal-space
)))))
4766 ;; [sequence width-fun dim-fun entry height width list]
4767 (defun ebnf-sequence-dimension (sequence)
4771 (lis (ebnf-node-list sequence
))
4774 (setq node
(car lis
)
4776 (ebnf-node-dimension-func node
)
4777 (setq entry
(ebnf-node-entry node
)
4778 above
(max above entry
)
4779 below
(max below
(- (ebnf-node-height node
) entry
))
4780 width
(+ width
(ebnf-node-width node
))))
4781 (ebnf-node-entry sequence above
)
4782 (ebnf-node-height sequence
(+ above below
))
4783 (ebnf-node-width sequence width
)))
4786 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4790 (defun ebnf-adjust-width (node width
)
4796 (setcar node
(ebnf-adjust-width (car node
) width
))
4797 (setq node
(cdr node
)))))
4800 ;; nothing to be done
4801 ((= width
(ebnf-node-width node
))
4803 ;; left justify term
4804 ((eq ebnf-justify-sequence
'left
)
4805 (ebnf-adjust-empty node width nil
))
4806 ;; right justify terms
4807 ((eq ebnf-justify-sequence
'right
)
4808 (ebnf-adjust-empty node width t
))
4811 (ebnf-node-width-func node width
)
4812 (ebnf-node-width node width
)
4820 (defun ebnf-adjust-empty (node width last-p
)
4821 (if (eq (ebnf-node-kind node
) 'ebnf-generate-empty
)
4823 (ebnf-node-width node width
)
4825 (let ((empty (ebnf-make-empty (- width
(ebnf-node-width node
)))))
4826 (ebnf-make-dup-sequence node
4829 (list node empty
))))))
4832 ;; [terminal width-fun dim-fun entry height width name]
4833 ;; [non-terminal width-fun dim-fun entry height width name]
4834 ;; [empty width-fun dim-fun entry height width]
4835 ;; [special width-fun dim-fun entry height width name]
4836 ;; [repeat width-fun dim-fun entry height width times element]
4837 ;; [except width-fun dim-fun entry height width element element]
4838 ;;(defun ebnf-terminal-width (terminal width)
4842 ;; [alternative width-fun dim-fun entry height width list]
4843 ;; [optional width-fun dim-fun entry height width element]
4844 (defun ebnf-alternative-width (alternative width
)
4845 (ebnf-adjust-width (ebnf-node-list alternative
)
4846 (- width ebnf-horizontal-space
)))
4849 ;; [one-or-more width-fun dim-fun entry height width element separator]
4850 ;; [zero-or-more width-fun dim-fun entry height width element separator]
4851 (defun ebnf-list-width (or-more width
)
4852 (setq width
(- width ebnf-horizontal-space
))
4853 (ebnf-node-list or-more
4854 (ebnf-justify-list or-more
4855 (ebnf-node-list or-more
)
4857 (ebnf-node-separator or-more
4858 (ebnf-justify-list or-more
4859 (ebnf-node-separator or-more
)
4863 ;; [sequence width-fun dim-fun entry height width list]
4864 (defun ebnf-sequence-width (sequence width
)
4865 (ebnf-node-list sequence
4866 (ebnf-justify-list sequence
4867 (ebnf-node-list sequence
)
4871 (defun ebnf-justify-list (node seq width
)
4872 (let ((seq-width (ebnf-node-width node
)))
4873 (if (= width seq-width
)
4876 ;; left justify terms
4877 ((eq ebnf-justify-sequence
'left
)
4878 (ebnf-justify node seq seq-width width t
))
4879 ;; right justify terms
4880 ((eq ebnf-justify-sequence
'right
)
4881 (ebnf-justify node seq seq-width width nil
))
4884 (let ((the-width (/ (- width seq-width
) (length seq
)))
4887 (ebnf-adjust-width (car lis
)
4888 (+ (ebnf-node-width (car lis
))
4890 (setq lis
(cdr lis
)))
4895 (defun ebnf-justify (node seq seq-width width last-p
)
4896 (let ((term (car (if last-p
(last seq
) seq
))))
4898 ;; adjust empty term
4899 ((eq (ebnf-node-kind term
) 'ebnf-generate-empty
)
4900 (ebnf-node-width term
(+ (- width seq-width
)
4901 (ebnf-node-width term
)))
4903 ;; insert empty at end ==> left justify
4906 (list (ebnf-make-empty (- width seq-width
)))))
4907 ;; insert empty at beginning ==> right justify
4909 (cons (ebnf-make-empty (- width seq-width
))
4914 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4915 ;; Functions used by parsers
4918 (defun ebnf-eps-add-context (name)
4919 (let ((filename (ebnf-eps-filename name
)))
4920 (if (member filename ebnf-eps-context
)
4921 (error "Try to open an already opened EPS file: %s" filename
)
4922 (setq ebnf-eps-context
(cons filename ebnf-eps-context
)))))
4925 (defun ebnf-eps-remove-context (name)
4926 (let ((filename (ebnf-eps-filename name
)))
4927 (if (member filename ebnf-eps-context
)
4928 (setq ebnf-eps-context
(delete filename ebnf-eps-context
))
4929 (error "Try to close a not opened EPS file: %s" filename
))))
4932 (defun ebnf-eps-add-production (header)
4933 (and ebnf-eps-executing
4935 (let ((prod (assoc header ebnf-eps-production-list
)))
4937 (setcdr prod
(append ebnf-eps-context
(cdr prod
)))
4938 (setq ebnf-eps-production-list
4939 (cons (cons header
(ebnf-dup-list ebnf-eps-context
))
4940 ebnf-eps-production-list
))))))
4943 (defun ebnf-dup-list (old)
4946 (setq new
(cons (car old
) new
)
4951 (defun ebnf-buffer-substring (chars)
4952 (buffer-substring-no-properties
4955 (skip-chars-forward chars ebnf-limit
)
4959 ;; replace the range "\240-\377" (see `ebnf-range-regexp').
4960 (defconst ebnf-8-bit-chars
(ebnf-range-regexp "" ?
\240 ?
\377))
4963 (defun ebnf-string (chars eos-char kind
)
4965 (buffer-substring-no-properties
4968 ;;(skip-chars-forward (concat chars "\240-\377") ebnf-limit)
4969 (skip-chars-forward (concat chars ebnf-8-bit-chars
) ebnf-limit
)
4970 (if (or (eobp) (/= (following-char) eos-char
))
4971 (error "Illegal %s: missing `%c'" kind eos-char
)
4976 (defun ebnf-get-string ()
4978 (buffer-substring-no-properties (point) (ebnf-end-of-string)))
4981 (defun ebnf-end-of-string ()
4983 (while (> (logand n
1) 0)
4984 (skip-chars-forward "^\"" ebnf-limit
)
4985 (setq n
(- (skip-chars-backward "\\\\")))
4986 (goto-char (+ (point) n
1))))
4987 (if (= (preceding-char) ?
\")
4989 (error "Missing `\"'")))
4992 (defun ebnf-trim-right (str)
4993 (let* ((len (1- (length str
)))
4995 (while (and (> index
0) (= (aref str index
) ?\
))
4996 (setq index
(1- index
)))
4999 (substring str
0 (1+ index
)))))
5002 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5006 (defun ebnf-make-empty (&optional width
)
5007 (vector 'ebnf-generate-empty
5012 (or width ebnf-horizontal-space
)))
5015 (defun ebnf-make-terminal (name)
5016 (ebnf-make-terminal1 name
5017 'ebnf-generate-terminal
5018 'ebnf-terminal-dimension
))
5021 (defun ebnf-make-non-terminal (name)
5022 (ebnf-make-terminal1 name
5023 'ebnf-generate-non-terminal
5024 'ebnf-non-terminal-dimension
))
5027 (defun ebnf-make-special (name)
5028 (ebnf-make-terminal1 name
5029 'ebnf-generate-special
5030 'ebnf-special-dimension
))
5033 (defun ebnf-make-terminal1 (name gen-func dim-func
)
5040 (let ((len (length name
)))
5041 (cond ((> len
2) name
)
5042 ((= len
2) (concat " " name
))
5043 ((= len
1) (concat " " name
" "))
5048 (defun ebnf-make-one-or-more (list-part &optional sep-part
)
5049 (ebnf-make-or-more1 'ebnf-generate-one-or-more
5050 'ebnf-one-or-more-dimension
5055 (defun ebnf-make-zero-or-more (list-part &optional sep-part
)
5056 (ebnf-make-or-more1 'ebnf-generate-zero-or-more
5057 'ebnf-zero-or-more-dimension
5062 (defun ebnf-make-or-more1 (gen-func dim-func list-part sep-part
)
5069 (if (listp list-part
)
5070 (ebnf-make-sequence list-part
)
5072 (if (and sep-part
(listp sep-part
))
5073 (ebnf-make-sequence sep-part
)
5077 (defun ebnf-make-production (name prod action
)
5078 (vector 'ebnf-generate-production
5080 'ebnf-production-dimension
5089 (defun ebnf-make-alternative (body)
5090 (vector 'ebnf-generate-alternative
5091 'ebnf-alternative-width
5092 'ebnf-alternative-dimension
5099 (defun ebnf-make-optional (body)
5100 (vector 'ebnf-generate-optional
5101 'ebnf-alternative-width
5102 'ebnf-optional-dimension
5109 (defun ebnf-make-except (factor exception
)
5110 (vector 'ebnf-generate-except
5112 'ebnf-except-dimension
5120 (defun ebnf-make-repeat (times primary
)
5121 (vector 'ebnf-generate-repeat
5123 'ebnf-repeat-dimension
5131 (defun ebnf-make-sequence (seq)
5132 (vector 'ebnf-generate-sequence
5133 'ebnf-sequence-width
5134 'ebnf-sequence-dimension
5141 (defun ebnf-make-dup-sequence (node seq
)
5142 (vector 'ebnf-generate-sequence
5143 'ebnf-sequence-width
5144 'ebnf-sequence-dimension
5145 (ebnf-node-entry node
)
5146 (ebnf-node-height node
)
5147 (ebnf-node-width node
)
5151 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5152 ;; Optimizers used by parsers
5155 (defun ebnf-token-except (element exception
)
5158 (setq exception
(cdr exception
)))
5159 (and element
; EMPTY - A ==> EMPTY
5160 (let ((kind (ebnf-node-kind element
)))
5163 ((and (null exception
)
5164 (eq kind
'ebnf-generate-optional
))
5165 (ebnf-node-list element
))
5166 ;; { A }- ==> { A }+
5167 ((and (null exception
)
5168 (eq kind
'ebnf-generate-zero-or-more
))
5169 (ebnf-node-kind element
'ebnf-generate-one-or-more
)
5170 (ebnf-node-dimension-func element
'ebnf-one-or-more-dimension
)
5172 ;; ( A | EMPTY )- ==> A
5173 ;; ( A | B | EMPTY )- ==> A | B
5174 ((and (null exception
)
5175 (eq kind
'ebnf-generate-alternative
)
5177 (car (last (ebnf-node-list element
))))
5178 'ebnf-generate-empty
))
5179 (let ((elt (ebnf-node-list element
))
5185 ;; this should not happen!!?!
5186 (setq element
(ebnf-make-empty
5187 (ebnf-node-width element
)))
5189 (setq elt
(ebnf-node-list element
))
5190 (and (= (length elt
) 1)
5191 (setq element
(car elt
))))
5195 (ebnf-make-except element exception
))
5199 (defun ebnf-token-repeat (times repeat
)
5200 (if (null (cdr repeat
))
5201 ;; n * EMPTY ==> EMPTY
5205 (ebnf-make-repeat times
(cdr repeat
)))))
5208 (defun ebnf-token-optional (body)
5209 (let ((kind (ebnf-node-kind body
)))
5211 ;; [ EMPTY ] ==> EMPTY
5212 ((eq kind
'ebnf-generate-empty
)
5214 ;; [ { A }* ] ==> { A }*
5215 ((eq kind
'ebnf-generate-zero-or-more
)
5217 ;; [ { A }+ ] ==> { A }*
5218 ((eq kind
'ebnf-generate-one-or-more
)
5219 (ebnf-node-kind body
'ebnf-generate-zero-or-more
)
5221 ;; [ A | B ] ==> A | B | EMPTY
5222 ((eq kind
'ebnf-generate-alternative
)
5223 (ebnf-node-list body
(nconc (ebnf-node-list body
)
5224 (list (ebnf-make-empty))))
5228 (ebnf-make-optional body
))
5232 (defun ebnf-token-alternative (body sequence
)
5236 (cons (car sequence
)
5238 (cons (car sequence
)
5239 (let ((seq (cdr sequence
)))
5240 (if (and (= (length body
) 1) (null seq
))
5242 (ebnf-make-alternative (nreverse (if seq
5247 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5248 ;; Variables used by parsers
5251 (defconst ebnf-comment-table
5252 (let ((table (make-vector 256 nil
)))
5253 ;; Override special comment character:
5254 (aset table ?
< 'newline
)
5255 (aset table ?
> 'keep-line
)
5257 "Vector used to map characters to a special comment token.")
5260 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5261 ;; To make this file smaller, some commands go in a separate file.
5262 ;; But autoload them here to make the separation invisible.
5264 (autoload 'ebnf-bnf-parser
"ebnf-bnf"
5267 (autoload 'ebnf-bnf-initialize
"ebnf-bnf"
5268 "Initialize EBNF token table.")
5270 (autoload 'ebnf-iso-parser
"ebnf-iso"
5273 (autoload 'ebnf-iso-initialize
"ebnf-iso"
5274 "Initialize ISO EBNF token table.")
5276 (autoload 'ebnf-yac-parser
"ebnf-yac"
5277 "Yacc/Bison parser.")
5279 (autoload 'ebnf-yac-initialize
"ebnf-yac"
5280 "Initializations for Yacc/Bison parser.")
5282 (autoload 'ebnf-eliminate-empty-rules
"ebnf-otz"
5283 "Eliminate empty rules.")
5285 (autoload 'ebnf-optimize
"ebnf-otz"
5286 "Syntatic chart optimizer.")
5288 (autoload 'ebnf-otz-initialize
"ebnf-otz"
5289 "Initialize optimizer.")
5292 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5297 ;;; ebnf2ps.el ends here