1 ;;; ebnf2ps.el --- translate an EBNF to a syntactic chart on PostScript
3 ;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
4 ;; Free Software Foundation, Inc.
6 ;; Author: Vinicius Jose Latorre <viniciusjl@ig.com.br>
7 ;; Maintainer: Vinicius Jose Latorre <viniciusjl@ig.com.br>
8 ;; Keywords: wp, ebnf, PostScript
10 ;; X-URL: http://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre
12 ;; This file is part of GNU Emacs.
14 ;; GNU Emacs is free software; you can redistribute it and/or modify
15 ;; it under the terms of the GNU General Public License as published by
16 ;; the Free Software Foundation; either version 3, or (at your option)
19 ;; GNU Emacs is distributed in the hope that it will be useful,
20 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 ;; GNU General Public License for more details.
24 ;; You should have received a copy of the GNU General Public License
25 ;; along with GNU Emacs; see the file COPYING. If not, write to the
26 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
27 ;; Boston, MA 02110-1301, USA.
29 (defconst ebnf-version
"4.4"
30 "ebnf2ps.el, v 4.4 <2007/02/12 vinicius>
32 Vinicius's last change version. When reporting bugs, please also
33 report the version of Emacs, if any, that ebnf2ps was running with.
35 Please send all bug fixes and enhancements to
36 Vinicius Jose Latorre <viniciusjl@ig.com.br>.
42 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
47 ;; This package translates an EBNF to a syntactic chart on PostScript.
49 ;; To use ebnf2ps, insert in your ~/.emacs:
53 ;; ebnf2ps uses ps-print package (version 5.2.3 or later), so see ps-print to
54 ;; know how to set options like landscape printing, page headings, margins,
57 ;; NOTE: ps-print zebra stripes and line number options doesn't have effect on
58 ;; ebnf2ps, they behave as it's turned off.
60 ;; For good performance, be sure to byte-compile ebnf2ps.el, e.g.
62 ;; M-x byte-compile-file <give the path to ebnf2ps.el when prompted>
64 ;; This will generate ebnf2ps.elc, which will be loaded instead of ebnf2ps.el.
66 ;; ebnf2ps was tested with GNU Emacs 20.4.1.
72 ;; ebnf2ps provides the following commands for generating PostScript syntactic
73 ;; chart images of Emacs buffers:
75 ;; ebnf-print-directory
79 ;; ebnf-spool-directory
88 ;; These commands all perform essentially the same function: they generate
89 ;; PostScript syntactic chart images suitable for printing on a PostScript
90 ;; printer or displaying with GhostScript. These commands are collectively
91 ;; referred to as "ebnf- commands".
93 ;; The word "print", "spool" and "eps" in the command name determines when the
94 ;; PostScript image is sent to the printer (or file):
96 ;; print - The PostScript image is immediately sent to the printer;
98 ;; spool - The PostScript image is saved temporarily in an Emacs buffer.
99 ;; Many images may be spooled locally before printing them. To
100 ;; send the spooled images to the printer, use the command
103 ;; eps - The PostScript image is immediately sent to an EPS file.
105 ;; The spooling mechanism is the same as used by ps-print and was designed for
106 ;; printing lots of small files to save paper that would otherwise be wasted on
107 ;; banner pages, and to make it easier to find your output at the printer (it's
108 ;; easier to pick up one 50-page printout than to find 50 single-page
109 ;; printouts). As ebnf2ps and ps-print use the same Emacs buffer to spool
110 ;; images, you can intermix the spooling of ebnf2ps and ps-print images.
112 ;; ebnf2ps use the same hook of ps-print in the `kill-emacs-hook' so that you
113 ;; won't accidentally quit from Emacs while you have unprinted PostScript
114 ;; waiting in the spool buffer. If you do attempt to exit with spooled
115 ;; PostScript, you'll be asked if you want to print it, and if you decline,
116 ;; you'll be asked to confirm the exit; this is modeled on the confirmation
117 ;; that Emacs uses for modified buffers.
119 ;; The word "directory", "file", "buffer" or "region" in the command name
120 ;; determines how much of the buffer is printed:
122 ;; directory - Read files in the directory and print them.
124 ;; file - Read file and print it.
126 ;; buffer - Print the entire buffer.
128 ;; region - Print just the current region.
130 ;; Two ebnf- command examples:
132 ;; ebnf-print-buffer - translate and print the entire buffer, and send it
133 ;; immediately to the printer.
135 ;; ebnf-spool-region - translate and print just the current region, and
136 ;; spool the image in Emacs to send to the printer
139 ;; Note that `ebnf-eps-directory', `ebnf-eps-file', `ebnf-eps-buffer' and
140 ;; `ebnf-eps-region' never spool the EPS image, so they don't use the ps-print
141 ;; spooling mechanism. See section "Actions in Comments" for an explanation
142 ;; about EPS file generation.
148 ;; To translate and print your buffer, type
150 ;; M-x ebnf-print-buffer
152 ;; or substitute one of the other four ebnf- commands. The command will
153 ;; generate the PostScript image and print or spool it as specified. By giving
154 ;; the command a prefix argument
156 ;; C-u M-x ebnf-print-buffer
158 ;; it will save the PostScript image to a file instead of sending it to the
159 ;; printer; you will be prompted for the name of the file to save the image to.
160 ;; The prefix argument is ignored by the commands that spool their images, but
161 ;; you may save the spooled images to a file by giving a prefix argument to
164 ;; C-u M-x ebnf-despool
166 ;; When invoked this way, `ebnf-despool' will prompt you for the name of the
169 ;; The prefix argument is also ignored by `ebnf-eps-buffer' and
170 ;; `ebnf-eps-region'.
172 ;; Any of the `ebnf-' commands can be bound to keys. Here are some examples:
174 ;; (global-set-key 'f22 'ebnf-print-buffer) ;f22 is prsc
175 ;; (global-set-key '(shift f22) 'ebnf-print-region)
176 ;; (global-set-key '(control f22) 'ebnf-despool)
179 ;; Invoking Ebnf2ps in Batch
180 ;; -------------------------
182 ;; It's possible also to run ebnf2ps in batch, this is useful when, for
183 ;; example, you have a directory with a lot of files containing the EBNF to be
184 ;; translated to PostScript.
186 ;; To run ebnf2ps in batch type, for example:
188 ;; emacs -batch -l setup-ebnf2ps.el -f ebnf-eps-directory
190 ;; Where setup-ebnf2ps.el should be a file containing:
192 ;; ;; set load-path if ebnf2ps isn't installed in your Emacs environment
193 ;; (setq load-path (append (list "/dir/of/ebnf2ps") load-path))
194 ;; (require 'ebnf2ps)
195 ;; ;; insert here your ebnf2ps settings
196 ;; (setq ebnf-terminal-shape 'bevel)
203 ;; BNF (Backus Naur Form) notation is defined like languages, and like
204 ;; languages there are rules about name formation and syntax. In this section
205 ;; it's defined a BNF syntax that it's called simply EBNF (Extended BNF).
206 ;; ebnf2ps package also deal with other BNF notation. Please, see the variable
207 ;; `ebnf-syntax' documentation below in this section.
209 ;; The current EBNF that ebnf2ps accepts has the following constructions:
211 ;; ; comment (until end of line)
215 ;; $A default non-terminal (see text below)
216 ;; $"C" default terminal (see text below)
217 ;; $?C? default special (see text below)
218 ;; A = B. production (A is the header and B the body)
219 ;; C D sequence (C occurs before D)
220 ;; C | D alternative (C or D occurs)
221 ;; A - B exception (A excluding B, B without any non-terminal)
222 ;; n * A repetition (A repeats at least n (integer) times)
223 ;; n * n A repetition (A repeats exactly n (integer) times)
224 ;; n * m A repetition (A repeats at least n (integer) and at most
225 ;; m (integer) times)
226 ;; (C) group (expression C is grouped together)
227 ;; [C] optional (C may or not occurs)
228 ;; C+ one or more occurrences of C
229 ;; {C}+ one or more occurrences of C
230 ;; {C}* zero or more occurrences of C
231 ;; {C} zero or more occurrences of C
232 ;; C / D equivalent to: C {D C}*
233 ;; {C || D}+ equivalent to: C {D C}*
234 ;; {C || D}* equivalent to: [C {D C}*]
235 ;; {C || D} equivalent to: [C {D C}*]
237 ;; The EBNF syntax written using the notation above is:
239 ;; EBNF = {production}+.
241 ;; production = non_terminal "=" body ".". ;; production
243 ;; body = {sequence || "|"}*. ;; alternative
245 ;; sequence = {exception}*. ;; sequence
247 ;; exception = repeat [ "-" repeat]. ;; exception
249 ;; repeat = [ integer "*" [ integer ]] term. ;; repetition
252 ;; | [factor] "+" ;; one-or-more
253 ;; | [factor] "/" [factor] ;; one-or-more
256 ;; factor = [ "$" ] "\"" terminal "\"" ;; terminal
257 ;; | [ "$" ] non_terminal ;; non-terminal
258 ;; | [ "$" ] "?" special "?" ;; special
259 ;; | "(" body ")" ;; group
260 ;; | "[" body "]" ;; zero-or-one
261 ;; | "{" body [ "||" body ] "}+" ;; one-or-more
262 ;; | "{" body [ "||" body ] "}*" ;; zero-or-more
263 ;; | "{" body [ "||" body ] "}" ;; zero-or-more
266 ;; non_terminal = "[!#%&'*-,0-:<>@-Z\\\\^-z~\\240-\\377]+".
267 ;; ;; that is, a valid non_terminal accepts decimal digits, letters (upper
268 ;; ;; and lower), 8-bit accentuated characters,
269 ;; ;; "!", "#", "%", "&", "'", "*", "+", ",", ":",
270 ;; ;; "<", ">", "@", "\", "^", "_", "`" and "~".
272 ;; terminal = "\\([^\"\\]\\|\\\\[ -~\\240-\\377]\\)+".
273 ;; ;; that is, a valid terminal accepts any printable character (including
274 ;; ;; 8-bit accentuated characters) except `"', as `"' is used to delimit a
275 ;; ;; terminal. Also, accepts escaped characters, that is, a character
276 ;; ;; pair starting with `\' followed by a printable character, for
277 ;; ;; example: \", \\.
279 ;; special = "[^?\\000-\\010\\012-\\037\\177-\\237]*".
280 ;; ;; that is, a valid special accepts any printable character (including
281 ;; ;; 8-bit accentuated characters) and tabs except `?', as `?' is used to
282 ;; ;; delimit a special.
284 ;; integer = "[0-9]+".
285 ;; ;; that is, an integer is a sequence of one or more decimal digits.
287 ;; comment = ";" "[^\\n\\000-\\010\\016-\\037\\177-\\237]*" "\\n".
288 ;; ;; that is, a comment starts with the character `;' and terminates at end
289 ;; ;; of line. Also, it only accepts printable characters (including 8-bit
290 ;; ;; accentuated characters) and tabs.
292 ;; Try to use the above EBNF to test ebnf2ps.
294 ;; The `default' terminal, non-terminal and special is a way to indicate a
295 ;; default path in a production. For example, the production:
297 ;; X = [ $A ( B | $C ) | D ].
299 ;; Indicates that the default meaning for "X" is "A C" if "X" is empty.
301 ;; The terminal name is controlled by `ebnf-terminal-regexp' and
302 ;; `ebnf-case-fold-search', so it's possible to match other kind of terminal
303 ;; name besides that enclosed by `"'.
305 ;; Let's see an example:
307 ;; (setq ebnf-terminal-regexp "[A-Z][_A-Z]*") ; upper case name
308 ;; (setq ebnf-case-fold-search nil) ; exact matching
310 ;; If you have the production:
312 ;; Logical = "(" Expression ( OR | AND | "XOR" ) Expression ")".
314 ;; The names are classified as:
316 ;; Logical Expression non-terminal
317 ;; "(" OR AND "XOR" ")" terminal
319 ;; The line comment is controlled by `ebnf-lex-comment-char'. The default
320 ;; value is ?\; (character `;').
322 ;; The end of production is controlled by `ebnf-lex-eop-char'. The default
323 ;; value is ?. (character `.').
325 ;; The variable `ebnf-syntax' specifies which syntax to recognize:
327 ;; `ebnf' ebnf2ps recognizes the syntax described above.
328 ;; The following variables *ONLY* have effect with this
330 ;; `ebnf-terminal-regexp', `ebnf-case-fold-search',
331 ;; `ebnf-lex-comment-char' and `ebnf-lex-eop-char'.
333 ;; `abnf' ebnf2ps recognizes the syntax described in the URL:
334 ;; `http://www.ietf.org/rfc/rfc2234.txt'
335 ;; ("Augmented BNF for Syntax Specifications: ABNF").
337 ;; `iso-ebnf' ebnf2ps recognizes the syntax described in the URL:
338 ;; `http://www.cl.cam.ac.uk/~mgk25/iso-ebnf.html'
339 ;; ("International Standard of the ISO EBNF Notation").
340 ;; The following variables *ONLY* have effect with this
342 ;; `ebnf-iso-alternative-p' and `ebnf-iso-normalize-p'.
344 ;; `yacc' ebnf2ps recognizes the Yacc/Bison syntax.
345 ;; The following variable *ONLY* has effect with this
347 ;; `ebnf-yac-ignore-error-recovery'.
349 ;; `ebnfx' ebnf2ps recognizes the syntax described in the URL:
350 ;; `http://www.w3.org/TR/2004/REC-xml-20040204/#sec-notation'
351 ;; ("Extensible Markup Language (XML) 1.0 (Third Edition)")
353 ;; `dtd' ebnf2ps recognizes the syntax described in the URL:
354 ;; `http://www.w3.org/TR/2004/REC-xml-20040204/'
355 ;; ("Extensible Markup Language (XML) 1.0 (Third Edition)")
357 ;; Any other value is treated as `ebnf'.
359 ;; The default value is `ebnf'.
365 ;; The following EBNF optimizations are done:
367 ;; [ { A }* ] ==> { A }*
368 ;; [ { A }+ ] ==> { A }*
369 ;; [ A ] + ==> { A }*
370 ;; { A }* + ==> { A }*
371 ;; { A }+ + ==> { A }+
374 ;; ( A | EMPTY )- ==> A
375 ;; ( A | B | EMPTY )- ==> A | B
376 ;; [ A | B ] ==> A | B | EMPTY
377 ;; n * EMPTY ==> EMPTY
379 ;; EMPTY / EMPTY ==> EMPTY
380 ;; EMPTY - A ==> EMPTY
382 ;; The following optimizations are done when `ebnf-optimize' is non-nil:
385 ;; 1. A = B | A C. ==> A = B {C}*.
386 ;; 2. A = B | A B. ==> A = {B}+.
387 ;; 3. A = | A B. ==> A = {B}*.
388 ;; 4. A = B | A C B. ==> A = {B || C}+.
389 ;; 5. A = B | D | A C | A E. ==> A = ( B | D ) { C | E }*.
392 ;; 6. A = B | . ==> A = [B].
393 ;; 7. A = | B . ==> A = [B].
396 ;; 8. A = B C | B D. ==> A = B (C | D).
397 ;; 9. A = C B | D B. ==> A = (C | D) B.
398 ;; 10. A = B C E | B D E. ==> A = B (C | D) E.
400 ;; The above optimizations are specially useful when `ebnf-syntax' is `yacc'.
406 ;; You may use form feed (^L \014) to force a production to start on a new
407 ;; page, for example:
416 ;; c) A = B ^L^L^L | C.^L
420 ;; In all examples above, only the production X will start on a new page.
423 ;; Actions in Comments
424 ;; -------------------
426 ;; ebnf2ps accepts the following actions in comments:
428 ;; ;^ same as form feed. See section Form Feed above.
430 ;; ;> the next production starts in the same line as the current one.
431 ;; It is useful when `ebnf-horizontal-orientation' is nil.
433 ;; ;< the next production starts in the next line.
434 ;; It is useful when `ebnf-horizontal-orientation' is non-nil.
436 ;; ;[EPS open a new EPS file. The EPS file name has the form:
437 ;; <PREFIX><NAME>.eps
438 ;; where <PREFIX> is given by variable `ebnf-eps-prefix' and
439 ;; <NAME> is the string given by ;[ action comment, this string is
440 ;; mapped to form a valid file name (see documentation for
441 ;; `ebnf-eps-buffer' or `ebnf-eps-region').
442 ;; It has effect only during `ebnf-eps-buffer' or
443 ;; `ebnf-eps-region' execution.
444 ;; It's an error to try to open an already opened EPS file.
446 ;; ;]EPS close an opened EPS file.
447 ;; It has effect only during `ebnf-eps-buffer' or
448 ;; `ebnf-eps-region' execution.
449 ;; It's an error to try to close a not opened EPS file.
451 ;; ;Hheader generate a header in current EPS file. The header string can
452 ;; have the following formats:
454 ;; %% prints a % character.
456 ;; %H prints the `ebnf-eps-header' (which see) value.
458 ;; %F prints the `ebnf-eps-footer' (which see) value.
460 ;; Any other format is ignored, that is, if, for example, it's
461 ;; used %s then %s characters are stripped out from the header.
462 ;; If header is an empty string, no header is generated until a
463 ;; non-empty header is specified or `ebnf-eps-header' has a
464 ;; non-empty string value.
466 ;; ;Ffooter generate a footer in current EPS file. Similar to ;H action
471 ;; (setq ebnf-horizontal-orientation nil)
475 ;; ;> C and B are drawn in the same line
479 ;; The graphical result is:
485 ;; +---------+ +-----+
497 ;; Note that if ascending production sort is used, the productions A and B will
498 ;; be drawn in the same line instead of C and B.
500 ;; If consecutive actions occur, only the last one takes effect, so if you
509 ;; Only the ;> will take effect, that is, A and B will be drawn in the same
512 ;; In ISO EBNF the above actions are specified as (*^*), (*>*), (*<*), (*[EPS*)
513 ;; and (*]EPS*). The first example above should be written:
517 ;; (*> C and B are drawn in the same line *)
521 ;; For an example of EPS action when executing `ebnf-eps-buffer' or
522 ;; `ebnf-eps-region':
541 ;; The following table summarizes the results:
543 ;; EPS FILE NAME NO SORT ASCENDING SORT DESCENDING SORT
544 ;; ebnf--AA.eps A C A C C A
545 ;; ebnf--BB.eps C B B C C B
546 ;; ebnf--CC.eps A C B F A B C F F C B A
552 ;; As you can see if EPS actions is not used, each single production is
553 ;; generated per EPS file. To avoid overriding EPS files, use names in ;[ that
554 ;; it's not an existing production name.
556 ;; In the following case:
564 ;; The production A is generated in both files ebnf--AA.eps and ebnf--BB.eps.
570 ;; The buffer *Ebnf2ps Log* is where the ebnf2ps log messages are inserted.
571 ;; These messages are intended to help debugging ebnf2ps.
573 ;; The log messages are enabled by `ebnf-log' option (which see). The default
574 ;; value is nil, that is, no log messages are generated.
580 ;; Some tools are provided to help you.
582 ;; `ebnf-setup' returns the current setup.
584 ;; `ebnf-syntax-directory' does a syntactic analysis of your EBNF files in the
587 ;; `ebnf-syntax-file' does a syntactic analysis of your EBNF in the given
590 ;; `ebnf-syntax-buffer' does a syntactic analysis of your EBNF in the current
593 ;; `ebnf-syntax-region' does a syntactic analysis of your EBNF in the current
596 ;; `ebnf-customize' activates a customization buffer for ebnf2ps options.
598 ;; `ebnf-syntax-directory', `ebnf-syntax-file', `ebnf-syntax-buffer',
599 ;; `ebnf-syntax-region' and `ebnf-customize' can be bound to keys in the same
600 ;; way as `ebnf-' commands.
606 ;; ebn2ps has the following hook variables:
609 ;; It is evaluated once before any ebnf2ps process.
611 ;; `ebnf-production-hook'
612 ;; It is evaluated on each beginning of production.
615 ;; It is evaluated on each beginning of page.
621 ;; Below it's shown a brief description of ebnf2ps options, please, see the
622 ;; options declaration in the code for a long documentation.
624 ;; `ebnf-horizontal-orientation' Non-nil means productions are drawn
627 ;; `ebnf-horizontal-max-height' Non-nil means to use maximum production
628 ;; height in horizontal orientation.
630 ;; `ebnf-production-horizontal-space' Specify horizontal space in points
631 ;; between productions.
633 ;; `ebnf-production-vertical-space' Specify vertical space in points
634 ;; between productions.
636 ;; `ebnf-justify-sequence' Specify justification of terms in a
637 ;; sequence inside alternatives.
639 ;; `ebnf-terminal-regexp' Specify how it's a terminal name.
641 ;; `ebnf-case-fold-search' Non-nil means ignore case on matching.
643 ;; `ebnf-terminal-font' Specify terminal font.
645 ;; `ebnf-terminal-shape' Specify terminal box shape.
647 ;; `ebnf-terminal-shadow' Non-nil means terminal box will have a
650 ;; `ebnf-terminal-border-width' Specify border width for terminal box.
652 ;; `ebnf-terminal-border-color' Specify border color for terminal box.
654 ;; `ebnf-production-name-p' Non-nil means production name will be
657 ;; `ebnf-sort-production' Specify how productions are sorted.
659 ;; `ebnf-production-font' Specify production font.
661 ;; `ebnf-non-terminal-font' Specify non-terminal font.
663 ;; `ebnf-non-terminal-shape' Specify non-terminal box shape.
665 ;; `ebnf-non-terminal-shadow' Non-nil means non-terminal box will
668 ;; `ebnf-non-terminal-border-width' Specify border width for non-terminal
671 ;; `ebnf-non-terminal-border-color' Specify border color for non-terminal
674 ;; `ebnf-special-show-delimiter' Non-nil means special delimiter
675 ;; (character `?') is shown.
677 ;; `ebnf-special-font' Specify special font.
679 ;; `ebnf-special-shape' Specify special box shape.
681 ;; `ebnf-special-shadow' Non-nil means special box will have a
684 ;; `ebnf-special-border-width' Specify border width for special box.
686 ;; `ebnf-special-border-color' Specify border color for special box.
688 ;; `ebnf-except-font' Specify except font.
690 ;; `ebnf-except-shape' Specify except box shape.
692 ;; `ebnf-except-shadow' Non-nil means except box will have a
695 ;; `ebnf-except-border-width' Specify border width for except box.
697 ;; `ebnf-except-border-color' Specify border color for except box.
699 ;; `ebnf-repeat-font' Specify repeat font.
701 ;; `ebnf-repeat-shape' Specify repeat box shape.
703 ;; `ebnf-repeat-shadow' Non-nil means repeat box will have a
706 ;; `ebnf-repeat-border-width' Specify border width for repeat box.
708 ;; `ebnf-repeat-border-color' Specify border color for repeat box.
710 ;; `ebnf-entry-percentage' Specify entry height on alternatives.
712 ;; `ebnf-arrow-shape' Specify the arrow shape.
714 ;; `ebnf-chart-shape' Specify chart flow shape.
716 ;; `ebnf-color-p' Non-nil means use color.
718 ;; `ebnf-line-width' Specify flow line width.
720 ;; `ebnf-line-color' Specify flow line color.
722 ;; `ebnf-arrow-extra-width' Specify extra width for arrow shape
725 ;; `ebnf-arrow-scale' Specify the arrow scale.
727 ;; `ebnf-user-arrow' Specify a sexp for user arrow shape (a
730 ;; `ebnf-debug-ps' Non-nil means to generate PostScript
733 ;; `ebnf-lex-comment-char' Specify the line comment character.
735 ;; `ebnf-lex-eop-char' Specify the end of production
738 ;; `ebnf-syntax' Specify syntax to be recognized.
740 ;; `ebnf-iso-alternative-p' Non-nil means use alternative ISO EBNF.
742 ;; `ebnf-iso-normalize-p' Non-nil means normalize ISO EBNF syntax
745 ;; `ebnf-default-width' Specify additional border width over
746 ;; default terminal, non-terminal or
749 ;; `ebnf-file-suffix-regexp' Specify file name suffix that contains
752 ;; `ebnf-eps-prefix' Specify EPS prefix file name.
754 ;; `ebnf-eps-header-font' Specify EPS header font.
756 ;; `ebnf-eps-header' Specify EPS header.
758 ;; `ebnf-eps-footer-font' Specify EPS footer font.
760 ;; `ebnf-eps-footer' Specify EPS footer.
762 ;; `ebnf-use-float-format' Non-nil means use `%f' float format.
764 ;; `ebnf-stop-on-error' Non-nil means signal error and stop.
765 ;; Nil means signal error and continue.
767 ;; `ebnf-yac-ignore-error-recovery' Non-nil means ignore error recovery.
769 ;; `ebnf-ignore-empty-rule' Non-nil means ignore empty rules.
771 ;; `ebnf-optimize' Non-nil means optimize syntactic chart
774 ;; `ebnf-log' Non-nil means generate log messages.
776 ;; To set the above options you may:
778 ;; a) insert the code in your ~/.emacs, like:
780 ;; (setq ebnf-terminal-shape 'bevel)
782 ;; This way always keep your default settings when you enter a new Emacs
785 ;; b) or use `set-variable' in your Emacs session, like:
787 ;; M-x set-variable RET ebnf-terminal-shape RET bevel RET
789 ;; This way keep your settings only during the current Emacs session.
791 ;; c) or use customization, for example:
792 ;; click on menu-bar *Help* option,
793 ;; then click on *Customize*,
794 ;; then click on *Browse Customization Groups*,
795 ;; expand *PostScript* group,
796 ;; expand *Ebnf2ps* group
797 ;; and then customize ebnf2ps options.
798 ;; Through this way, you may choose if the settings are kept or not when
799 ;; you leave out the current Emacs session.
801 ;; d) or see the option value:
803 ;; C-h v ebnf-terminal-shape RET
805 ;; and click the *customize* hypertext button.
806 ;; Through this way, you may choose if the settings are kept or not when
807 ;; you leave out the current Emacs session.
811 ;; M-x ebnf-customize RET
813 ;; and then customize ebnf2ps options.
814 ;; Through this way, you may choose if the settings are kept or not when
815 ;; you leave out the current Emacs session.
821 ;; Sometimes you need to change the EBNF style you are using, for example,
822 ;; change the shapes and colors. These changes may force you to set some
823 ;; variables and after use, set back the variables to the old values.
825 ;; To help to handle this situation, ebnf2ps has the following commands to
828 ;; `ebnf-find-style' Return style definition if NAME is already defined;
829 ;; otherwise, return nil.
831 ;; `ebnf-insert-style' Insert a new style NAME with inheritance INHERITS and
834 ;; `ebnf-delete-style' Delete style NAME.
836 ;; `ebnf-merge-style' Merge values of style NAME with style VALUES.
838 ;; `ebnf-apply-style' Set STYLE as the current style.
840 ;; `ebnf-reset-style' Reset current style.
842 ;; `ebnf-push-style' Push the current style and set STYLE as the current
845 ;; `ebnf-pop-style' Pop a style and set it as the current style.
847 ;; These commands help to put together a lot of variable settings in a group
848 ;; and name this group. So when you wish to apply these settings it's only
849 ;; needed to give the name.
851 ;; There is also a notion of simple inheritance of style: if you declare that
852 ;; style A inherits from style B, all settings of B are applied first and then
853 ;; the settings of A are applied. This is useful when you wish to modify some
854 ;; aspects of an existing style, but at same time wish to keep it unmodified.
856 ;; See documentation for `ebnf-style-database'.
862 ;; Below it is the layout of minimum area to draw each element, and it's used
863 ;; the following terms:
865 ;; font height is given by:
866 ;; (terminal font height + non-terminal font height) / 2
868 ;; entry is the vertical position used to know where it should
869 ;; be drawn the flow line in the current element.
871 ;; extra is given by `ebnf-arrow-extra-width'.
874 ;; * SPECIAL, TERMINAL and NON-TERMINAL
876 ;; +==============+...................................
877 ;; | | } font height / 2 } entry }
878 ;; | XXXXXXXX...|....... } }
879 ;; ====+ XXXXXXXX +==== } text height ...... } height
880 ;; : | XXXXXXXX...|...:... }
881 ;; : | : : | : } font height / 2 }
882 ;; : +==============+...:...............................
884 ;; : : : : : :.........................
885 ;; : : : : : } font height }
886 ;; : : : : :....... }
887 ;; : : : : } font height / 2 }
888 ;; : : : :........... }
889 ;; : : : } text width } width
890 ;; : : :.................. }
891 ;; : : } font height / 2 }
892 ;; : :...................... }
893 ;; : } font height + extra }
894 ;; :.................................................
899 ;; +==========+.....................................
903 ;; ===+===+ +===+===... } element height } height
906 ;; : | +==========+.|................. }
907 ;; : | : : | : } font height }
908 ;; : +==============+...................................
910 ;; : : : :......................
911 ;; : : : } font height * 2 }
913 ;; : : } element width } width
914 ;; : :..................... }
915 ;; : } font height * 2 }
916 ;; :...............................................
921 ;; +===+...................................
922 ;; +==+ A +==+ } A height } }
923 ;; | +===+..|........ } entry }
924 ;; + + } font height } }
925 ;; / +===+...\....... } }
926 ;; ===+====+ B +====+=== } B height ..... } height
927 ;; : \ +===+.../....... }
928 ;; : + + : } font height }
929 ;; : | +===+..|........ }
930 ;; : +==+ C +==+ : } C height }
931 ;; : : +===+...................................
933 ;; : : : :......................
934 ;; : : : } font height * 2 }
936 ;; : : } max width } width
937 ;; : :................. }
938 ;; : } font height * 2 }
939 ;; :..........................................
942 ;; 1. An empty alternative has zero of height.
944 ;; 2. The variable `ebnf-entry-percentage' is used to determine the
950 ;; +===========+...............................
951 ;; +=+ separator +=+ } separator height }
952 ;; / +===========+..\........ }
954 ;; | | } font height }
956 ;; \ +===========+../........ } height = entry
957 ;; +=+ element +=+ } element height }
958 ;; /: +===========+..\........ }
960 ;; + : : + } font height }
962 ;; ==+=======================+==.......................
964 ;; : : : :.......................
965 ;; : : : } font height * 2 }
967 ;; : : } max width } width
968 ;; : :......................... }
969 ;; : } font height * 2 }
970 ;; :...................................................
975 ;; +===========+......................................
976 ;; +=+ separator +=+ } separator height } }
977 ;; / +===========+..\...... } }
979 ;; | | } font height } } height
981 ;; \ +===========+../...... } }
982 ;; ===+=+ element +=+=== } element height .... }
983 ;; : : +===========+......................................
985 ;; : : : :........................
986 ;; : : : } font height * 2 }
988 ;; : : } max width } width
989 ;; : :....................... }
990 ;; : } font height * 2 }
991 ;; :..............................................
996 ;; XXXXXX:......................................
997 ;; XXXXXX: } production font height }
998 ;; XXXXXX:............ }
1000 ;; +======+....... } height = entry
1002 ;; ====+ +==== } element height }
1004 ;; : +======+.................................
1006 ;; : : : :......................
1007 ;; : : : } font height * 2 }
1009 ;; : : } element width } width
1010 ;; : :.............. }
1011 ;; : } font height * 2 }
1012 ;; :.....................................
1017 ;; +================+...................................
1018 ;; | | } font height / 2 } entry }
1019 ;; | +===+...|....... } }
1020 ;; ====+ N * | X | +==== } X height ......... } height
1021 ;; : | : : +===+...|...:... }
1022 ;; : | : : : : | : } font height / 2 }
1023 ;; : +================+...:...............................
1025 ;; : : : : : : : :..........................
1026 ;; : : : : : : : } font height }
1027 ;; : : : : : : :....... }
1028 ;; : : : : : : } font height / 2 }
1029 ;; : : : : : :........... }
1030 ;; : : : : : } X width }
1031 ;; : : : : :............... }
1032 ;; : : : : } font height / 2 } width
1033 ;; : : : :.................. }
1034 ;; : : : } text width }
1035 ;; : : :..................... }
1036 ;; : : } font height / 2 }
1037 ;; : :........................ }
1038 ;; : } font height + extra }
1039 ;; :...................................................
1044 ;; +==================+...................................
1045 ;; | | } font height / 2 } entry }
1046 ;; | +===+ +===+...|....... } }
1047 ;; ====+ | X | - | y | +==== } max height ....... } height
1048 ;; : | +===+ +===+...|...:... }
1049 ;; : | : : : : | : } font height / 2 }
1050 ;; : +==================+...:...............................
1052 ;; : : : : : : : :..........................
1053 ;; : : : : : : : } font height }
1054 ;; : : : : : : :....... }
1055 ;; : : : : : : } font height / 2 }
1056 ;; : : : : : :........... }
1057 ;; : : : : : } Y width }
1058 ;; : : : : :............... }
1059 ;; : : : : } font height } width
1060 ;; : : : :................... }
1061 ;; : : : } X width }
1062 ;; : : :....................... }
1063 ;; : : } font height / 2 }
1064 ;; : :.......................... }
1065 ;; : } font height + extra }
1066 ;; :.....................................................
1068 ;; NOTE: If Y element is empty, it's draw nothing at Y place.
1071 ;; Internal Structures
1072 ;; -------------------
1074 ;; ebnf2ps has two passes. The first pass does a lexical and syntactic analysis
1075 ;; of current buffer and generates an intermediate representation. The second
1076 ;; pass uses the intermediate representation to generate the PostScript
1079 ;; The intermediate representation is a list of vectors, the vector element
1080 ;; represents a syntactic chart element. Below is a vector representation for
1081 ;; each syntactic chart element.
1083 ;; [production WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH NAME PRODUCTION ACTION]
1084 ;; [alternative WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH LIST]
1085 ;; [sequence WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH LIST]
1086 ;; [terminal WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH NAME DEFAULT]
1087 ;; [non-terminal WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH NAME DEFAULT]
1088 ;; [special WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH NAME DEFAULT]
1089 ;; [empty WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH]
1090 ;; [optional WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH ELEMENT]
1091 ;; [one-or-more WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH ELEMENT SEPARATOR]
1092 ;; [zero-or-more WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH ELEMENT SEPARATOR]
1093 ;; [repeat WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH TIMES ELEMENT]
1094 ;; [except WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH ELEMENT ELEMENT]
1096 ;; The first vector position is a function symbol used to generate PostScript
1097 ;; for this element.
1098 ;; WIDTH-FUN is a function symbol called to adjust the element width.
1099 ;; DIM-FUN is a function symbol called to set the element dimensions.
1100 ;; ENTRY is the element entry point.
1101 ;; HEIGHT and WIDTH are the element height and width, respectively.
1102 ;; NAME is a string that it's the element name.
1103 ;; DEFAULT is a boolean that indicates if it's a `default' element.
1104 ;; PRODUCTION and ELEMENT are vectors that represents sub-elements of current
1106 ;; LIST is a list of vector that represents the list part for alternatives and
1108 ;; SEPARATOR is a vector that represents the sub-element used to separate the
1110 ;; TIMES is a string representing the number of times that ELEMENT is repeated
1111 ;; on a repeat construction.
1112 ;; ACTION indicates some action that should be done before production is
1113 ;; generated. The current actions are:
1117 ;; form-feed current production starts on a new page.
1119 ;; newline current production starts on next line, this is useful
1120 ;; when `ebnf-horizontal-orientation' is non-nil.
1122 ;; keep-line current production continues on the current line, this
1123 ;; is useful when `ebnf-horizontal-orientation' is nil.
1129 ;; . Handle situations when syntactic chart is out of paper.
1130 ;; . Use other alphabet than ascii.
1131 ;; . Optimizations...
1137 ;; Thanks to Eli Zaretskii <eliz@gnu.org> for some doc fixes.
1139 ;; Thanks to Drew Adams <drew.adams@oracle.com> for suggestions:
1140 ;; - `ebnf-arrow-extra-width', `ebnf-arrow-scale',
1141 ;; `ebnf-production-name-p', `ebnf-stop-on-error',
1142 ;; `ebnf-file-suffix-regexp'and `ebnf-special-show-delimiter' variables.
1143 ;; - `ebnf-delete-style', `ebnf-eps-file' and `ebnf-eps-directory'
1147 ;; Thanks to Matthew K. Junker <junker@alum.mit.edu> for the suggestion to deal
1148 ;; with some Bison features (%right, %left and %prec pragmas). His suggestion
1149 ;; was extended to deal with %nonassoc pragma too.
1151 ;; Thanks to all who emailed comments.
1154 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1161 (and (string< ps-print-version
"5.2.3")
1162 (error "`ebnf2ps' requires `ps-print' package version 5.2.3 or later"))
1165 ;; to avoid gripes with Emacs 20
1166 (or (fboundp 'assq-delete-all
)
1167 (defun assq-delete-all (key alist
)
1168 "Delete from ALIST all elements whose car is KEY.
1169 Return the modified alist.
1170 Elements of ALIST that are not conses are ignored."
1173 (if (and (consp (car tail
))
1174 (eq (car (car tail
)) key
))
1175 (setq alist
(delq (car tail
) alist
)))
1176 (setq tail
(cdr tail
)))
1180 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1184 ;;; Interface to the command system
1186 (defgroup postscript nil
1193 (defgroup ebnf2ps nil
1194 "Translate an EBNF to a syntactic chart on PostScript."
1201 (defgroup ebnf-special nil
1202 "Special customization."
1209 (defgroup ebnf-except nil
1210 "Except customization."
1217 (defgroup ebnf-repeat nil
1218 "Repeat customization."
1225 (defgroup ebnf-terminal nil
1226 "Terminal customization."
1233 (defgroup ebnf-non-terminal nil
1234 "Non-Terminal customization."
1241 (defgroup ebnf-production nil
1242 "Production customization."
1249 (defgroup ebnf-shape nil
1250 "Shapes customization."
1257 (defgroup ebnf-displacement nil
1258 "Displacement customization."
1265 (defgroup ebnf-syntactic nil
1266 "Syntactic customization."
1273 (defgroup ebnf-optimization nil
1274 "Optimization customization."
1281 (defcustom ebnf-horizontal-orientation nil
1282 "*Non-nil means productions are drawn horizontally."
1285 :group
'ebnf-displacement
)
1288 (defcustom ebnf-horizontal-max-height nil
1289 "*Non-nil means to use maximum production height in horizontal orientation.
1291 It is only used when `ebnf-horizontal-orientation' is non-nil."
1294 :group
'ebnf-displacement
)
1297 (defcustom ebnf-production-horizontal-space
0.0 ; use ebnf2ps default value
1298 "*Specify horizontal space in points between productions.
1300 Value less or equal to zero forces ebnf2ps to set a proper default value."
1303 :group
'ebnf-displacement
)
1306 (defcustom ebnf-production-vertical-space
0.0 ; use ebnf2ps default value
1307 "*Specify vertical space in points between productions.
1309 Value less or equal to zero forces ebnf2ps to set a proper default value."
1312 :group
'ebnf-displacement
)
1315 (defcustom ebnf-justify-sequence
'center
1316 "*Specify justification of terms in a sequence inside alternatives.
1320 `left' left justification
1321 `right' right justification
1322 any other value centralize"
1323 :type
'(radio :tag
"Sequence Justification"
1324 (const left
) (const right
) (other :tag
"center" center
))
1326 :group
'ebnf-displacement
)
1329 (defcustom ebnf-special-show-delimiter t
1330 "*Non-nil means special delimiter (character `?') is shown."
1333 :group
'ebnf-special
)
1336 (defcustom ebnf-special-font
'(7 Courier
"Black" "Gray95" bold italic
)
1337 "*Specify special font.
1339 See documentation for `ebnf-production-font'."
1340 :type
'(list :tag
"Special Font"
1341 (number :tag
"Font Size")
1342 (symbol :tag
"Font Name")
1343 (choice :tag
"Foreground Color"
1344 (string :tag
"Name")
1345 (other :tag
"Default" nil
))
1346 (choice :tag
"Background Color"
1347 (string :tag
"Name")
1348 (other :tag
"Default" nil
))
1349 (repeat :tag
"Font Attributes" :inline t
1350 (choice (const bold
) (const italic
)
1351 (const underline
) (const strikeout
)
1352 (const overline
) (const shadow
)
1353 (const box
) (const outline
))))
1355 :group
'ebnf-special
)
1358 (defcustom ebnf-special-shape
'bevel
1359 "*Specify special box shape.
1361 See documentation for `ebnf-non-terminal-shape'."
1362 :type
'(radio :tag
"Special Shape"
1363 (const miter
) (const round
) (const bevel
))
1365 :group
'ebnf-special
)
1368 (defcustom ebnf-special-shadow nil
1369 "*Non-nil means special box will have a shadow."
1372 :group
'ebnf-special
)
1375 (defcustom ebnf-special-border-width
0.5
1376 "*Specify border width for special box."
1379 :group
'ebnf-special
)
1382 (defcustom ebnf-special-border-color
"Black"
1383 "*Specify border color for special box."
1386 :group
'ebnf-special
)
1389 (defcustom ebnf-except-font
'(7 Courier
"Black" "Gray90" bold italic
)
1390 "*Specify except font.
1392 See documentation for `ebnf-production-font'."
1393 :type
'(list :tag
"Except Font"
1394 (number :tag
"Font Size")
1395 (symbol :tag
"Font Name")
1396 (choice :tag
"Foreground Color"
1397 (string :tag
"Name")
1398 (other :tag
"Default" nil
))
1399 (choice :tag
"Background Color"
1400 (string :tag
"Name")
1401 (other :tag
"Default" nil
))
1402 (repeat :tag
"Font Attributes" :inline t
1403 (choice (const bold
) (const italic
)
1404 (const underline
) (const strikeout
)
1405 (const overline
) (const shadow
)
1406 (const box
) (const outline
))))
1408 :group
'ebnf-except
)
1411 (defcustom ebnf-except-shape
'bevel
1412 "*Specify except box shape.
1414 See documentation for `ebnf-non-terminal-shape'."
1415 :type
'(radio :tag
"Except Shape"
1416 (const miter
) (const round
) (const bevel
))
1418 :group
'ebnf-except
)
1421 (defcustom ebnf-except-shadow nil
1422 "*Non-nil means except box will have a shadow."
1425 :group
'ebnf-except
)
1428 (defcustom ebnf-except-border-width
0.25
1429 "*Specify border width for except box."
1432 :group
'ebnf-except
)
1435 (defcustom ebnf-except-border-color
"Black"
1436 "*Specify border color for except box."
1439 :group
'ebnf-except
)
1442 (defcustom ebnf-repeat-font
'(7 Courier
"Black" "Gray85" bold italic
)
1443 "*Specify repeat font.
1445 See documentation for `ebnf-production-font'."
1446 :type
'(list :tag
"Repeat Font"
1447 (number :tag
"Font Size")
1448 (symbol :tag
"Font Name")
1449 (choice :tag
"Foreground Color"
1450 (string :tag
"Name")
1451 (other :tag
"Default" nil
))
1452 (choice :tag
"Background Color"
1453 (string :tag
"Name")
1454 (other :tag
"Default" nil
))
1455 (repeat :tag
"Font Attributes" :inline t
1456 (choice (const bold
) (const italic
)
1457 (const underline
) (const strikeout
)
1458 (const overline
) (const shadow
)
1459 (const box
) (const outline
))))
1461 :group
'ebnf-repeat
)
1464 (defcustom ebnf-repeat-shape
'bevel
1465 "*Specify repeat box shape.
1467 See documentation for `ebnf-non-terminal-shape'."
1468 :type
'(radio :tag
"Repeat Shape"
1469 (const miter
) (const round
) (const bevel
))
1471 :group
'ebnf-repeat
)
1474 (defcustom ebnf-repeat-shadow nil
1475 "*Non-nil means repeat box will have a shadow."
1478 :group
'ebnf-repeat
)
1481 (defcustom ebnf-repeat-border-width
0.0
1482 "*Specify border width for repeat box."
1485 :group
'ebnf-repeat
)
1488 (defcustom ebnf-repeat-border-color
"Black"
1489 "*Specify border color for repeat box."
1492 :group
'ebnf-repeat
)
1495 (defcustom ebnf-terminal-font
'(7 Courier
"Black" "White")
1496 "*Specify terminal font.
1498 See documentation for `ebnf-production-font'."
1499 :type
'(list :tag
"Terminal Font"
1500 (number :tag
"Font Size")
1501 (symbol :tag
"Font Name")
1502 (choice :tag
"Foreground Color"
1503 (string :tag
"Name")
1504 (other :tag
"Default" nil
))
1505 (choice :tag
"Background Color"
1506 (string :tag
"Name")
1507 (other :tag
"Default" nil
))
1508 (repeat :tag
"Font Attributes" :inline t
1509 (choice (const bold
) (const italic
)
1510 (const underline
) (const strikeout
)
1511 (const overline
) (const shadow
)
1512 (const box
) (const outline
))))
1514 :group
'ebnf-terminal
)
1517 (defcustom ebnf-terminal-shape
'miter
1518 "*Specify terminal box shape.
1520 See documentation for `ebnf-non-terminal-shape'."
1521 :type
'(radio :tag
"Terminal Shape"
1522 (const miter
) (const round
) (const bevel
))
1524 :group
'ebnf-terminal
)
1527 (defcustom ebnf-terminal-shadow nil
1528 "*Non-nil means terminal box will have a shadow."
1531 :group
'ebnf-terminal
)
1534 (defcustom ebnf-terminal-border-width
1.0
1535 "*Specify border width for terminal box."
1538 :group
'ebnf-terminal
)
1541 (defcustom ebnf-terminal-border-color
"Black"
1542 "*Specify border color for terminal box."
1545 :group
'ebnf-terminal
)
1548 (defcustom ebnf-production-name-p t
1549 "*Non-nil means production name will be printed."
1552 :group
'ebnf-production
)
1555 (defcustom ebnf-sort-production nil
1556 "*Specify how productions are sorted.
1560 nil don't sort productions.
1561 `ascending' ascending sort.
1562 any other value descending sort."
1563 :type
'(radio :tag
"Production Sort"
1564 (const :tag
"Ascending" ascending
)
1565 (const :tag
"Descending" descending
)
1566 (other :tag
"No Sort" nil
))
1568 :group
'ebnf-production
)
1571 (defcustom ebnf-production-font
'(10 Helvetica
"Black" "White" bold
)
1572 "*Specify production header font.
1574 It is a list with the following form:
1576 (SIZE NAME FOREGROUND BACKGROUND ATTRIBUTE...)
1579 SIZE is the font size.
1580 NAME is the font name symbol.
1581 ATTRIBUTE is one of the following symbols:
1582 bold - use bold font.
1583 italic - use italic font.
1584 underline - put a line under text.
1585 strikeout - like underline, but the line is in middle of text.
1586 overline - like underline, but the line is over the text.
1587 shadow - text will have a shadow.
1588 box - text will be surrounded by a box.
1589 outline - print characters as hollow outlines.
1590 FOREGROUND is a foreground string color name; if it's nil, the default color is
1592 BACKGROUND is a background string color name; if it's nil, the default color is
1595 See `ps-font-info-database' for valid font name."
1596 :type
'(list :tag
"Production Font"
1597 (number :tag
"Font Size")
1598 (symbol :tag
"Font Name")
1599 (choice :tag
"Foreground Color"
1600 (string :tag
"Name")
1601 (other :tag
"Default" nil
))
1602 (choice :tag
"Background Color"
1603 (string :tag
"Name")
1604 (other :tag
"Default" nil
))
1605 (repeat :tag
"Font Attributes" :inline t
1606 (choice (const bold
) (const italic
)
1607 (const underline
) (const strikeout
)
1608 (const overline
) (const shadow
)
1609 (const box
) (const outline
))))
1611 :group
'ebnf-production
)
1614 (defcustom ebnf-non-terminal-font
'(7 Helvetica
"Black" "White")
1615 "*Specify non-terminal font.
1617 See documentation for `ebnf-production-font'."
1618 :type
'(list :tag
"Non-Terminal Font"
1619 (number :tag
"Font Size")
1620 (symbol :tag
"Font Name")
1621 (choice :tag
"Foreground Color"
1622 (string :tag
"Name")
1623 (other :tag
"Default" nil
))
1624 (choice :tag
"Background Color"
1625 (string :tag
"Name")
1626 (other :tag
"Default" nil
))
1627 (repeat :tag
"Font Attributes" :inline t
1628 (choice (const bold
) (const italic
)
1629 (const underline
) (const strikeout
)
1630 (const overline
) (const shadow
)
1631 (const box
) (const outline
))))
1633 :group
'ebnf-non-terminal
)
1636 (defcustom ebnf-non-terminal-shape
'round
1637 "*Specify non-terminal box shape.
1653 Any other value is treated as `miter'."
1654 :type
'(radio :tag
"Non-Terminal Shape"
1655 (const miter
) (const round
) (const bevel
))
1657 :group
'ebnf-non-terminal
)
1660 (defcustom ebnf-non-terminal-shadow nil
1661 "*Non-nil means non-terminal box will have a shadow."
1664 :group
'ebnf-non-terminal
)
1667 (defcustom ebnf-non-terminal-border-width
1.0
1668 "*Specify border width for non-terminal box."
1671 :group
'ebnf-non-terminal
)
1674 (defcustom ebnf-non-terminal-border-color
"Black"
1675 "*Specify border color for non-terminal box."
1678 :group
'ebnf-non-terminal
)
1681 (defcustom ebnf-arrow-shape
'hollow
1682 "*Specify the arrow shape.
1688 `semi-up' * `transparent' *
1696 `semi-down' =====* `hollow' *
1712 `semi-up-hollow' `semi-up-full'
1718 `semi-down-hollow' `semi-down-full'
1724 `user' See also documentation for variable `ebnf-user-arrow'.
1726 Any other value is treated as `none'."
1727 :type
'(radio :tag
"Arrow Shape"
1728 (const none
) (const semi-up
)
1729 (const semi-down
) (const simple
)
1730 (const transparent
) (const hollow
)
1731 (const full
) (const semi-up-hollow
)
1732 (const semi-down-hollow
) (const semi-up-full
)
1733 (const semi-down-full
) (const user
))
1738 (defcustom ebnf-chart-shape
'round
1739 "*Specify chart flow shape.
1741 See documentation for `ebnf-non-terminal-shape'."
1742 :type
'(radio :tag
"Chart Flow Shape"
1743 (const miter
) (const round
) (const bevel
))
1748 (defcustom ebnf-user-arrow nil
1749 "*Specify a sexp for user arrow shape (a PostScript code).
1751 When evaluated, the sexp should return nil or a string containing PostScript
1752 code. PostScript code should draw a right arrow.
1754 The anatomy of a right arrow is:
1756 ...... Initial position
1758 : *.................
1762 ======+======*... } hT2
1766 : *.................
1772 :.......................
1774 Where `hT', `hT2' and `hT4' are predefined PostScript variable names that can
1775 be used to generate your own arrow. As these variables are used along
1776 PostScript execution, *DON'T* modify the values of them. Instead, copy the
1777 values, if you need to modify them.
1779 The relation between these variables is: hT = 2 * hT2 = 4 * hT4.
1781 The variable `ebnf-user-arrow' is only used when `ebnf-arrow-shape' is set to
1783 :type
'(sexp :tag
"User Arrow Shape")
1788 (defcustom ebnf-syntax
'ebnf
1789 "*Specify syntax to be recognized.
1793 `ebnf' ebnf2ps recognizes the syntax described in ebnf2ps
1795 The following variables *ONLY* have effect with this
1797 `ebnf-terminal-regexp', `ebnf-case-fold-search',
1798 `ebnf-lex-comment-char' and `ebnf-lex-eop-char'.
1800 `abnf' ebnf2ps recognizes the syntax described in the URL:
1801 `http://www.ietf.org/rfc/rfc2234.txt'
1802 (\"Augmented BNF for Syntax Specifications: ABNF\").
1804 `iso-ebnf' ebnf2ps recognizes the syntax described in the URL:
1805 `http://www.cl.cam.ac.uk/~mgk25/iso-ebnf.html'
1806 (\"International Standard of the ISO EBNF Notation\").
1807 The following variables *ONLY* have effect with this
1809 `ebnf-iso-alternative-p' and `ebnf-iso-normalize-p'.
1811 `yacc' ebnf2ps recognizes the Yacc/Bison syntax.
1812 The following variable *ONLY* has effect with this
1814 `ebnf-yac-ignore-error-recovery'.
1816 `ebnfx' ebnf2ps recognizes the syntax described in the URL:
1817 `http://www.w3.org/TR/2004/REC-xml-20040204/#sec-notation'
1818 (\"Extensible Markup Language (XML) 1.0 (Third Edition)\")
1820 `dtd' ebnf2ps recognizes the syntax described in the URL:
1821 `http://www.w3.org/TR/2004/REC-xml-20040204/'
1822 (\"Extensible Markup Language (XML) 1.0 (Third Edition)\")
1824 Any other value is treated as `ebnf'."
1825 :type
'(radio :tag
"Syntax"
1826 (const ebnf
) (const abnf
) (const iso-ebnf
)
1827 (const yacc
) (const ebnfx
) (const dtd
))
1829 :group
'ebnf-syntactic
)
1832 (defcustom ebnf-lex-comment-char ?\
;
1833 "*Specify the line comment character.
1835 It's used only when `ebnf-syntax' is `ebnf'."
1838 :group
'ebnf-syntactic
)
1841 (defcustom ebnf-lex-eop-char ?.
1842 "*Specify the end of production character.
1844 It's used only when `ebnf-syntax' is `ebnf'."
1847 :group
'ebnf-syntactic
)
1850 (defcustom ebnf-terminal-regexp nil
1851 "*Specify how it's a terminal name.
1853 If it's nil, the terminal name must be enclosed by `\"'.
1854 If it's a string, it should be a regexp that it'll be used to determine a
1855 terminal name; terminal name may also be enclosed by `\"'.
1857 It's used only when `ebnf-syntax' is `ebnf'."
1858 :type
'(radio :tag
"Terminal Name"
1861 :group
'ebnf-syntactic
)
1864 (defcustom ebnf-case-fold-search nil
1865 "*Non-nil means ignore case on matching.
1867 It's only used when `ebnf-terminal-regexp' is non-nil and when `ebnf-syntax' is
1871 :group
'ebnf-syntactic
)
1874 (defcustom ebnf-iso-alternative-p nil
1875 "*Non-nil means use alternative ISO EBNF.
1877 It's only used when `ebnf-syntax' is `iso-ebnf'.
1879 This variable affects the following symbol set:
1881 STANDARD ALTERNATIVE
1890 :group
'ebnf-syntactic
)
1893 (defcustom ebnf-iso-normalize-p nil
1894 "*Non-nil means normalize ISO EBNF syntax names.
1896 Normalize a name means that several contiguous spaces inside name become a
1897 single space, so \"A B C\" is normalized to \"A B C\".
1899 It's only used when `ebnf-syntax' is `iso-ebnf'."
1902 :group
'ebnf-syntactic
)
1905 (defcustom ebnf-file-suffix-regexp
"\.[Bb][Nn][Ff]$"
1906 "*Specify file name suffix that contains EBNF.
1908 See `ebnf-eps-directory' command."
1914 (defcustom ebnf-eps-prefix
"ebnf--"
1915 "*Specify EPS prefix file name.
1917 See `ebnf-eps-buffer' and `ebnf-eps-region' commands."
1923 (defcustom ebnf-eps-header-font
'(11 Helvetica
"Black" "White" bold
)
1924 "*Specify EPS header font.
1926 See documentation for `ebnf-production-font'.
1928 See `ebnf-eps-buffer' and `ebnf-eps-region' commands."
1929 :type
'(list :tag
"EPS Header Font"
1930 (number :tag
"Font Size")
1931 (symbol :tag
"Font Name")
1932 (choice :tag
"Foreground Color"
1933 (string :tag
"Name")
1934 (other :tag
"Default" nil
))
1935 (choice :tag
"Background Color"
1936 (string :tag
"Name")
1937 (other :tag
"Default" nil
))
1938 (repeat :tag
"Font Attributes" :inline t
1939 (choice (const bold
) (const italic
)
1940 (const underline
) (const strikeout
)
1941 (const overline
) (const shadow
)
1942 (const box
) (const outline
))))
1947 (defcustom ebnf-eps-header nil
1948 "*Specify EPS header.
1950 The value should be a string, a symbol or nil.
1952 String is inserted unchanged.
1954 For symbol bounded to a function, the function is called and should return a
1955 string. For symbol bounded to a value, the value should be a string.
1957 If symbol is unbounded, it is silently ignored.
1959 Empty string or nil mean that no header will be generated.
1961 Note that when the header action comment (;H in EBNF syntax) is specified, the
1962 string in the header action comment is processed and, if it returns a non-empty
1963 string, it's used to generate the header. The header action comment accepts
1964 the following formats:
1966 %% prints a % character.
1968 %H prints the `ebnf-eps-header' value.
1970 %F prints the `ebnf-eps-footer' (which see) value.
1972 Any other format is ignored, that is, if, for example, it's used %s then %s
1973 characters are stripped out from the header. If header action comment is an
1974 empty string, no header is generated until a non-empty header is specified or
1975 `ebnf-eps-header' has a non-empty string value."
1976 :type
'(repeat (choice :menu-tag
"EPS Header"
1978 string symbol
(const :tag
"No Header" nil
)))
1983 (defcustom ebnf-eps-footer-font
'(7 Helvetica
"Black" "White" bold
)
1984 "*Specify EPS footer font.
1986 See documentation for `ebnf-production-font'.
1988 See `ebnf-eps-buffer' and `ebnf-eps-region' commands."
1989 :type
'(list :tag
"EPS Footer Font"
1990 (number :tag
"Font Size")
1991 (symbol :tag
"Font Name")
1992 (choice :tag
"Foreground Color"
1993 (string :tag
"Name")
1994 (other :tag
"Default" nil
))
1995 (choice :tag
"Background Color"
1996 (string :tag
"Name")
1997 (other :tag
"Default" nil
))
1998 (repeat :tag
"Font Attributes" :inline t
1999 (choice (const bold
) (const italic
)
2000 (const underline
) (const strikeout
)
2001 (const overline
) (const shadow
)
2002 (const box
) (const outline
))))
2007 (defcustom ebnf-eps-footer nil
2008 "*Specify EPS footer.
2010 The value should be a string, a symbol or nil.
2012 String is inserted unchanged.
2014 For symbol bounded to a function, the function is called and should return a
2015 string. For symbol bounded to a value, the value should be a string.
2017 If symbol is unbounded, it is silently ignored.
2019 Empty string or nil mean that no footer will be generated.
2021 Note that when the footer action comment (;F in EBNF syntax) is specified, the
2022 string in the footer action comment is processed and, if it returns a non-empty
2023 string, it's used to generate the footer. The footer action comment accepts
2024 the following formats:
2026 %% prints a % character.
2028 %H prints the `ebnf-eps-header' (which see) value.
2030 %F prints the `ebnf-eps-footer' value.
2032 Any other format is ignored, that is, if, for example, it's used %s then %s
2033 characters are stripped out from the footer. If footer action comment is an
2034 empty string, no footer is generated until a non-empty footer is specified or
2035 `ebnf-eps-footer' has a non-empty string value."
2036 :type
'(repeat (choice :menu-tag
"EPS Footer"
2038 string symbol
(const :tag
"No Footer" nil
)))
2043 (defcustom ebnf-entry-percentage
0.5 ; middle
2044 "*Specify entry height on alternatives.
2046 It must be a float between 0.0 (top) and 1.0 (bottom)."
2052 (defcustom ebnf-default-width
0.6
2053 "*Specify additional border width over default terminal, non-terminal or
2060 ;; Printing color requires x-color-values.
2061 (defcustom ebnf-color-p
(or (fboundp 'x-color-values
) ; Emacs
2062 (fboundp 'color-instance-rgb-components
)) ; XEmacs
2063 "*Non-nil means use color."
2069 (defcustom ebnf-line-width
1.0
2070 "*Specify flow line width."
2076 (defcustom ebnf-line-color
"Black"
2077 "*Specify flow line color."
2083 (defcustom ebnf-arrow-extra-width
2084 (if (eq ebnf-arrow-shape
'none
)
2086 (* (sqrt 5.0) 0.65 ebnf-line-width
))
2087 "*Specify extra width for arrow shape drawing.
2089 The extra width is used to avoid that the arrowhead and the terminal border
2090 overlap. It depens on `ebnf-arrow-shape' and `ebnf-line-width'."
2096 (defcustom ebnf-arrow-scale
1.0
2097 "*Specify the arrow scale.
2099 Values lower than 1.0, shrink the arrow.
2100 Values greater than 1.0, expand the arrow."
2106 (defcustom ebnf-debug-ps nil
2107 "*Non-nil means to generate PostScript debug procedures.
2109 It is intended to help PostScript programmers in debugging."
2115 (defcustom ebnf-use-float-format t
2116 "*Non-nil means use `%f' float format.
2118 The advantage of using float format is that ebnf2ps generates a little short
2121 If it occurs the error message:
2123 Invalid format operation %f
2125 when executing ebnf2ps, set `ebnf-use-float-format' to nil."
2131 (defcustom ebnf-stop-on-error nil
2132 "*Non-nil means signal error and stop. Otherwise, signal error and continue."
2138 (defcustom ebnf-yac-ignore-error-recovery nil
2139 "*Non-nil means ignore error recovery.
2141 It's only used when `ebnf-syntax' is `yacc'."
2144 :group
'ebnf-syntactic
)
2147 (defcustom ebnf-ignore-empty-rule nil
2148 "*Non-nil means ignore empty rules.
2150 It's interesting to set this variable if your Yacc/Bison grammar has a lot of
2151 middle action rule."
2154 :group
'ebnf-optimization
)
2157 (defcustom ebnf-optimize nil
2158 "*Non-nil means optimize syntactic chart of rules.
2160 The following optimizations are done:
2163 1. A = B | A C. ==> A = B {C}*.
2164 2. A = B | A B. ==> A = {B}+.
2165 3. A = | A B. ==> A = {B}*.
2166 4. A = B | A C B. ==> A = {B || C}+.
2167 5. A = B | D | A C | A E. ==> A = ( B | D ) { C | E }*.
2170 6. A = B | . ==> A = [B].
2171 7. A = | B . ==> A = [B].
2174 8. A = B C | B D. ==> A = B (C | D).
2175 9. A = C B | D B. ==> A = (C | D) B.
2176 10. A = B C E | B D E. ==> A = B (C | D) E.
2178 The above optimizations are specially useful when `ebnf-syntax' is `yacc'."
2181 :group
'ebnf-optimization
)
2184 (defcustom ebnf-log nil
2185 "*Non-nil means generate log messages.
2187 The log messages are generated into the buffer *Ebnf2ps Log*.
2188 These messages are intended to help debugging ebnf2ps."
2194 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2195 ;; To make this file smaller, some commands go in a separate file.
2196 ;; But autoload them here to make the separation invisible.
2197 ;; Autoload is here to avoid compilation gripes.
2199 (autoload 'ebnf-eliminate-empty-rules
"ebnf-otz"
2200 "Eliminate empty rules.")
2202 (autoload 'ebnf-optimize
"ebnf-otz"
2203 "Syntactic chart optimizer.")
2205 (autoload 'ebnf-otz-initialize
"ebnf-otz"
2206 "Initialize optimizer.")
2209 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2214 (defun ebnf-customize ()
2215 "Customization for ebnf group."
2217 (customize-group 'ebnf2ps
))
2220 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2225 (defun ebnf-print-directory (&optional directory
)
2226 "Generate and print a PostScript syntactic chart image of DIRECTORY.
2228 If DIRECTORY is nil, it's used `default-directory'.
2230 The files in DIRECTORY that matches `ebnf-file-suffix-regexp' (which see) are
2233 See also `ebnf-print-buffer'."
2235 (list (read-file-name "Directory containing EBNF files (print): "
2236 nil default-directory
)))
2237 (ebnf-log-header "(ebnf-print-directory %S)" directory
)
2238 (ebnf-directory 'ebnf-print-buffer directory
))
2242 (defun ebnf-print-file (file &optional do-not-kill-buffer-when-done
)
2243 "Generate and print a PostScript syntactic chart image of the file FILE.
2245 If optional arg DO-NOT-KILL-BUFFER-WHEN-DONE is non-nil, the buffer isn't
2246 killed after process termination.
2248 See also `ebnf-print-buffer'."
2249 (interactive "fEBNF file to generate PostScript and print from: ")
2250 (ebnf-log-header "(ebnf-print-file %S %S)" file do-not-kill-buffer-when-done
)
2251 (ebnf-file 'ebnf-print-buffer file do-not-kill-buffer-when-done
))
2255 (defun ebnf-print-buffer (&optional filename
)
2256 "Generate and print a PostScript syntactic chart image of the buffer.
2258 When called with a numeric prefix argument (C-u), prompts the user for
2259 the name of a file to save the PostScript image in, instead of sending
2262 More specifically, the FILENAME argument is treated as follows: if it
2263 is nil, send the image to the printer. If FILENAME is a string, save
2264 the PostScript image in a file with that name. If FILENAME is a
2265 number, prompt the user for the name of the file to save in."
2266 (interactive (list (ps-print-preprint current-prefix-arg
)))
2267 (ebnf-log-header "(ebnf-print-buffer %S)" filename
)
2268 (ebnf-print-region (point-min) (point-max) filename
))
2272 (defun ebnf-print-region (from to
&optional filename
)
2273 "Generate and print a PostScript syntactic chart image of the region.
2274 Like `ebnf-print-buffer', but prints just the current region."
2275 (interactive (list (point) (mark) (ps-print-preprint current-prefix-arg
)))
2276 (ebnf-log-header "(ebnf-print-region %S %S %S)" from to filename
)
2277 (run-hooks 'ebnf-hook
)
2278 (or (ebnf-spool-region from to
)
2279 (ps-do-despool filename
)))
2283 (defun ebnf-spool-directory (&optional directory
)
2284 "Generate and spool a PostScript syntactic chart image of DIRECTORY.
2286 If DIRECTORY is nil, it's used `default-directory'.
2288 The files in DIRECTORY that matches `ebnf-file-suffix-regexp' (which see) are
2291 See also `ebnf-spool-buffer'."
2293 (list (read-file-name "Directory containing EBNF files (spool): "
2294 nil default-directory
)))
2295 (ebnf-log-header "(ebnf-spool-directory %S)" directory
)
2296 (ebnf-directory 'ebnf-spool-buffer directory
))
2300 (defun ebnf-spool-file (file &optional do-not-kill-buffer-when-done
)
2301 "Generate and spool a PostScript syntactic chart image of the file FILE.
2303 If optional arg DO-NOT-KILL-BUFFER-WHEN-DONE is non-nil, the buffer isn't
2304 killed after process termination.
2306 See also `ebnf-spool-buffer'."
2307 (interactive "fEBNF file to generate PostScript and spool from: ")
2308 (ebnf-log-header "(ebnf-spool-file %S %S)" file do-not-kill-buffer-when-done
)
2309 (ebnf-file 'ebnf-spool-buffer file do-not-kill-buffer-when-done
))
2313 (defun ebnf-spool-buffer ()
2314 "Generate and spool a PostScript syntactic chart image of the buffer.
2315 Like `ebnf-print-buffer' except that the PostScript image is saved in a
2316 local buffer to be sent to the printer later.
2318 Use the command `ebnf-despool' to send the spooled images to the printer."
2320 (ebnf-log-header "(ebnf-spool-buffer)")
2321 (ebnf-spool-region (point-min) (point-max)))
2325 (defun ebnf-spool-region (from to
)
2326 "Generate a PostScript syntactic chart image of the region and spool locally.
2327 Like `ebnf-spool-buffer', but spools just the current region.
2329 Use the command `ebnf-despool' to send the spooled images to the printer."
2331 (ebnf-log-header "(ebnf-spool-region %S)" from to
)
2332 (ebnf-generate-region from to
'ebnf-generate
))
2336 (defun ebnf-eps-directory (&optional directory
)
2337 "Generate EPS files from EBNF files in DIRECTORY.
2339 If DIRECTORY is nil, it's used `default-directory'.
2341 The files in DIRECTORY that matches `ebnf-file-suffix-regexp' (which see) are
2344 See also `ebnf-eps-buffer'."
2346 (list (read-file-name "Directory containing EBNF files (EPS): "
2347 nil default-directory
)))
2348 (ebnf-log-header "(ebnf-eps-directory %S)" directory
)
2349 (ebnf-directory 'ebnf-eps-buffer directory
))
2353 (defun ebnf-eps-file (file &optional do-not-kill-buffer-when-done
)
2354 "Generate an EPS file from EBNF file FILE.
2356 If optional arg DO-NOT-KILL-BUFFER-WHEN-DONE is non-nil, the buffer isn't
2357 killed after EPS generation.
2359 See also `ebnf-eps-buffer'."
2360 (interactive "fEBNF file to generate EPS file from: ")
2361 (ebnf-log-header "(ebnf-eps-file %S %S)" file do-not-kill-buffer-when-done
)
2362 (ebnf-file 'ebnf-eps-buffer file do-not-kill-buffer-when-done
))
2366 (defun ebnf-eps-buffer ()
2367 "Generate a PostScript syntactic chart image of the buffer in an EPS file.
2369 Generate an EPS file for each production in the buffer.
2370 The EPS file name has the following form:
2372 <PREFIX><PRODUCTION>.eps
2374 <PREFIX> is given by variable `ebnf-eps-prefix'.
2375 The default value is \"ebnf--\".
2377 <PRODUCTION> is the production name.
2378 Some characters in the production file name are replaced to
2379 produce a valid file name. For example, the production name
2380 \"A/B + C\" is modified to produce \"A_B_+_C\", and the EPS
2381 file name used in this case will be \"ebnf--A_B_+_C.eps\".
2383 WARNING: This function does *NOT* ask any confirmation to override existing
2386 (ebnf-log-header "(ebnf-eps-buffer)")
2387 (ebnf-eps-region (point-min) (point-max)))
2391 (defun ebnf-eps-region (from to
)
2392 "Generate a PostScript syntactic chart image of the region in an EPS file.
2394 Generate an EPS file for each production in the region.
2395 The EPS file name has the following form:
2397 <PREFIX><PRODUCTION>.eps
2399 <PREFIX> is given by variable `ebnf-eps-prefix'.
2400 The default value is \"ebnf--\".
2402 <PRODUCTION> is the production name.
2403 Some characters in the production file name are replaced to
2404 produce a valid file name. For example, the production name
2405 \"A/B + C\" is modified to produce \"A_B_+_C\", and the EPS
2406 file name used in this case will be \"ebnf--A_B_+_C.eps\".
2408 WARNING: This function does *NOT* ask any confirmation to override existing
2411 (ebnf-log-header "(ebnf-eps-region %S %S)" from to
)
2412 (let ((ebnf-eps-executing t
))
2413 (ebnf-generate-region from to
'ebnf-generate-eps
)))
2417 (defalias 'ebnf-despool
'ps-despool
)
2421 (defun ebnf-syntax-directory (&optional directory
)
2422 "Do a syntactic analysis of the files in DIRECTORY.
2424 If DIRECTORY is nil, use `default-directory'.
2426 Only the files in DIRECTORY that match `ebnf-file-suffix-regexp' (which see)
2429 See also `ebnf-syntax-buffer'."
2431 (list (read-file-name "Directory containing EBNF files (syntax): "
2432 nil default-directory
)))
2433 (ebnf-log-header "(ebnf-syntax-directory %S)" directory
)
2434 (ebnf-directory 'ebnf-syntax-buffer directory
))
2438 (defun ebnf-syntax-file (file &optional do-not-kill-buffer-when-done
)
2439 "Do a syntactic analysis of the named FILE.
2441 If optional arg DO-NOT-KILL-BUFFER-WHEN-DONE is non-nil, the buffer isn't
2442 killed after syntax checking.
2444 See also `ebnf-syntax-buffer'."
2445 (interactive "fEBNF file to check syntax: ")
2446 (ebnf-log-header "(ebnf-syntax-file %S %S)" file do-not-kill-buffer-when-done
)
2447 (ebnf-file 'ebnf-syntax-buffer file do-not-kill-buffer-when-done
))
2451 (defun ebnf-syntax-buffer ()
2452 "Do a syntactic analysis of the current buffer."
2454 (ebnf-log-header "(ebnf-syntax-buffer)")
2455 (ebnf-syntax-region (point-min) (point-max)))
2459 (defun ebnf-syntax-region (from to
)
2460 "Do a syntactic analysis of a region."
2462 (ebnf-log-header "(ebnf-syntax-region %S %S)" from to
)
2463 (ebnf-generate-region from to nil
))
2466 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2471 (defun ebnf-setup ()
2472 "Return the current ebnf2ps setup."
2475 ;;; ebnf2ps.el version %s
2477 ;;; Emacs version %S
2479 \(setq ebnf-special-show-delimiter %S
2480 ebnf-special-font %s
2481 ebnf-special-shape %s
2482 ebnf-special-shadow %S
2483 ebnf-special-border-width %S
2484 ebnf-special-border-color %S
2486 ebnf-except-shape %s
2487 ebnf-except-shadow %S
2488 ebnf-except-border-width %S
2489 ebnf-except-border-color %S
2491 ebnf-repeat-shape %s
2492 ebnf-repeat-shadow %S
2493 ebnf-repeat-border-width %S
2494 ebnf-repeat-border-color %S
2495 ebnf-terminal-regexp %S
2496 ebnf-case-fold-search %S
2497 ebnf-terminal-font %s
2498 ebnf-terminal-shape %s
2499 ebnf-terminal-shadow %S
2500 ebnf-terminal-border-width %S
2501 ebnf-terminal-border-color %S
2502 ebnf-non-terminal-font %s
2503 ebnf-non-terminal-shape %s
2504 ebnf-non-terminal-shadow %S
2505 ebnf-non-terminal-border-width %S
2506 ebnf-non-terminal-border-color %S
2507 ebnf-production-name-p %S
2508 ebnf-sort-production %s
2509 ebnf-production-font %s
2513 ebnf-horizontal-orientation %S
2514 ebnf-horizontal-max-height %S
2515 ebnf-production-horizontal-space %S
2516 ebnf-production-vertical-space %S
2517 ebnf-justify-sequence %s
2518 ebnf-lex-comment-char ?\\%03o
2519 ebnf-lex-eop-char ?\\%03o
2521 ebnf-iso-alternative-p %S
2522 ebnf-iso-normalize-p %S
2523 ebnf-file-suffix-regexp %S
2525 ebnf-eps-header-font %s
2527 ebnf-eps-footer-font %s
2529 ebnf-entry-percentage %S
2533 ebnf-arrow-extra-width %S
2536 ebnf-use-float-format %S
2537 ebnf-stop-on-error %S
2538 ebnf-yac-ignore-error-recovery %S
2539 ebnf-ignore-empty-rule %S
2543 ;;; ebnf2ps.el - end of settings
2547 ebnf-special-show-delimiter
2548 (ps-print-quote ebnf-special-font
)
2549 (ps-print-quote ebnf-special-shape
)
2551 ebnf-special-border-width
2552 ebnf-special-border-color
2553 (ps-print-quote ebnf-except-font
)
2554 (ps-print-quote ebnf-except-shape
)
2556 ebnf-except-border-width
2557 ebnf-except-border-color
2558 (ps-print-quote ebnf-repeat-font
)
2559 (ps-print-quote ebnf-repeat-shape
)
2561 ebnf-repeat-border-width
2562 ebnf-repeat-border-color
2563 ebnf-terminal-regexp
2564 ebnf-case-fold-search
2565 (ps-print-quote ebnf-terminal-font
)
2566 (ps-print-quote ebnf-terminal-shape
)
2567 ebnf-terminal-shadow
2568 ebnf-terminal-border-width
2569 ebnf-terminal-border-color
2570 (ps-print-quote ebnf-non-terminal-font
)
2571 (ps-print-quote ebnf-non-terminal-shape
)
2572 ebnf-non-terminal-shadow
2573 ebnf-non-terminal-border-width
2574 ebnf-non-terminal-border-color
2575 ebnf-production-name-p
2576 (ps-print-quote ebnf-sort-production
)
2577 (ps-print-quote ebnf-production-font
)
2578 (ps-print-quote ebnf-arrow-shape
)
2579 (ps-print-quote ebnf-chart-shape
)
2580 (ps-print-quote ebnf-user-arrow
)
2581 ebnf-horizontal-orientation
2582 ebnf-horizontal-max-height
2583 ebnf-production-horizontal-space
2584 ebnf-production-vertical-space
2585 (ps-print-quote ebnf-justify-sequence
)
2586 ebnf-lex-comment-char
2588 (ps-print-quote ebnf-syntax
)
2589 ebnf-iso-alternative-p
2590 ebnf-iso-normalize-p
2591 ebnf-file-suffix-regexp
2593 (ps-print-quote ebnf-eps-header-font
)
2594 (ps-print-quote ebnf-eps-header
)
2595 (ps-print-quote ebnf-eps-footer-font
)
2596 (ps-print-quote ebnf-eps-footer
)
2597 ebnf-entry-percentage
2601 ebnf-arrow-extra-width
2604 ebnf-use-float-format
2606 ebnf-yac-ignore-error-recovery
2607 ebnf-ignore-empty-rule
2612 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2616 (defvar ebnf-stack-style nil
2617 "Used in functions `ebnf-reset-style', `ebnf-push-style' and
2621 (defvar ebnf-current-style
'default
2622 "Used in functions `ebnf-apply-style' and `ebnf-push-style'.")
2625 (defconst ebnf-style-custom-list
2626 '(ebnf-special-show-delimiter
2630 ebnf-special-border-width
2631 ebnf-special-border-color
2635 ebnf-except-border-width
2636 ebnf-except-border-color
2640 ebnf-repeat-border-width
2641 ebnf-repeat-border-color
2642 ebnf-terminal-regexp
2643 ebnf-case-fold-search
2646 ebnf-terminal-shadow
2647 ebnf-terminal-border-width
2648 ebnf-terminal-border-color
2649 ebnf-non-terminal-font
2650 ebnf-non-terminal-shape
2651 ebnf-non-terminal-shadow
2652 ebnf-non-terminal-border-width
2653 ebnf-non-terminal-border-color
2654 ebnf-production-name-p
2655 ebnf-sort-production
2656 ebnf-production-font
2660 ebnf-horizontal-orientation
2661 ebnf-horizontal-max-height
2662 ebnf-production-horizontal-space
2663 ebnf-production-vertical-space
2664 ebnf-justify-sequence
2665 ebnf-lex-comment-char
2668 ebnf-iso-alternative-p
2669 ebnf-iso-normalize-p
2670 ebnf-file-suffix-regexp
2672 ebnf-eps-header-font
2674 ebnf-eps-footer-font
2676 ebnf-entry-percentage
2681 ebnf-use-float-format
2683 ebnf-yac-ignore-error-recovery
2684 ebnf-ignore-empty-rule
2686 "List of valid symbol custom variable.")
2689 (defvar ebnf-style-database
2693 (ebnf-special-show-delimiter . t
)
2694 (ebnf-special-font .
'(7 Courier
"Black" "Gray95" bold italic
))
2695 (ebnf-special-shape .
'bevel
)
2696 (ebnf-special-shadow . nil
)
2697 (ebnf-special-border-width .
0.5)
2698 (ebnf-special-border-color .
"Black")
2699 (ebnf-except-font .
'(7 Courier
"Black" "Gray90" bold italic
))
2700 (ebnf-except-shape .
'bevel
)
2701 (ebnf-except-shadow . nil
)
2702 (ebnf-except-border-width .
0.25)
2703 (ebnf-except-border-color .
"Black")
2704 (ebnf-repeat-font .
'(7 Courier
"Black" "Gray85" bold italic
))
2705 (ebnf-repeat-shape .
'bevel
)
2706 (ebnf-repeat-shadow . nil
)
2707 (ebnf-repeat-border-width .
0.0)
2708 (ebnf-repeat-border-color .
"Black")
2709 (ebnf-terminal-regexp . nil
)
2710 (ebnf-case-fold-search . nil
)
2711 (ebnf-terminal-font .
'(7 Courier
"Black" "White"))
2712 (ebnf-terminal-shape .
'miter
)
2713 (ebnf-terminal-shadow . nil
)
2714 (ebnf-terminal-border-width .
1.0)
2715 (ebnf-terminal-border-color .
"Black")
2716 (ebnf-non-terminal-font .
'(7 Helvetica
"Black" "White"))
2717 (ebnf-non-terminal-shape .
'round
)
2718 (ebnf-non-terminal-shadow . nil
)
2719 (ebnf-non-terminal-border-width .
1.0)
2720 (ebnf-non-terminal-border-color .
"Black")
2721 (ebnf-production-name-p . t
)
2722 (ebnf-sort-production . nil
)
2723 (ebnf-production-font .
'(10 Helvetica
"Black" "White" bold
))
2724 (ebnf-arrow-shape .
'hollow
)
2725 (ebnf-chart-shape .
'round
)
2726 (ebnf-user-arrow . nil
)
2727 (ebnf-horizontal-orientation . nil
)
2728 (ebnf-horizontal-max-height . nil
)
2729 (ebnf-production-horizontal-space .
0.0)
2730 (ebnf-production-vertical-space .
0.0)
2731 (ebnf-justify-sequence .
'center
)
2732 (ebnf-lex-comment-char . ?\
;)
2733 (ebnf-lex-eop-char . ?.
)
2734 (ebnf-syntax .
'ebnf
)
2735 (ebnf-iso-alternative-p . nil
)
2736 (ebnf-iso-normalize-p . nil
)
2737 (ebnf-file-suffix-regexp .
"\.[Bb][Nn][Ff]$")
2738 (ebnf-eps-prefix .
"ebnf--")
2739 (ebnf-eps-header-font .
'(11 Helvetica
"Black" "White" bold
))
2740 (ebnf-eps-header . nil
)
2741 (ebnf-eps-footer-font .
'(7 Helvetica
"Black" "White" bold
))
2742 (ebnf-eps-footer . nil
)
2743 (ebnf-entry-percentage .
0.5)
2744 (ebnf-color-p .
(or (fboundp 'x-color-values
) ; Emacs
2745 (fboundp 'color-instance-rgb-components
))) ; XEmacs
2746 (ebnf-line-width .
1.0)
2747 (ebnf-line-color .
"Black")
2748 (ebnf-debug-ps . nil
)
2749 (ebnf-use-float-format . t
)
2750 (ebnf-stop-on-error . nil
)
2751 (ebnf-yac-ignore-error-recovery . nil
)
2752 (ebnf-ignore-empty-rule . nil
)
2753 (ebnf-optimize . nil
))
2754 ;; Happy EBNF default
2757 (ebnf-justify-sequence .
'left
)
2758 (ebnf-lex-comment-char . ?\
#)
2759 (ebnf-lex-eop-char . ?\
;))
2763 (ebnf-syntax .
'abnf
))
2767 (ebnf-syntax .
'iso-ebnf
))
2768 ;; Yacc/Bison default
2771 (ebnf-syntax .
'yacc
))
2775 (ebnf-syntax .
'ebnfx
))
2779 (ebnf-syntax .
'dtd
))
2783 Each element has the following form:
2785 (NAME INHERITS (VAR . VALUE)...)
2789 NAME is a symbol name style.
2791 INHERITS is a symbol name style from which the current style inherits
2792 the context. If INHERITS is nil, then there is no inheritance.
2794 This is a simple inheritance of style: if you declare that
2795 style A inherits from style B, all settings of B are applied
2796 first, and then the settings of A are applied. This is useful
2797 when you wish to modify some aspects of an existing style, but
2798 at the same time wish to keep it unmodified.
2800 VAR is a valid ebnf2ps symbol custom variable.
2801 See `ebnf-style-custom-list' for valid symbol variables.
2803 VALUE is a sexp which will be evaluated to set the value of VAR.
2804 Don't forget to quote symbols and constant lists.
2805 See `default' style for an example.
2807 Don't use this variable directly. Use functions `ebnf-insert-style',
2808 `ebnf-delete-style' and `ebnf-merge-style'.")
2811 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2816 (defun ebnf-find-style (name)
2817 "Return style definition if NAME is already defined; otherwise, return nil.
2819 See `ebnf-style-database' documentation."
2820 (interactive "SStyle name: ")
2821 (assoc name ebnf-style-database
))
2825 (defun ebnf-insert-style (name inherits
&rest values
)
2826 "Insert a new style NAME with inheritance INHERITS and values VALUES.
2828 See `ebnf-style-database' documentation."
2829 (interactive "SStyle name: \nSStyle inherits from: \nXStyle values: ")
2830 (and (assoc name ebnf-style-database
)
2831 (error "Style name already exists: %s" name
))
2832 (or (assoc inherits ebnf-style-database
)
2833 (error "Style inheritance name doesn't exist: %s" inherits
))
2834 (setq ebnf-style-database
2835 (cons (cons name
(cons inherits
(ebnf-check-style-values values
)))
2836 ebnf-style-database
)))
2840 (defun ebnf-delete-style (name)
2843 See `ebnf-style-database' documentation."
2844 (interactive "SDelete style name: ")
2845 (or (assoc name ebnf-style-database
)
2846 (error "Style name doesn't exist: %s" name
))
2847 (let ((db ebnf-style-database
))
2849 (and (eq (nth 1 (car db
)) name
)
2850 (error "Style name `%s' is inherited by `%s' style"
2851 name
(nth 0 (car db
))))
2852 (setq db
(cdr db
))))
2853 (setq ebnf-style-database
(assq-delete-all name ebnf-style-database
)))
2857 (defun ebnf-merge-style (name &rest values
)
2858 "Merge values of style NAME with style VALUES.
2860 See `ebnf-style-database' documentation."
2861 (interactive "SStyle name: \nXStyle values: ")
2862 (let ((style (or (assoc name ebnf-style-database
)
2863 (error "Style name doesn't exist: %s" name
)))
2864 (merge (ebnf-check-style-values values
))
2866 ;; modify value of existing variables
2867 (setq val
(nthcdr 2 style
))
2869 (setq check
(car merge
)
2871 elt
(assoc (car check
) val
))
2873 (setcdr elt
(cdr check
))
2874 (setq new
(cons check new
))))
2875 ;; insert new variables
2876 (nconc style
(nreverse new
))))
2880 (defun ebnf-apply-style (style)
2881 "Set STYLE as the current style.
2883 Returns the old style symbol.
2885 See `ebnf-style-database' documentation."
2886 (interactive "SApply style: ")
2889 (and (ebnf-apply-style1 style
)
2890 (setq ebnf-current-style style
))))
2894 (defun ebnf-reset-style (&optional style
)
2895 "Reset current style.
2897 Returns the old style symbol.
2899 See `ebnf-style-database' documentation."
2900 (interactive "SReset style: ")
2901 (setq ebnf-stack-style nil
)
2902 (ebnf-apply-style (or style
'default
)))
2906 (defun ebnf-push-style (&optional style
)
2907 "Push the current style onto a stack and set STYLE as the current style.
2909 Returns the old style symbol.
2911 See also `ebnf-pop-style'.
2913 See `ebnf-style-database' documentation."
2914 (interactive "SPush style: ")
2917 (setq ebnf-stack-style
(cons ebnf-current-style ebnf-stack-style
))
2919 (ebnf-apply-style style
))))
2923 (defun ebnf-pop-style ()
2924 "Pop a style from the stack of pushed styles and set it as the current style.
2926 Returns the old style symbol.
2928 See also `ebnf-push-style'.
2930 See `ebnf-style-database' documentation."
2933 (ebnf-apply-style (car ebnf-stack-style
))
2934 (setq ebnf-stack-style
(cdr ebnf-stack-style
))))
2937 (defun ebnf-apply-style1 (style)
2938 (let ((value (cdr (assoc style ebnf-style-database
))))
2941 (and (car value
) (ebnf-apply-style1 (car value
)))
2942 (while (setq value
(cdr value
))
2943 (set (caar value
) (eval (cdar value
)))))))
2946 (defun ebnf-check-style-values (values)
2949 (and (memq (caar values
) ebnf-style-custom-list
)
2950 (setq style
(cons (car values
) style
)))
2951 (setq values
(cdr values
)))
2955 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2956 ;; Internal variables
2959 (defvar ebnf-eps-buffer-name
" *EPS*")
2960 (defvar ebnf-parser-func nil
)
2961 (defvar ebnf-eps-executing nil
)
2962 (defvar ebnf-eps-header-comment nil
)
2963 (defvar ebnf-eps-footer-comment nil
)
2964 (defvar ebnf-eps-upper-x
0.0)
2965 (make-variable-buffer-local 'ebnf-eps-upper-x
)
2966 (defvar ebnf-eps-upper-y
0.0)
2967 (make-variable-buffer-local 'ebnf-eps-upper-y
)
2968 (defvar ebnf-eps-prod-width
0.0)
2969 (make-variable-buffer-local 'ebnf-eps-prod-width
)
2970 (defvar ebnf-eps-max-height
0.0)
2971 (make-variable-buffer-local 'ebnf-eps-max-height
)
2972 (defvar ebnf-eps-max-width
0.0)
2973 (make-variable-buffer-local 'ebnf-eps-max-width
)
2976 (defvar ebnf-eps-context nil
2977 "List of EPS file name during parsing.
2979 See section \"Actions in Comments\" in ebnf2ps documentation.")
2982 (defvar ebnf-eps-file-alist nil
2983 "Alist associating file name with EPS header and footer.
2985 Each element has the following form:
2987 (EPS-FILENAME HEADER FOOTER)
2989 EPS-FILENAME is the EPS file name.
2990 HEADER is the header string or nil.
2991 FOOTER is the footer string or nil.
2993 It's generated during parsing and used during EPS generation.
2995 See `ebnf-eps-context' and section \"Actions in Comments\" in ebnf2ps
2999 (defvar ebnf-eps-production-list nil
3000 "Alist associating production name with EPS file name list.
3002 Each element has the following form:
3004 (PRODUCTION EPS-FILENAME...)
3006 PRODUCTION is the production name.
3007 EPS-FILENAME is the EPS file name.
3009 This is generated during parsing and used during EPS generation.
3011 See `ebnf-eps-context' and section \"Actions in Comments\" in ebnf2ps
3015 (defconst ebnf-arrow-shape-alist
3023 (semi-up-hollow .
7)
3025 (semi-down-hollow .
9)
3026 (semi-down-full .
10)
3028 "Alist associating values for `ebnf-arrow-shape'.
3030 See documentation for `ebnf-arrow-shape'.")
3033 (defconst ebnf-terminal-shape-alist
3037 "Alist associating values from `ebnf-terminal-shape' to a bit vector.
3039 See documentation for `ebnf-terminal-shape', `ebnf-non-terminal-shape' and
3040 `ebnf-chart-shape'.")
3043 (defvar ebnf-limit nil
)
3044 (defvar ebnf-action nil
)
3045 (defvar ebnf-action-list nil
)
3048 (defvar ebnf-default-p nil
)
3051 (defvar ebnf-font-height-P
0)
3052 (defvar ebnf-font-height-T
0)
3053 (defvar ebnf-font-height-NT
0)
3054 (defvar ebnf-font-height-S
0)
3055 (defvar ebnf-font-height-E
0)
3056 (defvar ebnf-font-height-R
0)
3057 (defvar ebnf-font-width-P
0)
3058 (defvar ebnf-font-width-T
0)
3059 (defvar ebnf-font-width-NT
0)
3060 (defvar ebnf-font-width-S
0)
3061 (defvar ebnf-font-width-E
0)
3062 (defvar ebnf-font-width-R
0)
3063 (defvar ebnf-space-T
0)
3064 (defvar ebnf-space-NT
0)
3065 (defvar ebnf-space-S
0)
3066 (defvar ebnf-space-E
0)
3067 (defvar ebnf-space-R
0)
3070 (defvar ebnf-basic-width-extra
0)
3071 (defvar ebnf-basic-width
0)
3072 (defvar ebnf-basic-height
0)
3073 (defvar ebnf-basic-empty-height
0)
3074 (defvar ebnf-vertical-space
0)
3075 (defvar ebnf-horizontal-space
0)
3078 (defvar ebnf-settings nil
)
3079 (defvar ebnf-fonts-required nil
)
3082 (defconst ebnf-debug
3084 % === begin EBNF procedures to help debugging
3086 % Mark visually current point: string debug
3090 gsave -s- show grestore
3102 % Show number value: number string debug-number
3105 20 0 rmoveto show ([) show 60 string cvs show (]) show
3109 % === end EBNF procedures to help debugging
3112 "This is intended to help debugging PostScript programming.")
3115 (defconst ebnf-prologue
3117 % === begin EBNF engine
3119 % --- Basic Definitions
3122 /SpaceS FontHeight 0.5 mul def
3123 /HeightS FontHeight FontHeight add def
3126 /SpaceE FontHeight 0.5 mul def
3127 /HeightE FontHeight FontHeight add def
3130 /SpaceR FontHeight 0.5 mul def
3131 /HeightR FontHeight FontHeight add def
3134 /SpaceT FontHeight 0.5 mul def
3135 /HeightT FontHeight FontHeight add def
3138 /SpaceNT FontHeight 0.5 mul def
3139 /HeightNT FontHeight FontHeight add def
3141 /T HeightT HeightNT add 0.5 mul def
3143 /hT2 hT 0.5 mul ArrowScale mul def
3144 /hT4 hT 0.25 mul ArrowScale mul def
3146 /Er 0.1 def % Error factor
3149 /c{currentpoint}bind def
3150 /xyi{/xi c /yi exch def def}bind def
3151 /xyo{/xo c /yo exch def def}bind def
3152 /xyp{/xp c /yp exch def def}bind def
3153 /xyt{/xt c /yt exch def def}bind def
3155 % vertical movement: x y height vm
3156 /vm{add moveto}bind def
3158 % horizontal movement: x y width hm
3159 /hm{3 -1 roll exch add exch moveto}bind def
3161 % set color: [R G B] SetRGB
3162 /SetRGB{aload pop setrgbcolor}bind def
3164 % filling gray area: gray-scale FillGray
3165 /FillGray{gsave setgray fill grestore}bind def
3167 % filling color area: [R G B] FillRGB
3168 /FillRGB{gsave SetRGB fill grestore}bind def
3170 /Stroke{LineWidth setlinewidth LineColor SetRGB stroke}bind def
3171 /StrokeShape{borderwidth setlinewidth bordercolor SetRGB stroke}bind def
3172 /Gstroke{gsave Stroke grestore}bind def
3174 % Empty Line: width EL
3175 /EL{0 rlineto Gstroke}bind def
3179 /Down{hT2 neg hT4 neg rlineto}bind def
3182 {hT2 neg hT4 rmoveto
3187 /ArrowPath{c newpath moveto Arrow closepath}bind def
3211 {hT2 neg hT4 rlineto} % 1 - semi-up
3212 {Down} % 2 - semi-down
3213 {Arrow} % 3 - simple
3214 {Gstroke ArrowPath} % 4 - transparent
3215 {Gstroke ArrowPath 1 FillGray} % 5 - hollow
3216 {Gstroke ArrowPath LineColor FillRGB} % 6 - full
3217 {Gstroke UpPath 1 FillGray} % 7 - semi-up-hollow
3218 {Gstroke UpPath LineColor FillRGB} % 8 - semi-up-full
3219 {Gstroke DownPath 1 FillGray} % 9 - semi-down-hollow
3220 {Gstroke DownPath LineColor FillRGB} % 10 - semi-down-full
3221 {Gstroke gsave UserArrow grestore} % 11 - user
3227 RA-vector ArrowShape get exec
3230 ExtraWidth 0 rmoveto
3233 % rotation DrawArrow
3248 /LA{180 DrawArrow}def
3255 /UA{90 DrawArrow}def
3262 /DA{270 DrawArrow}def
3266 %>corner Right Descendent: height arrow corner_RD
3268 % / height > 0 | 0 - none
3270 % * ---------- | 2 - left
3289 h 0 gt{DA}{UA}ifelse
3294 [{cRD0-vector arrow get exec} % 0 - miter
3295 {0 0 0 h hT h rcurveto} % 1 - rounded
3296 {hT h rlineto} % 2 - bevel
3300 {/arrow exch def /h exch def
3301 cRD-vector ChartShape get exec
3305 %>corner Right Ascendent: height arrow corner_RA
3307 % | height > 0 | 0 - none
3309 % *- ---------- | 2 - left
3327 h 0 gt{DA}{UA}ifelse
3333 [{cRA0-vector arrow get exec} % 0 - miter
3334 {0 0 hT 0 hT h rcurveto} % 1 - rounded
3335 {hT h rlineto} % 2 - bevel
3339 {/arrow exch def /h exch def
3340 cRA-vector ChartShape get exec
3344 %>corner Left Descendent: height arrow corner_LD
3346 % \\ height > 0 | 0 - none
3348 % * ---------- | 2 - left
3357 {hT neg h rmoveto xyi
3365 {hT neg h rmoveto xyi
3367 h 0 gt{DA}{UA}ifelse
3372 [{cLD0-vector arrow get exec} % 0 - miter
3373 {0 0 0 h hT neg h rcurveto} % 1 - rounded
3374 {hT neg h rlineto} % 2 - bevel
3378 {/arrow exch def /h exch def
3379 cLD-vector ChartShape get exec
3383 %>corner Left Ascendent: height arrow corner_LA
3385 % | height > 0 | 0 - none
3387 % -* ---------- | 2 - left
3396 {hT neg h rmoveto xyi
3404 {hT neg h rmoveto xyi
3405 h 0 gt{DA}{UA}ifelse
3411 [{cLA0-vector arrow get exec} % 0 - miter
3412 {0 0 hT neg 0 hT neg h rcurveto} % 1 - rounded
3413 {hT neg h rlineto} % 2 - bevel
3417 {/arrow exch def /h exch def
3418 cLA-vector ChartShape get exec
3424 % height prepare-height |- line_height corner_height corner_height
3428 {T add hT neg}ifelse
3432 %>Left Alternative: height LAlt
3459 %>Left Loop: height LLoop
3478 %>Right Alternative: height RAlt
3492 {T neg exch rlineto}
3505 %>Right Loop: height RLoop
3524 % --- Terminal, Non-terminal and Special Basics
3526 % string width prepare-width |- string
3529 dup stringwidth pop space add space add width exch sub ExtraWidth sub 0.5 mul
3533 % string width begin-right
3543 {xo width add Er add yo moveto
3548 % string width begin-left
3557 {xo width add Er add yo moveto
3570 {/half YY yy sub 0.5 mul abs def
3571 xx half add YY moveto
3572 0 0 half neg 0 half neg half neg rcurveto
3573 0 0 0 half neg half half neg rcurveto
3574 XX xx sub abs half sub half sub 0 rlineto
3575 0 0 half 0 half half rcurveto
3576 0 0 0 half half neg half rcurveto}
3578 {/quarter YY yy sub 0.25 mul abs def
3579 xx quarter add YY moveto
3580 quarter neg quarter neg rlineto
3581 0 quarter quarter add neg rlineto
3582 quarter quarter neg rlineto
3583 XX xx sub abs quarter sub quarter sub 0 rlineto
3584 quarter quarter rlineto
3585 0 quarter quarter add rlineto
3586 quarter neg quarter rlineto}
3591 ShapePath-vector shape get exec
3597 Xshadow Xshadow add Xshadow add
3598 Yshadow Yshadow add Yshadow add translate
3612 % string SBound |- string
3614 {/xx c dup /yy exch def
3615 FontHeight add /YY exch def def
3616 dup stringwidth pop xx add /XX exch def
3618 {/yy yy YShadow add def
3619 /XX XX XShadow add def
3628 /XX XX space add space add def
3629 /YY YY space add def
3630 /yy yy space sub def
3631 shadow{doShapeShadow}if
3633 space Descent abs rmoveto
3640 % TeRminal: string TR
3642 {/Effect EffectT def
3644 /shapecolor BackgroundT def
3645 /borderwidth BorderWidthT def
3646 /bordercolor BorderColorT def
3647 /foreground ForegroundT def
3652 %>Right Terminal: string width RT |- x y
3663 %>Left Terminal: string width LT |- x y
3674 %>Right Terminal Default: string width RTD |- x y
3676 {/-save- BorderWidthT def
3677 /BorderWidthT BorderWidthT DefaultWidth add def
3679 /BorderWidthT -save- def
3682 %>Left Terminal Default: string width LTD |- x y
3684 {/-save- BorderWidthT def
3685 /BorderWidthT BorderWidthT DefaultWidth add def
3687 /BorderWidthT -save- def
3692 % Non-Terminal: string NT
3694 {/Effect EffectNT def
3696 /shapecolor BackgroundNT def
3697 /borderwidth BorderWidthNT def
3698 /bordercolor BorderColorNT def
3699 /foreground ForegroundNT def
3700 /shadow ShadowNT def
3704 %>Right Non-Terminal: string width RNT |- x y
3715 %>Left Non-Terminal: string width LNT |- x y
3726 %>Right Non-Terminal Default: string width RNTD |- x y
3728 {/-save- BorderWidthNT def
3729 /BorderWidthNT BorderWidthNT DefaultWidth add def
3731 /BorderWidthNT -save- def
3734 %>Left Non-Terminal Default: string width LNTD |- x y
3736 {/-save- BorderWidthNT def
3737 /BorderWidthNT BorderWidthNT DefaultWidth add def
3739 /BorderWidthNT -save- def
3744 % SPecial: string SP
3746 {/Effect EffectS def
3748 /shapecolor BackgroundS def
3749 /borderwidth BorderWidthS def
3750 /bordercolor BorderColorS def
3751 /foreground ForegroundS def
3756 %>Right SPecial: string width RSP |- x y
3767 %>Left SPecial: string width LSP |- x y
3778 %>Right SPecial Default: string width RSPD |- x y
3780 {/-save- BorderWidthS def
3781 /BorderWidthS BorderWidthS DefaultWidth add def
3783 /BorderWidthS -save- def
3786 %>Left SPecial Default: string width LSPD |- x y
3788 {/-save- BorderWidthS def
3789 /BorderWidthS BorderWidthS DefaultWidth add def
3791 /BorderWidthS -save- def
3794 % --- Repeat and Except basics
3797 {/w width rwidth sub 0.5 mul def
3802 /xx c entry add /YY exch def def
3803 /yy YY height sub def
3804 /XX xx rwidth add def
3805 shadow{doShapeShadow}if
3828 % entry height width rwidth begin-repeat
3838 /shapecolor BackgroundR def
3839 /borderwidth BorderWidthR def
3840 /bordercolor BorderColorR def
3841 /foreground ForegroundR def
3846 % string end-repeat |- x y
3849 space Descent rmoveto
3853 exch space add exch moveto
3857 %>Right RePeat: string entry height width rwidth RRP |- x y
3858 /RRP{begin-repeat right-direction end-repeat}def
3860 %>Left RePeat: string entry height width rwidth LRP |- x y
3861 /LRP{begin-repeat left-direction end-repeat}def
3865 % entry height width rwidth begin-except
3875 /shapecolor BackgroundE def
3876 /borderwidth BorderWidthE def
3877 /bordercolor BorderColorE def
3878 /foreground ForegroundE def
3883 % x-width end-except |- x y
3886 space space add add Descent rmoveto
3887 (-) foreground SetRGB S
3893 %>Right EXcept: x-width entry height width rwidth REX |- x y
3894 /REX{begin-except right-direction end-except}def
3896 %>Left EXcept: x-width entry height width rwidth LEX |- x y
3897 /LEX{begin-except left-direction end-except}def
3901 %>Beginning Of Sequence: BOS |- x y
3902 /BOS{currentpoint}bind def
3904 %>End Of Sequence: x y x1 y1 EOS |- x y
3905 /EOS{pop pop}bind def
3909 %>Beginning Of Production: string width height BOP |- y x
3912 neg yp add /yw exch def
3913 xp add T sub /xw exch def
3914 dup length 0 gt % empty string ==> no production name
3915 {/Effect EffectP def
3916 /fP F ForegroundP SetRGB BackgroundP aload pop true BG S
3926 %>End Of Production: y x delta EOP
3927 /EOPH{add exch moveto}bind def % horizontal
3928 /EOPV{exch pop sub 0 exch moveto}bind def % vertical
3930 % --- Empty Alternative
3932 %>Empty Alternative: width EA |- x y
3943 %>AlTernative: h1 h2 ... hn n width AT |- x y
3945 {xyo xo add /xw exch def
3957 %>OPtional: height width OP |- x y
3974 %>One or More: height width OM |- x y
3988 %>Zero or More: h2 h1 width ZM |- x y
3998 yo add xo T add exch moveto
4002 % === end EBNF engine
4005 "EBNF PostScript prologue")
4008 (defconst ebnf-eps-prologue
4010 /#ebnf2ps#dict 230 dict def
4013 % Initiliaze variables to avoid name-conflicting with document variables.
4014 % This is the case when using `bind' operator.
4015 /-fillp- 0 def /h 0 def
4016 /-ox- 0 def /half 0 def
4017 /-oy- 0 def /height 0 def
4018 /-save- 0 def /ow 0 def
4019 /Ascent 0 def /quarter 0 def
4020 /Descent 0 def /rXX 0 def
4021 /Effect 0 def /rYY 0 def
4022 /FontHeight 0 def /rwidth 0 def
4023 /LineThickness 0 def /rxx 0 def
4024 /OverlinePosition 0 def /ryy 0 def
4025 /SpaceBackground 0 def /shadow 0 def
4026 /StrikeoutPosition 0 def /shape 0 def
4027 /UnderlinePosition 0 def /shapecolor 0 def
4028 /XBox 0 def /space 0 def
4029 /XX 0 def /st 1 string def
4030 /Xshadow 0 def /w 0 def
4031 /YBox 0 def /width 0 def
4033 /Yshadow 0 def /xo 0 def
4034 /arrow 0 def /xp 0 def
4035 /bg false def /xt 0 def
4036 /bgcolor 0 def /xw 0 def
4037 /bordercolor 0 def /xx 0 def
4038 /borderwidth 0 def /yi 0 def
4040 /entry 0 def /yp 0 def
4041 /foreground 0 def /yt 0 def
4045 % ISOLatin1Encoding stolen from ps_init.ps in GhostScript 2.6.1.4:
4046 /ISOLatin1Encoding where
4048 {% -- The ISO Latin-1 encoding vector isn't known, so define it.
4049 % -- The first half is the same as the standard encoding,
4050 % -- except for minus instead of hyphen at code 055.
4052 StandardEncoding 0 45 getinterval aload pop
4054 StandardEncoding 46 82 getinterval aload pop
4055 %*** NOTE: the following are missing in the Adobe documentation,
4056 %*** but appear in the displayed table:
4057 %*** macron at 0225, dieresis at 0230, cedilla at 0233, space at 0240.
4059 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
4060 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
4061 /dotlessi /grave /acute /circumflex /tilde /macron /breve /dotaccent
4062 /dieresis /.notdef /ring /cedilla /.notdef /hungarumlaut /ogonek /caron
4064 /space /exclamdown /cent /sterling
4065 /currency /yen /brokenbar /section
4066 /dieresis /copyright /ordfeminine /guillemotleft
4067 /logicalnot /hyphen /registered /macron
4068 /degree /plusminus /twosuperior /threesuperior
4069 /acute /mu /paragraph /periodcentered
4070 /cedilla /onesuperior /ordmasculine /guillemotright
4071 /onequarter /onehalf /threequarters /questiondown
4073 /Agrave /Aacute /Acircumflex /Atilde
4074 /Adieresis /Aring /AE /Ccedilla
4075 /Egrave /Eacute /Ecircumflex /Edieresis
4076 /Igrave /Iacute /Icircumflex /Idieresis
4077 /Eth /Ntilde /Ograve /Oacute
4078 /Ocircumflex /Otilde /Odieresis /multiply
4079 /Oslash /Ugrave /Uacute /Ucircumflex
4080 /Udieresis /Yacute /Thorn /germandbls
4082 /agrave /aacute /acircumflex /atilde
4083 /adieresis /aring /ae /ccedilla
4084 /egrave /eacute /ecircumflex /edieresis
4085 /igrave /iacute /icircumflex /idieresis
4086 /eth /ntilde /ograve /oacute
4087 /ocircumflex /otilde /odieresis /divide
4088 /oslash /ugrave /uacute /ucircumflex
4089 /udieresis /yacute /thorn /ydieresis
4093 /reencodeFontISO %def
4095 length 12 add dict % Make a new font (a new dict the same size
4096 % as the old one) with room for our new symbols.
4098 begin % Make the new font the current dictionary.
4100 {def}{pop pop}ifelse
4101 }forall % Copy each of the symbols from the old dictionary
4102 % to the new one except for the font ID.
4104 currentdict /FontType get 0 ne
4105 {/Encoding ISOLatin1Encoding def}if % Override the encoding with
4106 % the ISOLatin1 encoding.
4108 % Use the font's bounding box to determine the ascent, descent,
4109 % and overall height; don't forget that these values have to be
4110 % transformed using the font's matrix.
4117 % | | | | Ascent (usually > 0)
4119 % (0 0) -> +--+----+-------->
4121 % | | v Descent (usually < 0)
4122 % (x1 y1) --> +----+ - -
4124 currentdict /FontType get 0 ne
4125 {/FontBBox load aload pop % -- x1 y1 x2 y2
4126 FontMatrix transform /Ascent exch def pop
4127 FontMatrix transform /Descent exch def pop}
4128 {/PrimaryFont FDepVector 0 get def
4129 PrimaryFont /FontBBox get aload pop
4130 PrimaryFont /FontMatrix get transform /Ascent exch def pop
4131 PrimaryFont /FontMatrix get transform /Descent exch def pop
4134 /FontHeight Ascent Descent sub def % use `sub' because descent < 0
4136 % Define these in case they're not in the FontInfo
4137 % (also, here they're easier to get to).
4138 /UnderlinePosition Descent 0.70 mul def
4139 /OverlinePosition Descent UnderlinePosition sub Ascent add def
4140 /StrikeoutPosition Ascent 0.30 mul def
4141 /LineThickness FontHeight 0.05 mul def
4142 /Xshadow FontHeight 0.08 mul def
4143 /Yshadow FontHeight -0.09 mul def
4144 /SpaceBackground Descent neg UnderlinePosition add def
4145 /XBox Descent neg def
4146 /YBox LineThickness 0.7 mul def
4148 currentdict % Leave the new font on the stack
4149 end % Stop using the font as the current dictionary
4150 definefont % Put the font into the font dictionary
4151 pop % Discard the returned font
4155 /DefFont{findfont exch scalefont reencodeFontISO}def
4160 dup /Ascent get /Ascent exch def
4161 dup /Descent get /Descent exch def
4162 dup /FontHeight get /FontHeight exch def
4163 dup /UnderlinePosition get /UnderlinePosition exch def
4164 dup /OverlinePosition get /OverlinePosition exch def
4165 dup /StrikeoutPosition get /StrikeoutPosition exch def
4166 dup /LineThickness get /LineThickness exch def
4167 dup /Xshadow get /Xshadow exch def
4168 dup /Yshadow get /Yshadow exch def
4169 dup /SpaceBackground get /SpaceBackground exch def
4170 dup /XBox get /XBox exch def
4171 dup /YBox get /YBox exch def
4184 /FillBgColor{bgcolor aload pop setrgbcolor fill}bind def
4186 % stack: fill-or-not lower-x lower-y upper-x upper-y |- --
4199 % top of stack: fill-or-not
4201 {LineThickness setlinewidth stroke}
4206 % stack: string fill-or-not |- --
4209 /-ox- currentpoint /-oy- exch def def
4211 LineThickness setlinewidth
4213 st dup true charpath
4214 -fillp- {gsave FillBgColor grestore}if
4216 -oy- add /-oy- exch def
4217 -ox- add /-ox- exch def
4224 % stack: fill-or-not delta |- --
4227 xx XBox sub dd sub yy YBox sub dd sub
4228 XX XBox add dd add YY YBox add dd add
4232 % stack: string |- --
4235 Xshadow Yshadow rmoveto
4240 % stack: position |- --
4242 {currentpoint exch pop add dup
4248 LineThickness setlinewidth stroke
4252 % stack: string |- --
4253 % effect: 1 - underline 2 - strikeout 4 - overline
4254 % 8 - shadow 16 - box 32 - outline
4256 {/xx currentpoint dup Descent add /yy exch def
4257 Ascent add /YY exch def def
4258 dup stringwidth pop xx add /XX exch def
4260 {/yy yy Yshadow add def
4261 /XX XX Xshadow add def
4266 {SpaceBackground doBox}
4267 {xx yy XX YY doRect}
4270 Effect 16 and 0 ne{false 0 doBox}if % box
4271 Effect 8 and 0 ne{dup doShadow}if % shadow
4273 {true doOutline} % outline
4274 {show} % normal text
4276 Effect 1 and 0 ne{UnderlinePosition Hline}if % underline
4277 Effect 2 and 0 ne{StrikeoutPosition Hline}if % strikeout
4278 Effect 4 and 0 ne{OverlinePosition Hline}if % overline
4282 "EBNF EPS prologue")
4285 (defconst ebnf-eps-begin
4289 % x y #ebnf2ps#begin
4291 {#ebnf2ps#dict begin /#ebnf2ps#save save def
4292 moveto false BG 0.0 0.0 0.0 setrgbcolor}def
4294 /#ebnf2ps#end{showpage #ebnf2ps#save restore end}def
4301 (defconst ebnf-eps-end
4308 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4312 (defun ebnf-eps-header-footer (value)
4313 ;; evaluate header/footer value
4314 ;; return a string or nil
4315 (let ((tmp (if (symbolp value
)
4316 (cond ((fboundp value
) (funcall value
))
4317 ((boundp value
) (symbol-value value
))
4320 (and (stringp tmp
) tmp
)))
4323 (defun ebnf-eps-header ()
4324 ;; evaluate header value
4325 (ebnf-eps-header-footer ebnf-eps-header
))
4328 (defun ebnf-eps-footer ()
4329 ;; evaluate footer value
4330 (ebnf-eps-header-footer ebnf-eps-footer
))
4333 ;; hacked fom `ps-output-string-prim' (ps-print.el)
4334 (defun ebnf-eps-string (string)
4335 (let* ((str (string-as-unibyte string
))
4338 (new "(") ; insert start-string delimiter
4340 ;; Find and quote special characters as necessary for PS
4341 ;; This skips everything except control chars, non-ASCII chars, (, ) and \.
4342 (while (setq start
(string-match "[^]-~ -'*-[]" str index
))
4343 (setq special
(aref str start
)
4345 (substring str index start
)
4346 (if (and (<= 0 special
) (<= special
255))
4347 (aref ps-string-escape-codes special
)
4348 ;; insert hexadecimal representation if character
4349 ;; code is out of range
4350 (format "\\%04X" special
)))
4354 (substring str index len
))
4355 ")"))) ; insert end-string delimiter
4358 (defun ebnf-eps-header-footer-comment (str)
4359 ;; parse header/footer comment string
4360 (let ((len (1- (length str
)))
4363 (while (setq start
(string-match "%" str index
))
4364 (setq fmt
(if (< start len
) (aref str
(1+ start
)) ?
\?)
4366 (substring str index start
)
4367 (cond ((= fmt ?%
) "%")
4368 ((= fmt ?H
) (ebnf-eps-header))
4369 ((= fmt ?F
) (ebnf-eps-footer))
4373 (ebnf-eps-string (concat new
4375 (substring str index
(1+ len
)))))))
4378 (defun ebnf-eps-header-footer-p (value)
4379 ;; return t if value is non-nil and is not an empty string
4380 (not (or (null value
)
4381 (and (stringp value
) (string= value
"")))))
4384 (defun ebnf-eps-header-comment (str)
4385 ;; set header comment if header is on
4386 (when (ebnf-eps-header-footer-p ebnf-eps-header
)
4387 (setq ebnf-eps-header-comment
(ebnf-eps-header-footer-comment str
))))
4390 (defun ebnf-eps-footer-comment (str)
4391 ;; set footer comment if footer is on
4392 (when (ebnf-eps-header-footer-p ebnf-eps-footer
)
4393 (setq ebnf-eps-footer-comment
(ebnf-eps-header-footer-comment str
))))
4396 (defun ebnf-eps-header-footer-file (filename)
4397 ;; associate header and footer with a filename
4398 (let ((filehf (assoc filename ebnf-eps-file-alist
))
4399 (header (or ebnf-eps-header-comment
(ebnf-eps-header)))
4400 (footer (or ebnf-eps-footer-comment
(ebnf-eps-footer))))
4402 (setq ebnf-eps-file-alist
(cons (list filename header footer
)
4403 ebnf-eps-file-alist
))
4404 (setcar (nthcdr 1 filehf
) header
)
4405 (setcar (nthcdr 2 filehf
) footer
))))
4408 (defun ebnf-eps-header-footer-set (filename)
4409 ;; set header and footer from a filename
4410 (let ((header-footer (assoc filename ebnf-eps-file-alist
)))
4411 (setq ebnf-eps-header-comment
(nth 1 header-footer
)
4412 ebnf-eps-footer-comment
(nth 2 header-footer
))))
4415 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4419 (defvar ebnf-format-float
"%1.3f")
4422 (defun ebnf-format-float (&rest floats
)
4425 (format ebnf-format-float float
))
4430 (defun ebnf-format-color (format-str color default
)
4431 (let* ((the-color (or color default
))
4432 (rgb (ps-color-scale the-color
)))
4435 (ebnf-format-float (nth 0 rgb
) (nth 1 rgb
) (nth 2 rgb
))
4440 (defvar ebnf-message-float
"%3.2f")
4443 (defsubst ebnf-message-float
(format-str value
)
4445 (format ebnf-message-float value
)))
4448 (defvar ebnf-total
0)
4449 (defvar ebnf-nprod
0)
4452 (defsubst ebnf-message-info
(messag)
4453 (message "%s...%3d%%"
4455 (round (/ (* (setq ebnf-nprod
(1+ ebnf-nprod
)) 100.0) ebnf-total
))))
4458 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4462 (defmacro ebnf-node-kind
(vec &optional value
)
4464 `(aset ,vec
0 ,value
)
4468 (defmacro ebnf-node-width-func
(node width
)
4469 `(funcall (aref ,node
1) ,node
,width
))
4472 (defmacro ebnf-node-dimension-func
(node &optional value
)
4474 `(aset ,node
2 ,value
)
4475 `(funcall (aref ,node
2) ,node
)))
4478 (defmacro ebnf-node-entry
(vec &optional value
)
4480 `(aset ,vec
3 ,value
)
4484 (defmacro ebnf-node-height
(vec &optional value
)
4486 `(aset ,vec
4 ,value
)
4490 (defmacro ebnf-node-width
(vec &optional value
)
4492 `(aset ,vec
5 ,value
)
4496 (defmacro ebnf-node-name
(vec)
4500 (defmacro ebnf-node-list
(vec &optional value
)
4502 `(aset ,vec
6 ,value
)
4506 (defmacro ebnf-node-default
(vec)
4510 (defmacro ebnf-node-production
(vec &optional value
)
4512 `(aset ,vec
7 ,value
)
4516 (defmacro ebnf-node-separator
(vec &optional value
)
4518 `(aset ,vec
7 ,value
)
4522 (defmacro ebnf-node-action
(vec &optional value
)
4524 `(aset ,vec
8 ,value
)
4528 (defmacro ebnf-node-generation
(node)
4529 `(funcall (ebnf-node-kind ,node
) ,node
))
4532 (defmacro ebnf-max-width
(prod)
4533 `(max (ebnf-node-width ,prod
)
4534 (+ (* (length (ebnf-node-name ,prod
))
4536 ebnf-production-horizontal-space
)))
4539 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4540 ;; PostScript generation
4543 (defun ebnf-generate-eps (ebnf-tree)
4544 (let* ((ps-color-p (and ebnf-color-p
(ps-color-device)))
4545 (ps-print-color-scale (if ps-color-p
4546 (float (car (ps-color-values "white")))
4548 (ebnf-total (length ebnf-tree
))
4550 (old-ps-output (symbol-function 'ps-output
))
4551 (old-ps-output-string (symbol-function 'ps-output-string
))
4552 (eps-buffer (get-buffer-create ebnf-eps-buffer-name
))
4553 ebnf-debug-ps error-msg horizontal
4554 prod prod-name prod-width prod-height prod-list file-list
)
4555 ;; redefines `ps-output' and `ps-output-string'
4556 (defalias 'ps-output
'ebnf-eps-output
)
4557 (defalias 'ps-output-string
'ps-output-string-prim
)
4558 ;; generate EPS file
4560 (condition-case data
4563 (setq prod
(car ebnf-tree
)
4564 prod-name
(ebnf-node-name prod
)
4565 prod-width
(ebnf-max-width prod
)
4566 prod-height
(ebnf-node-height prod
)
4567 horizontal
(memq (ebnf-node-action prod
)
4569 ;; generate production in EPS buffer
4571 (set-buffer eps-buffer
)
4572 (setq ebnf-eps-upper-x
0.0
4573 ebnf-eps-upper-y
0.0
4574 ebnf-eps-max-width prod-width
4575 ebnf-eps-max-height prod-height
)
4576 (ebnf-generate-production prod
))
4577 (if (setq prod-list
(cdr (assoc prod-name
4578 ebnf-eps-production-list
)))
4579 ;; insert EPS buffer in all buffer associated with production
4580 (ebnf-eps-production-list prod-list
'file-list horizontal
4581 prod-width prod-height eps-buffer
)
4582 ;; write EPS file for production
4583 (ebnf-eps-finish-and-write eps-buffer
4584 (ebnf-eps-filename prod-name
)))
4585 ;; prepare for next loop
4587 (set-buffer eps-buffer
)
4589 (setq ebnf-tree
(cdr ebnf-tree
)))
4590 ;; write and kill temporary buffers
4591 (ebnf-eps-write-kill-temp file-list t
)
4592 (setq file-list nil
))
4595 (setq error-msg
(error-message-string data
)))))
4596 ;; restore `ps-output' and `ps-output-string'
4597 (defalias 'ps-output old-ps-output
)
4598 (defalias 'ps-output-string old-ps-output-string
)
4599 ;; kill temporary buffers
4600 (kill-buffer eps-buffer
)
4601 (ebnf-eps-write-kill-temp file-list nil
)
4602 (and error-msg
(error error-msg
))
4606 ;; write and kill temporary buffers
4607 (defun ebnf-eps-write-kill-temp (file-list write-p
)
4609 (let ((buffer (get-buffer (concat " *" (car file-list
) "*"))))
4612 (ebnf-eps-finish-and-write buffer
(car file-list
)))
4613 (kill-buffer buffer
)))
4614 (setq file-list
(cdr file-list
))))
4617 ;; insert EPS buffer in all buffer associated with production
4618 (defun ebnf-eps-production-list (prod-list file-list-sym horizontal
4619 prod-width prod-height eps-buffer
)
4621 (add-to-list file-list-sym
(car prod-list
))
4623 (set-buffer (get-buffer-create (concat " *" (car prod-list
) "*")))
4624 (goto-char (point-max))
4627 ((zerop (buffer-size))
4628 (setq ebnf-eps-upper-x
0.0
4629 ebnf-eps-upper-y
0.0
4630 ebnf-eps-max-width prod-width
4631 ebnf-eps-max-height prod-height
))
4634 (ebnf-eop-horizontal ebnf-eps-prod-width
)
4635 (setq ebnf-eps-max-width
(+ ebnf-eps-max-width
4636 ebnf-production-horizontal-space
4638 ebnf-eps-max-height
(max ebnf-eps-max-height prod-height
)))
4641 (ebnf-eop-vertical ebnf-eps-max-height
)
4642 (setq ebnf-eps-upper-x
(max ebnf-eps-upper-x ebnf-eps-max-width
)
4643 ebnf-eps-upper-y
(if (zerop ebnf-eps-upper-y
)
4646 ebnf-production-vertical-space
4647 ebnf-eps-max-height
))
4648 ebnf-eps-max-width prod-width
4649 ebnf-eps-max-height prod-height
))
4651 (setq ebnf-eps-prod-width prod-width
)
4652 (insert-buffer-substring eps-buffer
))
4653 (setq prod-list
(cdr prod-list
))))
4656 (defun ebnf-generate (ebnf-tree)
4657 (let* ((ps-color-p (and ebnf-color-p
(ps-color-device)))
4658 (ps-print-color-scale (if ps-color-p
4659 (float (car (ps-color-values "white")))
4661 ps-zebra-stripes ps-line-number ps-razzle-dazzle
4663 ps-print-begin-sheet-hook
4664 ps-print-begin-page-hook
4665 ps-print-begin-column-hook
)
4666 (ps-generate (current-buffer) (point-min) (point-max)
4667 'ebnf-generate-postscript
)))
4670 (defvar ebnf-tree nil
)
4671 (defvar ebnf-direction
"R")
4674 (defun ebnf-generate-postscript (from to
)
4676 (if ebnf-horizontal-max-height
4677 (ebnf-generate-with-max-height)
4678 (ebnf-generate-without-max-height))
4682 (defun ebnf-generate-with-max-height ()
4683 (let ((ebnf-total (length ebnf-tree
))
4685 next-line max-height prod the-width
)
4687 ;; find next line point
4688 (setq next-line ebnf-tree
4689 prod
(car ebnf-tree
)
4690 max-height
(ebnf-node-height prod
))
4691 (ebnf-begin-line prod
(ebnf-max-width prod
))
4692 (while (and (setq next-line
(cdr next-line
))
4693 (setq prod
(car next-line
))
4694 (memq (ebnf-node-action prod
) ebnf-action-list
)
4695 (setq the-width
(ebnf-max-width prod
))
4696 (<= the-width ps-width-remaining
))
4697 (setq max-height
(max max-height
(ebnf-node-height prod
))
4698 ps-width-remaining
(- ps-width-remaining
4700 ebnf-production-horizontal-space
))))
4701 ;; generate current line
4702 (ebnf-newline max-height
)
4703 (setq prod
(car ebnf-tree
))
4704 (ebnf-generate-production prod
)
4705 (while (not (eq (setq ebnf-tree
(cdr ebnf-tree
)) next-line
))
4706 (ebnf-eop-horizontal (ebnf-max-width prod
))
4707 (setq prod
(car ebnf-tree
))
4708 (ebnf-generate-production prod
))
4709 (ebnf-eop-vertical max-height
))))
4712 (defun ebnf-generate-without-max-height ()
4713 (let ((ebnf-total (length ebnf-tree
))
4715 max-height prod bef-width cur-width
)
4717 ;; generate current line
4718 (setq prod
(car ebnf-tree
)
4719 max-height
(ebnf-node-height prod
)
4720 bef-width
(ebnf-max-width prod
))
4721 (ebnf-begin-line prod bef-width
)
4722 (ebnf-generate-production prod
)
4723 (while (and (setq ebnf-tree
(cdr ebnf-tree
))
4724 (setq prod
(car ebnf-tree
))
4725 (memq (ebnf-node-action prod
) ebnf-action-list
)
4726 (setq cur-width
(ebnf-max-width prod
))
4727 (<= cur-width ps-width-remaining
)
4728 (<= (ebnf-node-height prod
) ps-height-remaining
))
4729 (ebnf-eop-horizontal bef-width
)
4730 (ebnf-generate-production prod
)
4731 (setq bef-width cur-width
4732 max-height
(max max-height
(ebnf-node-height prod
))
4733 ps-width-remaining
(- ps-width-remaining
4735 ebnf-production-horizontal-space
))))
4736 (ebnf-eop-vertical max-height
)
4737 ;; prepare next line
4738 (ebnf-newline max-height
))))
4741 (defun ebnf-begin-line (prod width
)
4742 (and (or (eq (ebnf-node-action prod
) 'form-feed
)
4743 (> (ebnf-node-height prod
) ps-height-remaining
))
4745 (setq ps-width-remaining
(- ps-width-remaining
4747 ebnf-production-horizontal-space
))))
4750 (defun ebnf-newline (height)
4751 (and (> height ps-height-remaining
)
4753 (setq ps-width-remaining ps-print-width
4754 ps-height-remaining
(- ps-height-remaining
4756 ebnf-production-vertical-space
))))
4759 ;; [production width-fun dim-fun entry height width name production action]
4760 (defun ebnf-generate-production (production)
4761 (ebnf-message-info "Generating")
4762 (run-hooks 'ebnf-production-hook
)
4763 (ps-output-string (if ebnf-production-name-p
4764 (ebnf-node-name production
)
4768 (ebnf-node-width production
)
4769 (+ (if ebnf-production-name-p
4772 (ebnf-node-entry (ebnf-node-production production
))))
4774 (ebnf-node-generation (ebnf-node-production production
))
4775 (ps-output "EOS\n"))
4778 ;; [alternative width-fun dim-fun entry height width list]
4779 (defun ebnf-generate-alternative (alternative)
4780 (let ((alt (ebnf-node-list alternative
))
4781 (entry (ebnf-node-entry alternative
))
4783 alt-height alt-entry
)
4785 (ps-output (ebnf-format-float (- entry
(ebnf-node-entry (car alt
))))
4787 (setq entry
(- entry
(ebnf-node-height (car alt
)) ebnf-vertical-space
)
4790 (ps-output (format "%d " nlist
)
4791 (ebnf-format-float (ebnf-node-width alternative
))
4793 (setq alt
(ebnf-node-list alternative
))
4795 (ebnf-node-generation (car alt
))
4796 (setq alt-height
(- (ebnf-node-height (car alt
))
4797 (ebnf-node-entry (car alt
)))))
4798 (while (setq alt
(cdr alt
))
4799 (setq alt-entry
(ebnf-node-entry (car alt
)))
4800 (ebnf-vertical-movement
4801 (- (+ alt-height ebnf-vertical-space alt-entry
)))
4802 (ebnf-node-generation (car alt
))
4803 (setq alt-height
(- (ebnf-node-height (car alt
)) alt-entry
))))
4804 (ps-output "EOS\n"))
4807 ;; [sequence width-fun dim-fun entry height width list]
4808 (defun ebnf-generate-sequence (sequence)
4810 (let ((seq (ebnf-node-list sequence
))
4813 (ebnf-node-generation (car seq
))
4814 (setq seq-width
(ebnf-node-width (car seq
))))
4815 (while (setq seq
(cdr seq
))
4816 (ebnf-horizontal-movement seq-width
)
4817 (ebnf-node-generation (car seq
))
4818 (setq seq-width
(ebnf-node-width (car seq
)))))
4819 (ps-output "EOS\n"))
4822 ;; [terminal width-fun dim-fun entry height width name]
4823 (defun ebnf-generate-terminal (terminal)
4824 (ebnf-gen-terminal terminal
"T"))
4827 ;; [non-terminal width-fun dim-fun entry height width name]
4828 (defun ebnf-generate-non-terminal (non-terminal)
4829 (ebnf-gen-terminal non-terminal
"NT"))
4832 ;; [empty width-fun dim-fun entry height width]
4833 (defun ebnf-generate-empty (empty)
4834 (ebnf-empty-alternative (ebnf-node-width empty
)))
4837 ;; [optional width-fun dim-fun entry height width element]
4838 (defun ebnf-generate-optional (optional)
4839 (let ((the-optional (ebnf-node-list optional
)))
4840 (ps-output (ebnf-format-float
4841 (+ (- (ebnf-node-height the-optional
)
4842 (ebnf-node-entry optional
))
4843 ebnf-vertical-space
)
4844 (ebnf-node-width optional
))
4846 (ebnf-node-generation the-optional
)
4847 (ps-output "EOS\n")))
4850 ;; [one-or-more width-fun dim-fun entry height width element separator]
4851 (defun ebnf-generate-one-or-more (one-or-more)
4852 (let* ((width (ebnf-node-width one-or-more
))
4853 (sep (ebnf-node-separator one-or-more
))
4854 (entry (- (ebnf-node-entry one-or-more
)
4856 (ebnf-node-entry sep
)
4858 (ps-output (ebnf-format-float entry width
)
4860 (ebnf-node-generation (ebnf-node-list one-or-more
))
4861 (ebnf-vertical-movement entry
)
4863 (let ((ebnf-direction "L"))
4864 (ebnf-node-generation sep
))
4865 (ebnf-empty-alternative (- width
4866 ebnf-horizontal-space
4867 ebnf-basic-width-extra
))))
4868 (ps-output "EOS\n"))
4871 ;; [zero-or-more width-fun dim-fun entry height width element separator]
4872 (defun ebnf-generate-zero-or-more (zero-or-more)
4873 (let* ((width (ebnf-node-width zero-or-more
))
4874 (node-list (ebnf-node-list zero-or-more
))
4875 (list-entry (ebnf-node-entry node-list
))
4876 (node-sep (ebnf-node-separator zero-or-more
))
4877 (entry (+ list-entry
4880 (- (ebnf-node-height node-sep
)
4881 (ebnf-node-entry node-sep
))
4882 ebnf-basic-empty-height
))))
4883 (ps-output (ebnf-format-float entry
4884 (+ (- (ebnf-node-height node-list
)
4886 ebnf-vertical-space
)
4889 (ebnf-node-generation (ebnf-node-list zero-or-more
))
4890 (ebnf-vertical-movement entry
)
4891 (if (ebnf-node-separator zero-or-more
)
4892 (let ((ebnf-direction "L"))
4893 (ebnf-node-generation (ebnf-node-separator zero-or-more
)))
4894 (ebnf-empty-alternative (- width
4895 ebnf-horizontal-space
4896 ebnf-basic-width-extra
))))
4897 (ps-output "EOS\n"))
4900 ;; [special width-fun dim-fun entry height width name]
4901 (defun ebnf-generate-special (special)
4902 (ebnf-gen-terminal special
"SP"))
4905 ;; [repeat width-fun dim-fun entry height width times element]
4906 (defun ebnf-generate-repeat (repeat)
4907 (let ((times (ebnf-node-name repeat
))
4908 (element (ebnf-node-separator repeat
)))
4909 (ps-output-string times
)
4912 (ebnf-node-entry repeat
)
4913 (ebnf-node-height repeat
)
4914 (ebnf-node-width repeat
)
4916 (+ (ebnf-node-width element
)
4917 ebnf-space-R ebnf-space-R ebnf-space-R
4918 (* (length times
) ebnf-font-width-R
))
4920 " " ebnf-direction
"RP\n")
4922 (ebnf-node-generation element
)))
4923 (ps-output "EOS\n"))
4926 ;; [except width-fun dim-fun entry height width element element]
4927 (defun ebnf-generate-except (except)
4928 (let* ((element (ebnf-node-list except
))
4929 (exception (ebnf-node-separator except
))
4930 (width (ebnf-node-width element
)))
4931 (ps-output (ebnf-format-float
4933 (ebnf-node-entry except
)
4934 (ebnf-node-height except
)
4935 (ebnf-node-width except
)
4937 ebnf-space-E ebnf-space-E ebnf-space-E
4940 (+ (ebnf-node-width exception
) ebnf-space-E
)
4942 " " ebnf-direction
"EX\n")
4943 (ebnf-node-generation (ebnf-node-list except
))
4945 (ebnf-horizontal-movement (+ width ebnf-space-E
4946 ebnf-font-width-E ebnf-space-E
))
4947 (ebnf-node-generation exception
)))
4948 (ps-output "EOS\n"))
4951 (defun ebnf-gen-terminal (node code
)
4952 (ps-output-string (ebnf-node-name node
))
4953 (ps-output " " (ebnf-format-float (ebnf-node-width node
))
4954 " " ebnf-direction code
4955 (if (ebnf-node-default node
)
4960 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4961 ;; Internal functions
4964 (defun ebnf-directory (fun &optional directory
)
4965 "Process files in DIRECTORY applying function FUN on each file.
4967 If DIRECTORY is nil, use `default-directory'.
4969 Only files in DIRECTORY that match `ebnf-file-suffix-regexp' (which see) are
4971 (let ((files (directory-files (or directory default-directory
)
4972 t ebnf-file-suffix-regexp
)))
4974 (set-buffer (find-file-noselect (car files
)))
4976 (setq buffer-backed-up t
) ; Do not back it up.
4977 (save-buffer) ; Just save new version.
4978 (kill-buffer (current-buffer))
4979 (setq files
(cdr files
)))))
4982 (defun ebnf-file (fun file
&optional do-not-kill-buffer-when-done
)
4983 "Process the named FILE applying function FUN.
4985 If optional arg DO-NOT-KILL-BUFFER-WHEN-DONE is non-nil, the buffer isn't
4986 killed after process termination."
4987 (set-buffer (find-file-noselect file
))
4989 (or do-not-kill-buffer-when-done
4990 (kill-buffer (current-buffer))))
4993 ;; function `ebnf-range-regexp' is used to avoid a bug of `skip-chars-forward'
4994 ;; on version 20.4.1, that is, it doesn't accept ranges like "\240-\377" (or
4995 ;; "\177-\237"), but it accepts the character sequence from \240 to \377 (or
4996 ;; from \177 to \237). It seems that version 20.7 has the same problem.
4997 (defun ebnf-range-regexp (prefix from to
)
5000 (setq str
(concat str
(char-to-string from
))
5002 (concat prefix str
)))
5005 (defvar ebnf-map-name
5006 (let ((map (make-vector 256 ?\_
)))
5007 (mapc #'(lambda (char)
5008 (aset map char char
))
5009 (concat "#$%&+-.0123456789=?@~"
5010 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
5011 "abcdefghijklmnopqrstuvwxyz"))
5015 (defun ebnf-eps-filename (str)
5016 (let* ((len (length str
))
5018 ;; to keep compatibility with Emacs 20 & 21:
5019 ;; DO NOT REPLACE `?\ ' BY `?\s'
5020 (new (make-string len ?\
)))
5022 (aset new stri
(aref ebnf-map-name
(aref str stri
)))
5023 (setq stri
(1+ stri
)))
5024 (concat ebnf-eps-prefix new
".eps")))
5027 (defun ebnf-eps-output (&rest args
)
5030 (setq args
(cdr args
))))
5033 (defun ebnf-generate-region (from to gen-func
)
5034 (run-hooks 'ebnf-hook
)
5035 (let ((ebnf-limit (max from to
))
5036 (error-msg "SYNTAX")
5041 (condition-case data
5042 (let ((tree (ebnf-parse-and-sort (min from to
))))
5044 (setq error-msg
"EMPTY RULES"
5045 tree
(ebnf-eliminate-empty-rules tree
))
5046 (setq error-msg
"OPTMIZE"
5047 tree
(ebnf-optimize tree
))
5048 (setq error-msg
"DIMENSIONS"
5049 tree
(ebnf-dimensions tree
))
5050 (setq error-msg
"GENERATION")
5051 (funcall gen-func tree
))
5052 (setq error-msg nil
)) ; here it's ok
5056 (setq the-point
(max (1- (point)) (point-min))
5057 error-msg
(concat error-msg
": "
5058 (error-message-string data
)
5060 (and (string= error-msg
"SYNTAX")
5061 (format "at position %d "
5063 (format "in buffer \"%s\"."
5064 (buffer-name)))))))))
5068 (goto-char the-point
)
5069 (if ebnf-stop-on-error
5071 (message "%s" error-msg
)))
5072 ;; generated output OK
5075 ;; syntax checked OK
5077 (message "EBNF syntactic analysis: NO ERRORS.")))))
5080 (defun ebnf-parse-and-sort (start)
5081 (ebnf-log "(ebnf-parse-and-sort %S)" start
)
5083 (let ((tree (funcall ebnf-parser-func start
)))
5084 (if ebnf-sort-production
5086 (message "Sorting...")
5088 (if (eq ebnf-sort-production
'ascending
)
5089 'ebnf-sorter-ascending
5090 'ebnf-sorter-descending
)))
5094 (defun ebnf-sorter-ascending (first second
)
5095 (string< (ebnf-node-name first
)
5096 (ebnf-node-name second
)))
5099 (defun ebnf-sorter-descending (first second
)
5100 (string< (ebnf-node-name second
)
5101 (ebnf-node-name first
)))
5104 (defun ebnf-empty-alternative (width)
5105 (ps-output (ebnf-format-float width
) " EA\n"))
5108 (defun ebnf-vertical-movement (height)
5109 (ps-output (ebnf-format-float height
) " vm\n"))
5112 (defun ebnf-horizontal-movement (width)
5113 (ps-output (ebnf-format-float width
) " hm\n"))
5116 (defun ebnf-entry (height)
5117 (* height ebnf-entry-percentage
))
5120 (defun ebnf-eop-vertical (height)
5121 (ps-output (ebnf-format-float (+ height ebnf-production-vertical-space
))
5125 (defun ebnf-eop-horizontal (width)
5126 (ps-output (ebnf-format-float (+ width ebnf-production-horizontal-space
))
5130 (defun ebnf-new-page ()
5131 (when (< ps-height-remaining ps-print-height
)
5132 (run-hooks 'ebnf-page-hook
)
5137 (defsubst ebnf-font-size
(font) (nth 0 font
))
5138 (defsubst ebnf-font-name
(font) (nth 1 font
))
5139 (defsubst ebnf-font-foreground
(font) (nth 2 font
))
5140 (defsubst ebnf-font-background
(font) (nth 3 font
))
5141 (defsubst ebnf-font-list
(font) (nthcdr 4 font
))
5142 (defsubst ebnf-font-attributes
(font)
5143 (lsh (ps-extension-bit (cdr font
)) -
2))
5146 (defconst ebnf-font-name-select
5147 (vector 'normal
'bold
'italic
'bold-italic
))
5150 (defun ebnf-font-name-select (font)
5151 (let* ((font-list (ebnf-font-list font
))
5152 (font-index (+ (if (memq 'bold font-list
) 1 0)
5153 (if (memq 'italic font-list
) 2 0)))
5154 (name (ebnf-font-name font
))
5155 (database (cdr (assoc name ps-font-info-database
)))
5156 (info-list (or (cdr (assoc 'fonts database
))
5157 (error "Invalid font: %s" name
))))
5158 (or (cdr (assoc (aref ebnf-font-name-select font-index
)
5160 (error "Invalid attributes for font %s" name
))))
5163 (defun ebnf-font-select (font select
)
5164 (let* ((name (ebnf-font-name font
))
5165 (database (cdr (assoc name ps-font-info-database
)))
5166 (size (cdr (assoc 'size database
)))
5167 (base (cdr (assoc select database
))))
5169 (/ (* (ebnf-font-size font
) base
)
5171 (error "Invalid font: %s" name
))))
5174 (defsubst ebnf-font-width
(font)
5175 (ebnf-font-select font
'avg-char-width
))
5176 (defsubst ebnf-font-height
(font)
5177 (ebnf-font-select font
'line-height
))
5180 (defconst ebnf-syntax-alist
5181 ;; 0.syntax 1.parser 2.initializer
5182 '((iso-ebnf ebnf-iso-parser ebnf-iso-initialize
)
5183 (yacc ebnf-yac-parser ebnf-yac-initialize
)
5184 (abnf ebnf-abn-parser ebnf-abn-initialize
)
5185 (ebnf ebnf-bnf-parser ebnf-bnf-initialize
)
5186 (ebnfx ebnf-ebx-parser ebnf-ebx-initialize
)
5187 (dtd ebnf-dtd-parser ebnf-dtd-initialize
))
5188 "Alist associating EBNF syntax with a parser and an initializer.")
5191 (defun ebnf-begin-job ()
5192 (ps-printing-region nil nil nil
)
5193 (if ebnf-use-float-format
5194 (setq ebnf-format-float
"%1.3f"
5195 ebnf-message-float
"%3.2f")
5196 (setq ebnf-format-float
"%s"
5197 ebnf-message-float
"%s"))
5198 (ebnf-otz-initialize)
5199 ;; to avoid compilation gripes when calling autoloaded functions
5200 (let ((init (or (assoc ebnf-syntax ebnf-syntax-alist
)
5201 (assoc 'ebnf ebnf-syntax-alist
))))
5202 (setq ebnf-parser-func
(nth 1 init
))
5203 (funcall (nth 2 init
)))
5204 (and ebnf-terminal-regexp
; ensures that it's a string or nil
5205 (not (stringp ebnf-terminal-regexp
))
5206 (setq ebnf-terminal-regexp nil
))
5207 (or (and ebnf-eps-prefix
; ensures that it's a string
5208 (stringp ebnf-eps-prefix
))
5209 (setq ebnf-eps-prefix
"ebnf--"))
5210 (setq ebnf-entry-percentage
; ensures value between 0.0 and 1.0
5211 (min (max ebnf-entry-percentage
0.0) 1.0)
5212 ebnf-action-list
(if ebnf-horizontal-orientation
5216 ebnf-fonts-required nil
5219 ebnf-eps-context nil
5220 ebnf-eps-file-alist nil
5221 ebnf-eps-production-list nil
5222 ebnf-eps-header-comment nil
5223 ebnf-eps-footer-comment nil
5224 ebnf-eps-upper-x
0.0
5225 ebnf-eps-upper-y
0.0
5226 ebnf-font-height-P
(ebnf-font-height ebnf-production-font
)
5227 ebnf-font-height-T
(ebnf-font-height ebnf-terminal-font
)
5228 ebnf-font-height-NT
(ebnf-font-height ebnf-non-terminal-font
)
5229 ebnf-font-height-S
(ebnf-font-height ebnf-special-font
)
5230 ebnf-font-height-E
(ebnf-font-height ebnf-except-font
)
5231 ebnf-font-height-R
(ebnf-font-height ebnf-repeat-font
)
5232 ebnf-font-width-P
(ebnf-font-width ebnf-production-font
)
5233 ebnf-font-width-T
(ebnf-font-width ebnf-terminal-font
)
5234 ebnf-font-width-NT
(ebnf-font-width ebnf-non-terminal-font
)
5235 ebnf-font-width-S
(ebnf-font-width ebnf-special-font
)
5236 ebnf-font-width-E
(ebnf-font-width ebnf-except-font
)
5237 ebnf-font-width-R
(ebnf-font-width ebnf-repeat-font
)
5238 ebnf-space-T
(* ebnf-font-height-T
0.5)
5239 ebnf-space-NT
(* ebnf-font-height-NT
0.5)
5240 ebnf-space-S
(* ebnf-font-height-S
0.5)
5241 ebnf-space-E
(* ebnf-font-height-E
0.5)
5242 ebnf-space-R
(* ebnf-font-height-R
0.5))
5243 (let ((basic (+ ebnf-font-height-T ebnf-font-height-NT
)))
5244 (setq ebnf-basic-width
(* basic
0.5)
5245 ebnf-horizontal-space
(+ basic basic
)
5246 ebnf-basic-empty-height
(* ebnf-basic-width
0.5)
5247 ebnf-basic-height ebnf-basic-width
5248 ebnf-vertical-space ebnf-basic-width
5249 ebnf-basic-width-extra
(- ebnf-basic-width
5250 ebnf-arrow-extra-width
5251 0.1)) ; error factor
5252 ;; ensures value is greater than zero
5253 (or (and (numberp ebnf-production-horizontal-space
)
5254 (> ebnf-production-horizontal-space
0.0))
5255 (setq ebnf-production-horizontal-space basic
))
5256 ;; ensures value is greater than zero
5257 (or (and (numberp ebnf-production-vertical-space
)
5258 (> ebnf-production-vertical-space
0.0))
5259 (setq ebnf-production-vertical-space basic
)))
5260 (ebnf-log "(ebnf-begin-job)")
5261 (ebnf-log " ebnf-arrow-extra-width ............ : %7.3f" ebnf-arrow-extra-width
)
5262 (ebnf-log " ebnf-arrow-scale .................. : %7.3f" ebnf-arrow-scale
)
5263 (ebnf-log " ebnf-basic-width-extra ............ : %7.3f" ebnf-basic-width-extra
)
5264 (ebnf-log " ebnf-basic-width .................. : %7.3f (T)" ebnf-basic-width
)
5265 (ebnf-log " ebnf-horizontal-space ............. : %7.3f (4T)" ebnf-horizontal-space
)
5266 (ebnf-log " ebnf-basic-empty-height ........... : %7.3f (hT)" ebnf-basic-empty-height
)
5267 (ebnf-log " ebnf-basic-height ................. : %7.3f (T)" ebnf-basic-height
)
5268 (ebnf-log " ebnf-vertical-space ............... : %7.3f (T)" ebnf-vertical-space
)
5269 (ebnf-log " ebnf-production-horizontal-space .. : %7.3f (2T)" ebnf-production-horizontal-space
)
5270 (ebnf-log " ebnf-production-vertical-space .... : %7.3f (2T)" ebnf-production-vertical-space
))
5273 (defsubst ebnf-shape-value
(sym alist
)
5274 (or (cdr (assq sym alist
)) 0))
5277 (defsubst ebnf-boolean
(value)
5278 (if value
"true" "false"))
5281 (defun ebnf-begin-file ()
5284 (set-buffer ps-spool-buffer
)
5285 (goto-char (point-min))
5286 (and (search-forward "%%Creator: " nil t
)
5287 (not (search-forward "& ebnf2ps v"
5288 (save-excursion (end-of-line) (point))
5291 ;; adjust creator comment
5294 (insert " & ebnf2ps v" ebnf-version
)
5295 ;; insert ebnf settings & engine
5296 (goto-char (point-max))
5297 (search-backward "\n%%EndProlog\n")
5298 (ebnf-insert-ebnf-prologue)
5299 (ps-output "\n")))))
5302 (defun ebnf-eps-finish-and-write (buffer filename
)
5303 (when (buffer-modified-p buffer
)
5306 (ebnf-eps-header-footer-set filename
)
5307 (setq ebnf-eps-upper-x
(max ebnf-eps-upper-x ebnf-eps-max-width
)
5308 ebnf-eps-upper-y
(if (zerop ebnf-eps-upper-y
)
5311 ebnf-production-vertical-space
5312 ebnf-eps-max-height
)))
5314 (goto-char (point-min))
5316 "%!PS-Adobe-3.0 EPSF-3.0"
5317 "\n%%BoundingBox: 0 0 "
5318 (format "%d %d" (1+ ebnf-eps-upper-x
) (1+ ebnf-eps-upper-y
))
5319 "\n%%Title: " filename
5320 "\n%%CreationDate: " (format-time-string "%T %b %d %Y")
5321 "\n%%Creator: " (user-full-name) " (using ebnf2ps v" ebnf-version
")"
5322 "\n%%DocumentNeededResources: font "
5323 (or ebnf-fonts-required
5324 (setq ebnf-fonts-required
5325 (mapconcat 'identity
5326 (ps-remove-duplicates
5327 (mapcar 'ebnf-font-name-select
5328 (list ebnf-production-font
5330 ebnf-non-terminal-font
5334 ebnf-eps-header-font
5335 ebnf-eps-footer-font
)))
5337 "\n%%Pages: 0\n%%EndComments\n\n%%BeginProlog\n"
5339 (ebnf-insert-ebnf-prologue)
5340 (insert ebnf-eps-begin
5341 "\n0 " (ebnf-format-float
5342 (- ebnf-eps-upper-y
(* ebnf-font-height-P
0.7)))
5343 " #ebnf2ps#begin\n")
5345 (goto-char (point-max))
5346 (insert ebnf-eps-end
)
5348 (message "Saving...")
5349 (setq filename
(expand-file-name filename
))
5350 (let ((coding-system-for-write 'raw-text-unix
))
5351 (write-region (point-min) (point-max) filename
))
5352 (message "Wrote %s" filename
))))
5355 (defun ebnf-insert-ebnf-prologue ()
5360 "\n\n% === begin EBNF settings\n\n"
5361 (format "/Header %s def\n"
5362 (or ebnf-eps-header-comment
"()"))
5363 (format "/Footer %s def\n"
5364 (or ebnf-eps-footer-comment
"()"))
5366 (format "/ShowHeader %s def\n"
5368 (ebnf-eps-header-footer-p ebnf-eps-header
)))
5369 (format "/fH %s /%s DefFont\n"
5371 (ebnf-font-size ebnf-eps-header-font
))
5372 (ebnf-font-name-select ebnf-eps-header-font
))
5373 (ebnf-format-color "/ForegroundH %s def %% %s\n"
5374 (ebnf-font-foreground ebnf-eps-header-font
)
5376 (ebnf-format-color "/BackgroundH %s def %% %s\n"
5377 (ebnf-font-background ebnf-eps-header-font
)
5379 (format "/EffectH %d def\n"
5380 (ebnf-font-attributes ebnf-eps-header-font
))
5382 (format "/ShowFooter %s def\n"
5384 (ebnf-eps-header-footer-p ebnf-eps-footer
)))
5385 (format "/fF %s /%s DefFont\n"
5387 (ebnf-font-size ebnf-eps-footer-font
))
5388 (ebnf-font-name-select ebnf-eps-footer-font
))
5389 (ebnf-format-color "/ForegroundF %s def %% %s\n"
5390 (ebnf-font-foreground ebnf-eps-footer-font
)
5392 (ebnf-format-color "/BackgroundF %s def %% %s\n"
5393 (ebnf-font-background ebnf-eps-footer-font
)
5395 (format "/EffectF %d def\n"
5396 (ebnf-font-attributes ebnf-eps-footer-font
))
5398 (format "/fP %s /%s DefFont\n"
5399 (ebnf-format-float (ebnf-font-size ebnf-production-font
))
5400 (ebnf-font-name-select ebnf-production-font
))
5401 (ebnf-format-color "/ForegroundP %s def %% %s\n"
5402 (ebnf-font-foreground ebnf-production-font
)
5404 (ebnf-format-color "/BackgroundP %s def %% %s\n"
5405 (ebnf-font-background ebnf-production-font
)
5407 (format "/EffectP %d def\n"
5408 (ebnf-font-attributes ebnf-production-font
))
5410 (format "/fT %s /%s DefFont\n"
5411 (ebnf-format-float (ebnf-font-size ebnf-terminal-font
))
5412 (ebnf-font-name-select ebnf-terminal-font
))
5413 (ebnf-format-color "/ForegroundT %s def %% %s\n"
5414 (ebnf-font-foreground ebnf-terminal-font
)
5416 (ebnf-format-color "/BackgroundT %s def %% %s\n"
5417 (ebnf-font-background ebnf-terminal-font
)
5419 (format "/EffectT %d def\n"
5420 (ebnf-font-attributes ebnf-terminal-font
))
5421 (format "/BorderWidthT %s def\n"
5422 (ebnf-format-float ebnf-terminal-border-width
))
5423 (ebnf-format-color "/BorderColorT %s def %% %s\n"
5424 ebnf-terminal-border-color
5426 (format "/ShapeT %d def\n"
5427 (ebnf-shape-value ebnf-terminal-shape
5428 ebnf-terminal-shape-alist
))
5429 (format "/ShadowT %s def\n"
5430 (ebnf-boolean ebnf-terminal-shadow
))
5432 (format "/fNT %s /%s DefFont\n"
5434 (ebnf-font-size ebnf-non-terminal-font
))
5435 (ebnf-font-name-select ebnf-non-terminal-font
))
5436 (ebnf-format-color "/ForegroundNT %s def %% %s\n"
5437 (ebnf-font-foreground ebnf-non-terminal-font
)
5439 (ebnf-format-color "/BackgroundNT %s def %% %s\n"
5440 (ebnf-font-background ebnf-non-terminal-font
)
5442 (format "/EffectNT %d def\n"
5443 (ebnf-font-attributes ebnf-non-terminal-font
))
5444 (format "/BorderWidthNT %s def\n"
5445 (ebnf-format-float ebnf-non-terminal-border-width
))
5446 (ebnf-format-color "/BorderColorNT %s def %% %s\n"
5447 ebnf-non-terminal-border-color
5449 (format "/ShapeNT %d def\n"
5450 (ebnf-shape-value ebnf-non-terminal-shape
5451 ebnf-terminal-shape-alist
))
5452 (format "/ShadowNT %s def\n"
5453 (ebnf-boolean ebnf-non-terminal-shadow
))
5455 (format "/fS %s /%s DefFont\n"
5456 (ebnf-format-float (ebnf-font-size ebnf-special-font
))
5457 (ebnf-font-name-select ebnf-special-font
))
5458 (ebnf-format-color "/ForegroundS %s def %% %s\n"
5459 (ebnf-font-foreground ebnf-special-font
)
5461 (ebnf-format-color "/BackgroundS %s def %% %s\n"
5462 (ebnf-font-background ebnf-special-font
)
5464 (format "/EffectS %d def\n"
5465 (ebnf-font-attributes ebnf-special-font
))
5466 (format "/BorderWidthS %s def\n"
5467 (ebnf-format-float ebnf-special-border-width
))
5468 (ebnf-format-color "/BorderColorS %s def %% %s\n"
5469 ebnf-special-border-color
5471 (format "/ShapeS %d def\n"
5472 (ebnf-shape-value ebnf-special-shape
5473 ebnf-terminal-shape-alist
))
5474 (format "/ShadowS %s def\n"
5475 (ebnf-boolean ebnf-special-shadow
))
5477 (format "/fE %s /%s DefFont\n"
5478 (ebnf-format-float (ebnf-font-size ebnf-except-font
))
5479 (ebnf-font-name-select ebnf-except-font
))
5480 (ebnf-format-color "/ForegroundE %s def %% %s\n"
5481 (ebnf-font-foreground ebnf-except-font
)
5483 (ebnf-format-color "/BackgroundE %s def %% %s\n"
5484 (ebnf-font-background ebnf-except-font
)
5486 (format "/EffectE %d def\n"
5487 (ebnf-font-attributes ebnf-except-font
))
5488 (format "/BorderWidthE %s def\n"
5489 (ebnf-format-float ebnf-except-border-width
))
5490 (ebnf-format-color "/BorderColorE %s def %% %s\n"
5491 ebnf-except-border-color
5493 (format "/ShapeE %d def\n"
5494 (ebnf-shape-value ebnf-except-shape
5495 ebnf-terminal-shape-alist
))
5496 (format "/ShadowE %s def\n"
5497 (ebnf-boolean ebnf-except-shadow
))
5499 (format "/fR %s /%s DefFont\n"
5500 (ebnf-format-float (ebnf-font-size ebnf-repeat-font
))
5501 (ebnf-font-name-select ebnf-repeat-font
))
5502 (ebnf-format-color "/ForegroundR %s def %% %s\n"
5503 (ebnf-font-foreground ebnf-repeat-font
)
5505 (ebnf-format-color "/BackgroundR %s def %% %s\n"
5506 (ebnf-font-background ebnf-repeat-font
)
5508 (format "/EffectR %d def\n"
5509 (ebnf-font-attributes ebnf-repeat-font
))
5510 (format "/BorderWidthR %s def\n"
5511 (ebnf-format-float ebnf-repeat-border-width
))
5512 (ebnf-format-color "/BorderColorR %s def %% %s\n"
5513 ebnf-repeat-border-color
5515 (format "/ShapeR %d def\n"
5516 (ebnf-shape-value ebnf-repeat-shape
5517 ebnf-terminal-shape-alist
))
5518 (format "/ShadowR %s def\n"
5519 (ebnf-boolean ebnf-repeat-shadow
))
5521 (format "/ExtraWidth %s def\n"
5522 (ebnf-format-float ebnf-arrow-extra-width
))
5523 (format "/ArrowScale %s def\n"
5524 (ebnf-format-float ebnf-arrow-scale
))
5525 (format "/DefaultWidth %s def\n"
5526 (ebnf-format-float ebnf-default-width
))
5527 (format "/LineWidth %s def\n"
5528 (ebnf-format-float ebnf-line-width
))
5529 (ebnf-format-color "/LineColor %s def %% %s\n"
5532 (format "/ArrowShape %d def\n"
5533 (ebnf-shape-value ebnf-arrow-shape
5534 ebnf-arrow-shape-alist
))
5535 (format "/ChartShape %d def\n"
5536 (ebnf-shape-value ebnf-chart-shape
5537 ebnf-terminal-shape-alist
))
5538 (format "/UserArrow{%s}def\n"
5539 (let ((arrow (eval ebnf-user-arrow
)))
5543 "\n% === end EBNF settings\n\n"
5544 (and ebnf-debug-ps ebnf-debug
))))
5548 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5549 ;; Adjusting dimensions
5552 (defun ebnf-dimensions (tree)
5553 (ebnf-log "(ebnf-dimensions tree)")
5554 (let ((ebnf-total (length tree
))
5556 (mapc 'ebnf-production-dimension tree
))
5560 ;; [empty width-fun dim-fun entry height width]
5561 ;;(defun ebnf-empty-dimension (empty)
5565 ;; [production width-fun dim-fun entry height width name production action]
5566 (defun ebnf-production-dimension (production)
5567 (ebnf-log "(ebnf-production-dimension production)")
5568 (ebnf-message-info "Calculating dimensions")
5569 (ebnf-node-dimension-func (ebnf-node-production production
))
5570 (let* ((prod (ebnf-node-production production
))
5571 (height (+ (if ebnf-production-name-p
5574 ebnf-line-width ebnf-line-width
5576 (ebnf-node-height prod
))))
5577 (ebnf-node-entry production height
)
5578 (ebnf-node-height production height
)
5579 (ebnf-node-width production
(+ (ebnf-node-width prod
)
5581 ebnf-horizontal-space
5582 ebnf-basic-width-extra
)))
5583 (ebnf-log " production name : %S" (ebnf-node-name production
))
5584 (ebnf-log " production entry : %7.3f" (ebnf-node-entry production
))
5585 (ebnf-log " production height : %7.3f" (ebnf-node-height production
))
5586 (ebnf-log " production width : %7.3f" (ebnf-node-width production
)))
5589 ;; [terminal width-fun dim-fun entry height width name]
5590 (defun ebnf-terminal-dimension (terminal)
5591 (ebnf-log "(ebnf-terminal-dimension terminal)")
5592 (ebnf-terminal-dimension1 terminal
5598 ;; [non-terminal width-fun dim-fun entry height width name]
5599 (defun ebnf-non-terminal-dimension (non-terminal)
5600 (ebnf-log "(ebnf-non-terminal-dimension non-terminal)")
5601 (ebnf-terminal-dimension1 non-terminal
5607 ;; [special width-fun dim-fun entry height width name]
5608 (defun ebnf-special-dimension (special)
5609 (ebnf-log "(ebnf-special-dimension special)")
5610 (ebnf-terminal-dimension1 special
5616 (defun ebnf-terminal-dimension1 (node font-height font-width space
)
5617 (let ((height (+ space font-height space
))
5618 (len (length (ebnf-node-name node
))))
5619 (ebnf-node-entry node
(* height
0.5))
5620 (ebnf-node-height node height
)
5621 (ebnf-node-width node
(+ ebnf-basic-width
5622 ebnf-arrow-extra-width
5627 (ebnf-log " name : %S" (ebnf-node-name node
))
5628 (ebnf-log " entry : %7.3f" (ebnf-node-entry node
))
5629 (ebnf-log " height : %7.3f" (ebnf-node-height node
))
5630 (ebnf-log " width : %7.3f" (ebnf-node-width node
)))
5633 (defconst ebnf-null-vector
(vector t t t
0.0 0.0 0.0))
5636 ;; [repeat width-fun dim-fun entry height width times element]
5637 (defun ebnf-repeat-dimension (repeat)
5638 (ebnf-log "(ebnf-repeat-dimension repeat)")
5639 (let ((times (ebnf-node-name repeat
))
5640 (element (ebnf-node-separator repeat
)))
5642 (ebnf-node-dimension-func element
)
5643 (setq element ebnf-null-vector
))
5644 (ebnf-node-entry repeat
(+ (ebnf-node-entry element
)
5646 (ebnf-node-height repeat
(+ (max (ebnf-node-height element
)
5648 ebnf-space-R ebnf-space-R
))
5649 (ebnf-node-width repeat
(+ (ebnf-node-width element
)
5650 ebnf-arrow-extra-width
5651 ebnf-space-R ebnf-space-R ebnf-space-R
5652 ebnf-horizontal-space
5653 (* (length times
) ebnf-font-width-R
))))
5654 (ebnf-log " repeat entry : %7.3f" (ebnf-node-entry repeat
))
5655 (ebnf-log " repeat height : %7.3f" (ebnf-node-height repeat
))
5656 (ebnf-log " repeat width : %7.3f" (ebnf-node-width repeat
)))
5659 ;; [except width-fun dim-fun entry height width element element]
5660 (defun ebnf-except-dimension (except)
5661 (ebnf-log "(ebnf-except-dimension except)")
5662 (let ((factor (ebnf-node-list except
))
5663 (element (ebnf-node-separator except
)))
5664 (ebnf-node-dimension-func factor
)
5666 (ebnf-node-dimension-func element
)
5667 (setq element ebnf-null-vector
))
5668 (ebnf-node-entry except
(+ (max (ebnf-node-entry factor
)
5669 (ebnf-node-entry element
))
5671 (ebnf-node-height except
(+ (max (ebnf-node-height factor
)
5672 (ebnf-node-height element
))
5673 ebnf-space-E ebnf-space-E
))
5674 (ebnf-node-width except
(+ (ebnf-node-width factor
)
5675 (ebnf-node-width element
)
5676 ebnf-arrow-extra-width
5677 ebnf-space-E ebnf-space-E
5678 ebnf-space-E ebnf-space-E
5680 ebnf-horizontal-space
)))
5681 (ebnf-log " except entry : %7.3f" (ebnf-node-entry except
))
5682 (ebnf-log " except height : %7.3f" (ebnf-node-height except
))
5683 (ebnf-log " except width : %7.3f" (ebnf-node-width except
)))
5686 ;; [alternative width-fun dim-fun entry height width list]
5687 (defun ebnf-alternative-dimension (alternative)
5688 (ebnf-log "(ebnf-alternative-dimension alternative)")
5689 (let ((body (ebnf-node-list alternative
))
5690 (lis (ebnf-node-list alternative
)))
5692 (ebnf-node-dimension-func (car lis
))
5693 (setq lis
(cdr lis
)))
5697 (tail (car (last body
)))
5698 (entry (ebnf-node-entry (car body
)))
5701 (setq node
(car alt
)
5703 height
(+ (ebnf-node-height node
) height
)
5704 width
(max (ebnf-node-width node
) width
)))
5705 (ebnf-adjust-width body width
)
5706 (setq height
(+ height
(* (1- (length body
)) ebnf-vertical-space
)))
5707 (ebnf-node-entry alternative
(+ entry
5710 (- (ebnf-node-height tail
)
5711 (ebnf-node-entry tail
))))))
5712 (ebnf-node-height alternative height
)
5713 (ebnf-node-width alternative
(+ width
5714 ebnf-horizontal-space
5715 ebnf-basic-width-extra
))
5716 (ebnf-node-list alternative body
)))
5717 (ebnf-log " alternative entry : %7.3f" (ebnf-node-entry alternative
))
5718 (ebnf-log " alternative height : %7.3f" (ebnf-node-height alternative
))
5719 (ebnf-log " alternative width : %7.3f" (ebnf-node-width alternative
)))
5722 ;; [optional width-fun dim-fun entry height width element]
5723 (defun ebnf-optional-dimension (optional)
5724 (ebnf-log "(ebnf-optional-dimension optional)")
5725 (let ((body (ebnf-node-list optional
)))
5726 (ebnf-node-dimension-func body
)
5727 (ebnf-node-entry optional
(ebnf-node-entry body
))
5728 (ebnf-node-height optional
(+ (ebnf-node-height body
)
5729 ebnf-vertical-space
))
5730 (ebnf-node-width optional
(+ (ebnf-node-width body
)
5731 ebnf-horizontal-space
)))
5732 (ebnf-log " optional entry : %7.3f" (ebnf-node-entry optional
))
5733 (ebnf-log " optional height : %7.3f" (ebnf-node-height optional
))
5734 (ebnf-log " optional width : %7.3f" (ebnf-node-width optional
)))
5737 ;; [one-or-more width-fun dim-fun entry height width element separator]
5738 (defun ebnf-one-or-more-dimension (or-more)
5739 (ebnf-log "(ebnf-one-or-more-dimension or-more)")
5740 (let ((list-part (ebnf-node-list or-more
))
5741 (sep-part (ebnf-node-separator or-more
)))
5742 (ebnf-node-dimension-func list-part
)
5744 (ebnf-node-dimension-func sep-part
))
5745 (let ((height (+ (if sep-part
5746 (ebnf-node-height sep-part
)
5747 ebnf-basic-empty-height
)
5749 (ebnf-node-height list-part
)))
5750 (width (max (if sep-part
5751 (ebnf-node-width sep-part
)
5753 (ebnf-node-width list-part
))))
5755 (ebnf-adjust-width list-part width
)
5756 (ebnf-adjust-width sep-part width
))
5757 (ebnf-node-entry or-more
(+ (- height
5758 (ebnf-node-height list-part
))
5759 (ebnf-node-entry list-part
)))
5760 (ebnf-node-height or-more height
)
5761 (ebnf-node-width or-more
(+ width
5762 ebnf-horizontal-space
5763 ebnf-basic-width-extra
))))
5764 (ebnf-log " one-or-more entry : %7.3f" (ebnf-node-entry or-more
))
5765 (ebnf-log " one-or-more height : %7.3f" (ebnf-node-height or-more
))
5766 (ebnf-log " one-or-more width : %7.3f" (ebnf-node-width or-more
)))
5769 ;; [zero-or-more width-fun dim-fun entry height width element separator]
5770 (defun ebnf-zero-or-more-dimension (or-more)
5771 (ebnf-log "(ebnf-zero-or-more-dimension or-more)")
5772 (let ((list-part (ebnf-node-list or-more
))
5773 (sep-part (ebnf-node-separator or-more
)))
5774 (ebnf-node-dimension-func list-part
)
5776 (ebnf-node-dimension-func sep-part
))
5777 (let ((height (+ (if sep-part
5778 (ebnf-node-height sep-part
)
5779 ebnf-basic-empty-height
)
5781 (ebnf-node-height list-part
)
5782 ebnf-vertical-space
))
5783 (width (max (if sep-part
5784 (ebnf-node-width sep-part
)
5786 (ebnf-node-width list-part
))))
5788 (ebnf-adjust-width list-part width
)
5789 (ebnf-adjust-width sep-part width
))
5790 (ebnf-node-entry or-more height
)
5791 (ebnf-node-height or-more height
)
5792 (ebnf-node-width or-more
(+ width
5793 ebnf-horizontal-space
5794 ebnf-basic-width-extra
))))
5795 (ebnf-log " zero-or-more entry : %7.3f" (ebnf-node-entry or-more
))
5796 (ebnf-log " zero-or-more height : %7.3f" (ebnf-node-height or-more
))
5797 (ebnf-log " zero-or-more width : %7.3f" (ebnf-node-width or-more
)))
5800 ;; [sequence width-fun dim-fun entry height width list]
5801 (defun ebnf-sequence-dimension (sequence)
5802 (ebnf-log "(ebnf-sequence-dimension sequence)")
5806 (lis (ebnf-node-list sequence
))
5809 (setq node
(car lis
)
5811 (ebnf-node-dimension-func node
)
5812 (setq entry
(ebnf-node-entry node
)
5813 above
(max above entry
)
5814 below
(max below
(- (ebnf-node-height node
) entry
))
5815 width
(+ width
(ebnf-node-width node
))))
5816 (ebnf-node-entry sequence above
)
5817 (ebnf-node-height sequence
(+ above below
))
5818 (ebnf-node-width sequence width
))
5819 (ebnf-log " sequence entry : %7.3f" (ebnf-node-entry sequence
))
5820 (ebnf-log " sequence height : %7.3f" (ebnf-node-height sequence
))
5821 (ebnf-log " sequence width : %7.3f" (ebnf-node-width sequence
)))
5824 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5828 (defun ebnf-adjust-width (node width
)
5834 (setcar node
(ebnf-adjust-width (car node
) width
))
5835 (setq node
(cdr node
)))))
5838 ;; nothing to be done
5839 ((= width
(ebnf-node-width node
))
5841 ;; left justify term
5842 ((eq ebnf-justify-sequence
'left
)
5843 (ebnf-adjust-empty node width nil
))
5844 ;; right justify terms
5845 ((eq ebnf-justify-sequence
'right
)
5846 (ebnf-adjust-empty node width t
))
5849 (ebnf-node-width-func node width
)
5850 (ebnf-node-width node width
)
5858 (defun ebnf-adjust-empty (node width last-p
)
5859 (if (eq (ebnf-node-kind node
) 'ebnf-generate-empty
)
5861 (ebnf-node-width node width
)
5863 (let ((empty (ebnf-make-empty (- width
(ebnf-node-width node
)))))
5864 (ebnf-make-dup-sequence node
5867 (list node empty
))))))
5870 ;; [terminal width-fun dim-fun entry height width name]
5871 ;; [non-terminal width-fun dim-fun entry height width name]
5872 ;; [empty width-fun dim-fun entry height width]
5873 ;; [special width-fun dim-fun entry height width name]
5874 ;; [repeat width-fun dim-fun entry height width times element]
5875 ;; [except width-fun dim-fun entry height width element element]
5876 ;;(defun ebnf-terminal-width (terminal width)
5880 ;; [alternative width-fun dim-fun entry height width list]
5881 ;; [optional width-fun dim-fun entry height width element]
5882 (defun ebnf-alternative-width (alternative width
)
5883 (ebnf-adjust-width (ebnf-node-list alternative
)
5884 (- width ebnf-horizontal-space
)))
5887 ;; [one-or-more width-fun dim-fun entry height width element separator]
5888 ;; [zero-or-more width-fun dim-fun entry height width element separator]
5889 (defun ebnf-element-width (or-more width
)
5890 (setq width
(- width ebnf-horizontal-space
))
5891 (ebnf-node-list or-more
5892 (ebnf-justify-list or-more
5893 (ebnf-node-list or-more
)
5895 (ebnf-node-separator or-more
5896 (ebnf-justify-list or-more
5897 (ebnf-node-separator or-more
)
5901 ;; [sequence width-fun dim-fun entry height width list]
5902 (defun ebnf-sequence-width (sequence width
)
5903 (ebnf-node-list sequence
5904 (ebnf-justify-list sequence
5905 (ebnf-node-list sequence
)
5909 (defun ebnf-justify-list (node seq width
)
5910 (let ((seq-width (ebnf-node-width node
)))
5911 (if (= width seq-width
)
5914 ;; left justify terms
5915 ((eq ebnf-justify-sequence
'left
)
5916 (ebnf-justify node seq seq-width width t
))
5917 ;; right justify terms
5918 ((eq ebnf-justify-sequence
'right
)
5919 (ebnf-justify node seq seq-width width nil
))
5920 ;; centralize terms -- element
5922 (ebnf-adjust-width seq width
))
5923 ;; centralize terms -- list
5925 (let ((the-width (/ (- width seq-width
) (length seq
)))
5928 (ebnf-adjust-width (car lis
)
5929 (+ (ebnf-node-width (car lis
))
5931 (setq lis
(cdr lis
)))
5936 (defun ebnf-justify (node seq seq-width width last-p
)
5937 (let ((term (car (if last-p
(last seq
) seq
))))
5939 ;; adjust empty term
5940 ((eq (ebnf-node-kind term
) 'ebnf-generate-empty
)
5941 (ebnf-node-width term
(+ (- width seq-width
)
5942 (ebnf-node-width term
)))
5944 ;; insert empty at end ==> left justify
5947 (list (ebnf-make-empty (- width seq-width
)))))
5948 ;; insert empty at beginning ==> right justify
5950 (cons (ebnf-make-empty (- width seq-width
))
5955 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5956 ;; Functions used by parsers
5959 (defun ebnf-eps-add-context (name)
5960 (let ((filename (ebnf-eps-filename name
)))
5961 (if (member filename ebnf-eps-context
)
5962 (error "Try to open an already opened EPS file: %s" filename
)
5963 (setq ebnf-eps-context
(cons filename ebnf-eps-context
)))
5964 (ebnf-eps-header-footer-file filename
)))
5967 (defun ebnf-eps-remove-context (name)
5968 (let ((filename (ebnf-eps-filename name
)))
5969 (if (member filename ebnf-eps-context
)
5970 (setq ebnf-eps-context
(delete filename ebnf-eps-context
))
5971 (error "Try to close a not opened EPS file: %s" filename
))))
5974 (defun ebnf-eps-add-production (header)
5975 (when ebnf-eps-executing
5976 (if ebnf-eps-context
5977 (let ((prod (assoc header ebnf-eps-production-list
)))
5979 (setcdr prod
(ebnf-dup-list
5980 (append ebnf-eps-context
(cdr prod
))))
5981 (setq ebnf-eps-production-list
5982 (cons (cons header
(ebnf-dup-list ebnf-eps-context
))
5983 ebnf-eps-production-list
))))
5984 (ebnf-eps-header-footer-file (ebnf-eps-filename header
)))))
5987 (defun ebnf-dup-list (old)
5990 (setq new
(cons (car old
) new
)
5995 (defun ebnf-buffer-substring (chars)
5996 (buffer-substring-no-properties
5999 (skip-chars-forward chars ebnf-limit
)
6003 ;; replace the range "\240-\377" (see `ebnf-range-regexp').
6004 (defconst ebnf-8-bit-chars
(ebnf-range-regexp "" ?
\240 ?
\377))
6007 (defun ebnf-string (chars eos-char kind
)
6009 (buffer-substring-no-properties
6012 ;;(skip-chars-forward (concat chars "\240-\377") ebnf-limit)
6013 (skip-chars-forward (concat chars ebnf-8-bit-chars
) ebnf-limit
)
6014 (if (or (eobp) (/= (following-char) eos-char
))
6015 (error "Invalid %s: missing `%c'" kind eos-char
)
6020 (defun ebnf-get-string ()
6022 (buffer-substring-no-properties (point) (ebnf-end-of-string)))
6025 (defun ebnf-end-of-string ()
6027 (while (> (logand n
1) 0)
6028 (skip-chars-forward "^\"" ebnf-limit
)
6029 (setq n
(- (skip-chars-backward "\\\\")))
6030 (goto-char (+ (point) n
1))))
6031 (if (= (preceding-char) ?
\")
6033 (error "Missing `\"'")))
6036 (defun ebnf-trim-right (str)
6037 (let* ((len (1- (length str
)))
6039 ;; to keep compatibility with Emacs 20 & 21:
6040 ;; DO NOT REPLACE `?\ ' BY `?\s'
6041 (while (and (> index
0) (= (aref str index
) ?\
))
6042 (setq index
(1- index
)))
6045 (substring str
0 (1+ index
)))))
6048 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6052 (defun ebnf-make-empty (&optional width
)
6053 (vector 'ebnf-generate-empty
; 0 generator
6054 'ignore
; 1 width fun
6055 'ignore
; 2 dimension fun
6058 (or width ebnf-horizontal-space
))) ; 5 width
6061 (defun ebnf-make-terminal (name)
6062 (ebnf-make-terminal1 name
6063 'ebnf-generate-terminal
6064 'ebnf-terminal-dimension
))
6067 (defun ebnf-make-non-terminal (name)
6068 (ebnf-make-terminal1 name
6069 'ebnf-generate-non-terminal
6070 'ebnf-non-terminal-dimension
))
6073 (defun ebnf-make-special (name)
6074 (ebnf-make-terminal1 name
6075 'ebnf-generate-special
6076 'ebnf-special-dimension
))
6079 (defun ebnf-make-terminal1 (name gen-func dim-func
)
6080 (vector gen-func
; 0 generatore
6081 'ignore
; 1 width fun
6082 dim-func
; 2 dimension fun
6086 (let ((len (length name
))) ; 6 name
6087 (cond ((> len
3) name
)
6088 ((= len
3) (concat name
" "))
6089 ((= len
2) (concat " " name
" "))
6090 ((= len
1) (concat " " name
" "))
6092 ebnf-default-p
)) ; 7 is default?
6095 (defun ebnf-make-one-or-more (list-part &optional sep-part
)
6096 (ebnf-make-or-more1 'ebnf-generate-one-or-more
6097 'ebnf-one-or-more-dimension
6102 (defun ebnf-make-zero-or-more (list-part &optional sep-part
)
6103 (ebnf-make-or-more1 'ebnf-generate-zero-or-more
6104 'ebnf-zero-or-more-dimension
6109 (defun ebnf-make-or-more1 (gen-func dim-func list-part sep-part
)
6110 (vector gen-func
; 0 generator
6111 'ebnf-element-width
; 1 width fun
6112 dim-func
; 2 dimension fun
6116 (if (listp list-part
) ; 6 element
6117 (ebnf-make-sequence list-part
)
6119 (if (and sep-part
(listp sep-part
)) ; 7 separator
6120 (ebnf-make-sequence sep-part
)
6124 (defun ebnf-make-production (name prod action
)
6125 (vector 'ebnf-generate-production
; 0 generator
6126 'ignore
; 1 width fun
6127 'ebnf-production-dimension
; 2 dimension fun
6131 name
; 6 production name
6132 prod
; 7 production body
6133 action
)) ; 8 production action
6136 (defun ebnf-make-alternative (body)
6137 (vector 'ebnf-generate-alternative
; 0 generator
6138 'ebnf-alternative-width
; 1 width fun
6139 'ebnf-alternative-dimension
; 2 dimension fun
6143 body
)) ; 6 alternative list
6146 (defun ebnf-make-optional (body)
6147 (vector 'ebnf-generate-optional
; 0 generator
6148 'ebnf-alternative-width
; 1 width fun
6149 'ebnf-optional-dimension
; 2 dimension fun
6153 body
)) ; 6 optional element
6156 (defun ebnf-make-except (factor exception
)
6157 (vector 'ebnf-generate-except
; 0 generator
6158 'ignore
; 1 width fun
6159 'ebnf-except-dimension
; 2 dimension fun
6163 factor
; 6 base element
6164 exception
)) ; 7 exception element
6167 (defun ebnf-make-repeat (times primary
&optional upper
)
6168 (vector 'ebnf-generate-repeat
; 0 generator
6169 'ignore
; 1 width fun
6170 'ebnf-repeat-dimension
; 2 dimension fun
6175 (cond ((and times upper
) ; L * U, L * L
6176 (if (string= times upper
)
6177 (if (string= times
"")
6180 (concat times
" * " upper
)))
6182 (concat times
" *"))
6184 (concat "* " upper
))
6187 primary
)) ; 7 element
6190 (defun ebnf-make-sequence (seq)
6191 (vector 'ebnf-generate-sequence
; 0 generator
6192 'ebnf-sequence-width
; 1 width fun
6193 'ebnf-sequence-dimension
; 2 dimension fun
6200 (defun ebnf-make-dup-sequence (node seq
)
6201 (vector 'ebnf-generate-sequence
; 0 generator
6202 'ebnf-sequence-width
; 1 width fun
6203 'ebnf-sequence-dimension
; 2 dimension fun
6204 (ebnf-node-entry node
) ; 3 entry
6205 (ebnf-node-height node
) ; 4 height
6206 (ebnf-node-width node
) ; 5 width
6210 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6211 ;; Optimizers used by parsers
6214 (defun ebnf-token-except (element exception
)
6217 (setq exception
(cdr exception
)))
6218 (and element
; EMPTY - A ==> EMPTY
6219 (let ((kind (ebnf-node-kind element
)))
6222 ((and (null exception
)
6223 (eq kind
'ebnf-generate-optional
))
6224 (ebnf-node-list element
))
6225 ;; { A }- ==> { A }+
6226 ((and (null exception
)
6227 (eq kind
'ebnf-generate-zero-or-more
))
6228 (ebnf-node-kind element
'ebnf-generate-one-or-more
)
6229 (ebnf-node-dimension-func element
'ebnf-one-or-more-dimension
)
6231 ;; ( A | EMPTY )- ==> A
6232 ;; ( A | B | EMPTY )- ==> A | B
6233 ((and (null exception
)
6234 (eq kind
'ebnf-generate-alternative
)
6236 (car (last (ebnf-node-list element
))))
6237 'ebnf-generate-empty
))
6238 (let ((elt (ebnf-node-list element
))
6244 ;; this should not happen!!?!
6245 (setq element
(ebnf-make-empty
6246 (ebnf-node-width element
)))
6248 (setq elt
(ebnf-node-list element
))
6249 (and (= (length elt
) 1)
6250 (setq element
(car elt
))))
6254 (ebnf-make-except element exception
))
6258 (defun ebnf-token-repeat (times repeat
&optional upper
)
6259 (if (null (cdr repeat
))
6260 ;; n * EMPTY ==> EMPTY
6264 (ebnf-make-repeat times
(cdr repeat
) upper
))))
6267 (defun ebnf-token-optional (body)
6268 (let ((kind (ebnf-node-kind body
)))
6270 ;; [ EMPTY ] ==> EMPTY
6271 ((eq kind
'ebnf-generate-empty
)
6273 ;; [ { A }* ] ==> { A }*
6274 ((eq kind
'ebnf-generate-zero-or-more
)
6276 ;; [ { A }+ ] ==> { A }*
6277 ((eq kind
'ebnf-generate-one-or-more
)
6278 (ebnf-node-kind body
'ebnf-generate-zero-or-more
)
6280 ;; [ A | B ] ==> A | B | EMPTY
6281 ((eq kind
'ebnf-generate-alternative
)
6282 (ebnf-node-list body
(nconc (ebnf-node-list body
)
6283 (list (ebnf-make-empty))))
6287 (ebnf-make-optional body
))
6291 (defun ebnf-token-alternative (body sequence
)
6297 (cons (car sequence
) ; token
6299 (cons (car sequence
) ; token
6300 (let ((seq (cdr sequence
)))
6301 (if (and (= (length body
) 1) (null seq
))
6302 ;; alternative with one element
6304 ;; a real alternative
6305 (ebnf-make-alternative (nreverse (if seq
6310 (defun ebnf-token-sequence (sequence)
6315 ;; sequence with only one element
6316 ((= (length sequence
) 1)
6320 (ebnf-make-sequence (nreverse sequence
)))
6324 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6325 ;; Variables used by parsers
6328 (defconst ebnf-comment-table
6329 (let ((table (make-vector 256 nil
)))
6330 ;; Override special comment character:
6331 (aset table ?
< 'newline
)
6332 (aset table ?
> 'keep-line
)
6333 (aset table ?^
'form-feed
)
6335 "Vector used to map characters to a special comment token.")
6338 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6342 (defun ebnf-log-header (format-str &rest args
)
6347 "\n\n===============================================================\n\n"
6352 (defun ebnf-log (format-str &rest args
)
6355 (set-buffer (get-buffer-create "*Ebnf2ps Log*"))
6356 (goto-char (point-max))
6357 (insert (apply 'format format-str args
) "\n"))))
6360 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6361 ;; To make this file smaller, some commands go in a separate file.
6362 ;; But autoload them here to make the separation invisible.
6364 (autoload 'ebnf-abn-parser
"ebnf-abn"
6367 (autoload 'ebnf-abn-initialize
"ebnf-abn"
6368 "Initialize ABNF token table.")
6370 (autoload 'ebnf-bnf-parser
"ebnf-bnf"
6373 (autoload 'ebnf-bnf-initialize
"ebnf-bnf"
6374 "Initialize EBNF token table.")
6376 (autoload 'ebnf-iso-parser
"ebnf-iso"
6379 (autoload 'ebnf-iso-initialize
"ebnf-iso"
6380 "Initialize ISO EBNF token table.")
6382 (autoload 'ebnf-yac-parser
"ebnf-yac"
6383 "Yacc/Bison parser.")
6385 (autoload 'ebnf-yac-initialize
"ebnf-yac"
6386 "Initializations for Yacc/Bison parser.")
6388 (autoload 'ebnf-ebx-parser
"ebnf-ebx"
6391 (autoload 'ebnf-ebx-initialize
"ebnf-ebx"
6392 "Initializations for EBNFX parser.")
6394 (autoload 'ebnf-dtd-parser
"ebnf-dtd"
6397 (autoload 'ebnf-dtd-initialize
"ebnf-dtd"
6398 "Initializations for DTD parser.")
6401 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6406 ;;; arch-tag: 148bc8af-5398-468b-b922-eeb7afef3e4f
6407 ;;; ebnf2ps.el ends here