Fix up comment convention on the arch-tag lines.
[bpt/emacs.git] / lisp / progmodes / ebnf2ps.el
CommitLineData
ab3256ed 1;;; ebnf2ps.el --- translate an EBNF to a syntactic chart on PostScript
984ae001 2
4e643dd2 3;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
3ced5caa 4;; Free Software Foundation, Inc.
984ae001 5
ac4780a1
VJL
6;; Author: Vinicius Jose Latorre <viniciusjl@ig.com.br>
7;; Maintainer: Vinicius Jose Latorre <viniciusjl@ig.com.br>
0b5ecd6d 8;; Keywords: wp, ebnf, PostScript
3ced5caa 9;; Version: 4.4
502ca00a 10;; X-URL: http://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre
984ae001 11
8d9ea7b1 12;; This file is part of GNU Emacs.
984ae001 13
8d9ea7b1 14;; GNU Emacs is free software; you can redistribute it and/or modify
984ae001 15;; it under the terms of the GNU General Public License as published by
1a484753 16;; the Free Software Foundation; either version 3, or (at your option)
984ae001
GM
17;; any later version.
18
8d9ea7b1 19;; GNU Emacs is distributed in the hope that it will be useful,
984ae001
GM
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.
23
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
3a35cf56
LK
26;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
27;; Boston, MA 02110-1301, USA.
984ae001 28
3ced5caa
VJL
29(defconst ebnf-version "4.4"
30 "ebnf2ps.el, v 4.4 <2007/02/12 vinicius>
8d9ea7b1
GM
31
32Vinicius's last change version. When reporting bugs, please also
33report the version of Emacs, if any, that ebnf2ps was running with.
34
35Please send all bug fixes and enhancements to
ac4780a1 36 Vinicius Jose Latorre <viniciusjl@ig.com.br>.
8d9ea7b1
GM
37")
38
39
984ae001
GM
40;;; Commentary:
41
42;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
43;;
44;; Introduction
45;; ------------
46;;
ab3256ed 47;; This package translates an EBNF to a syntactic chart on PostScript.
984ae001
GM
48;;
49;; To use ebnf2ps, insert in your ~/.emacs:
50;;
51;; (require 'ebnf2ps)
52;;
b685181e
GM
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,
55;; etc.
984ae001
GM
56;;
57;; NOTE: ps-print zebra stripes and line number options doesn't have effect on
58;; ebnf2ps, they behave as it's turned off.
59;;
60;; For good performance, be sure to byte-compile ebnf2ps.el, e.g.
61;;
62;; M-x byte-compile-file <give the path to ebnf2ps.el when prompted>
63;;
64;; This will generate ebnf2ps.elc, which will be loaded instead of ebnf2ps.el.
65;;
66;; ebnf2ps was tested with GNU Emacs 20.4.1.
67;;
68;;
69;; Using ebnf2ps
70;; -------------
71;;
cc86f83f
VJL
72;; ebnf2ps provides the following commands for generating PostScript syntactic
73;; chart images of Emacs buffers:
984ae001 74;;
ed0aa46c
VJL
75;; ebnf-print-directory
76;; ebnf-print-file
77;; ebnf-print-buffer
78;; ebnf-print-region
79;; ebnf-spool-directory
80;; ebnf-spool-file
81;; ebnf-spool-buffer
82;; ebnf-spool-region
83;; ebnf-eps-directory
84;; ebnf-eps-file
85;; ebnf-eps-buffer
86;; ebnf-eps-region
984ae001
GM
87;;
88;; These commands all perform essentially the same function: they generate
ab3256ed 89;; PostScript syntactic chart images suitable for printing on a PostScript
984ae001
GM
90;; printer or displaying with GhostScript. These commands are collectively
91;; referred to as "ebnf- commands".
92;;
93;; The word "print", "spool" and "eps" in the command name determines when the
94;; PostScript image is sent to the printer (or file):
95;;
ed0aa46c 96;; print - The PostScript image is immediately sent to the printer;
984ae001 97;;
ed0aa46c
VJL
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
101;; `ebnf-despool'.
984ae001 102;;
4303661c 103;; eps - The PostScript image is immediately sent to an EPS file.
984ae001
GM
104;;
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.
111;;
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,
b685181e
GM
116;; you'll be asked to confirm the exit; this is modeled on the confirmation
117;; that Emacs uses for modified buffers.
984ae001 118;;
ac4780a1
VJL
119;; The word "directory", "file", "buffer" or "region" in the command name
120;; determines how much of the buffer is printed:
984ae001 121;;
ed0aa46c 122;; directory - Read files in the directory and print them.
984ae001 123;;
ed0aa46c 124;; file - Read file and print it.
ac4780a1 125;;
ed0aa46c 126;; buffer - Print the entire buffer.
ac4780a1 127;;
ed0aa46c 128;; region - Print just the current region.
984ae001
GM
129;;
130;; Two ebnf- command examples:
131;;
ed0aa46c
VJL
132;; ebnf-print-buffer - translate and print the entire buffer, and send it
133;; immediately to the printer.
984ae001 134;;
ed0aa46c
VJL
135;; ebnf-spool-region - translate and print just the current region, and
136;; spool the image in Emacs to send to the printer
137;; later.
984ae001 138;;
ac4780a1
VJL
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.
984ae001
GM
143;;
144;;
145;; Invoking Ebnf2ps
146;; ----------------
147;;
148;; To translate and print your buffer, type
149;;
ed0aa46c 150;; M-x ebnf-print-buffer
984ae001
GM
151;;
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
155;;
ed0aa46c 156;; C-u M-x ebnf-print-buffer
984ae001
GM
157;;
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
162;; `ebnf-despool':
163;;
ed0aa46c 164;; C-u M-x ebnf-despool
984ae001
GM
165;;
166;; When invoked this way, `ebnf-despool' will prompt you for the name of the
167;; file to save to.
168;;
169;; The prefix argument is also ignored by `ebnf-eps-buffer' and
170;; `ebnf-eps-region'.
171;;
172;; Any of the `ebnf-' commands can be bound to keys. Here are some examples:
173;;
ed0aa46c
VJL
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)
984ae001
GM
177;;
178;;
6411a60a
VJL
179;; Invoking Ebnf2ps in Batch
180;; -------------------------
181;;
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.
185;;
186;; To run ebnf2ps in batch type, for example:
187;;
188;; emacs -batch -l setup-ebnf2ps.el -f ebnf-eps-directory
189;;
190;; Where setup-ebnf2ps.el should be a file containing:
191;;
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)
197;; ;; etc.
198;;
199;;
984ae001
GM
200;; EBNF Syntax
201;; -----------
202;;
6411a60a
VJL
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.
208;;
984ae001
GM
209;; The current EBNF that ebnf2ps accepts has the following constructions:
210;;
211;; ; comment (until end of line)
212;; A non-terminal
213;; "C" terminal
214;; ?C? special
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)
7fd08a0a
VJL
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)
984ae001
GM
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}*]
236;;
237;; The EBNF syntax written using the notation above is:
238;;
239;; EBNF = {production}+.
240;;
241;; production = non_terminal "=" body ".". ;; production
242;;
243;; body = {sequence || "|"}*. ;; alternative
244;;
245;; sequence = {exception}*. ;; sequence
246;;
247;; exception = repeat [ "-" repeat]. ;; exception
248;;
7fd08a0a 249;; repeat = [ integer "*" [ integer ]] term. ;; repetition
984ae001
GM
250;;
251;; term = factor
252;; | [factor] "+" ;; one-or-more
253;; | [factor] "/" [factor] ;; one-or-more
254;; .
255;;
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
264;; .
265;;
0b5ecd6d 266;; non_terminal = "[!#%&'*-,0-:<>@-Z\\\\^-z~\\240-\\377]+".
ac4780a1
VJL
267;; ;; that is, a valid non_terminal accepts decimal digits, letters (upper
268;; ;; and lower), 8-bit accentuated characters,
269;; ;; "!", "#", "%", "&", "'", "*", "+", ",", ":",
270;; ;; "<", ">", "@", "\", "^", "_", "`" and "~".
984ae001
GM
271;;
272;; terminal = "\\([^\"\\]\\|\\\\[ -~\\240-\\377]\\)+".
ac4780a1
VJL
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
6f19f70a 277;; ;; example: \", \\.
984ae001 278;;
ac4780a1
VJL
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.
984ae001
GM
283;;
284;; integer = "[0-9]+".
ac4780a1 285;; ;; that is, an integer is a sequence of one or more decimal digits.
984ae001
GM
286;;
287;; comment = ";" "[^\\n\\000-\\010\\016-\\037\\177-\\237]*" "\\n".
ac4780a1
VJL
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.
984ae001
GM
291;;
292;; Try to use the above EBNF to test ebnf2ps.
293;;
294;; The `default' terminal, non-terminal and special is a way to indicate a
295;; default path in a production. For example, the production:
296;;
297;; X = [ $A ( B | $C ) | D ].
298;;
299;; Indicates that the default meaning for "X" is "A C" if "X" is empty.
300;;
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 `"'.
304;;
305;; Let's see an example:
306;;
307;; (setq ebnf-terminal-regexp "[A-Z][_A-Z]*") ; upper case name
308;; (setq ebnf-case-fold-search nil) ; exact matching
309;;
310;; If you have the production:
311;;
312;; Logical = "(" Expression ( OR | AND | "XOR" ) Expression ")".
313;;
314;; The names are classified as:
315;;
316;; Logical Expression non-terminal
317;; "(" OR AND "XOR" ")" terminal
318;;
b685181e
GM
319;; The line comment is controlled by `ebnf-lex-comment-char'. The default
320;; value is ?\; (character `;').
984ae001
GM
321;;
322;; The end of production is controlled by `ebnf-lex-eop-char'. The default
323;; value is ?. (character `.').
324;;
325;; The variable `ebnf-syntax' specifies which syntax to recognize:
326;;
327;; `ebnf' ebnf2ps recognizes the syntax described above.
328;; The following variables *ONLY* have effect with this
329;; setting:
330;; `ebnf-terminal-regexp', `ebnf-case-fold-search',
331;; `ebnf-lex-comment-char' and `ebnf-lex-eop-char'.
332;;
ac4780a1 333;; `abnf' ebnf2ps recognizes the syntax described in the URL:
97818b07 334;; `http://www.ietf.org/rfc/rfc2234.txt'
ac4780a1
VJL
335;; ("Augmented BNF for Syntax Specifications: ABNF").
336;;
984ae001
GM
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
341;; setting:
342;; `ebnf-iso-alternative-p' and `ebnf-iso-normalize-p'.
343;;
344;; `yacc' ebnf2ps recognizes the Yacc/Bison syntax.
345;; The following variable *ONLY* has effect with this
346;; setting:
347;; `ebnf-yac-ignore-error-recovery'.
348;;
6ca94f87
VJL
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)")
352;;
6411a60a
VJL
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)")
356;;
984ae001
GM
357;; Any other value is treated as `ebnf'.
358;;
359;; The default value is `ebnf'.
360;;
361;;
362;; Optimizations
363;; -------------
364;;
365;; The following EBNF optimizations are done:
366;;
367;; [ { A }* ] ==> { A }*
368;; [ { A }+ ] ==> { A }*
369;; [ A ] + ==> { A }*
370;; { A }* + ==> { A }*
371;; { A }+ + ==> { A }+
372;; { A }- ==> { A }+
373;; [ A ]- ==> A
374;; ( A | EMPTY )- ==> A
375;; ( A | B | EMPTY )- ==> A | B
376;; [ A | B ] ==> A | B | EMPTY
377;; n * EMPTY ==> EMPTY
378;; EMPTY + ==> EMPTY
379;; EMPTY / EMPTY ==> EMPTY
380;; EMPTY - A ==> EMPTY
381;;
382;; The following optimizations are done when `ebnf-optimize' is non-nil:
383;;
384;; left recursion:
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 }*.
390;;
391;; optional:
392;; 6. A = B | . ==> A = [B].
393;; 7. A = | B . ==> A = [B].
394;;
ad96a7ef 395;; factorization:
984ae001
GM
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.
399;;
400;; The above optimizations are specially useful when `ebnf-syntax' is `yacc'.
401;;
402;;
403;; Form Feed
404;; ---------
405;;
b685181e
GM
406;; You may use form feed (^L \014) to force a production to start on a new
407;; page, for example:
984ae001
GM
408;;
409;; a) A = B | C.
410;; ^L
411;; X = Y | Z.
412;;
413;; b) A = B ^L | C.
414;; X = Y | Z.
415;;
416;; c) A = B ^L^L^L | C.^L
417;; ^L
418;; X = Y | Z.
419;;
420;; In all examples above, only the production X will start on a new page.
421;;
422;;
423;; Actions in Comments
424;; -------------------
425;;
426;; ebnf2ps accepts the following actions in comments:
427;;
6411a60a
VJL
428;; ;^ same as form feed. See section Form Feed above.
429;;
984ae001
GM
430;; ;> the next production starts in the same line as the current one.
431;; It is useful when `ebnf-horizontal-orientation' is nil.
432;;
433;; ;< the next production starts in the next line.
434;; It is useful when `ebnf-horizontal-orientation' is non-nil.
435;;
436;; ;[EPS open a new EPS file. The EPS file name has the form:
437;; <PREFIX><NAME>.eps
b685181e
GM
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
984ae001
GM
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.
445;;
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.
450;;
3ced5caa
VJL
451;; ;Hheader generate a header in current EPS file. The header string can
452;; have the following formats:
453;;
454;; %% prints a % character.
455;;
456;; %H prints the `ebnf-eps-header' (which see) value.
457;;
458;; %F prints the `ebnf-eps-footer' (which see) value.
459;;
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.
465;;
466;; ;Ffooter generate a footer in current EPS file. Similar to ;H action
467;; comment.
468;;
984ae001
GM
469;; So if you have:
470;;
471;; (setq ebnf-horizontal-orientation nil)
472;;
473;; A = t.
474;; C = x.
475;; ;> C and B are drawn in the same line
476;; B = y.
477;; W = v.
478;;
479;; The graphical result is:
480;;
481;; +---+
482;; | A |
483;; +---+
484;;
485;; +---------+ +-----+
486;; | | | |
487;; | C | | |
488;; | | | B |
489;; +---------+ | |
490;; | |
491;; +-----+
492;;
493;; +-----------+
494;; | W |
495;; +-----------+
496;;
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.
499;;
b685181e
GM
500;; If consecutive actions occur, only the last one takes effect, so if you
501;; have:
984ae001
GM
502;;
503;; A = X.
504;; ;<
505;; ^L
506;; ;>
507;; B = Y.
508;;
509;; Only the ;> will take effect, that is, A and B will be drawn in the same
510;; line.
511;;
6411a60a
VJL
512;; In ISO EBNF the above actions are specified as (*^*), (*>*), (*<*), (*[EPS*)
513;; and (*]EPS*). The first example above should be written:
984ae001
GM
514;;
515;; A = t;
516;; C = x;
517;; (*> C and B are drawn in the same line *)
518;; B = y;
519;; W = v;
520;;
521;; For an example of EPS action when executing `ebnf-eps-buffer' or
522;; `ebnf-eps-region':
523;;
524;; Z = B0.
525;; ;[CC
526;; ;[AA
527;; A = B1.
528;; ;[BB
529;; C = B2.
530;; ;]AA
531;; B = B3.
532;; ;]BB
533;; ;]CC
534;; D = B4.
535;; E = B5.
536;; ;[CC
537;; F = B6.
538;; ;]CC
539;; G = B7.
540;;
541;; The following table summarizes the results:
542;;
ed0aa46c
VJL
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
547;; ebnf--D.eps D D D
548;; ebnf--E.eps E E E
549;; ebnf--G.eps G G G
550;; ebnf--Z.eps Z Z Z
984ae001
GM
551;;
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.
555;;
556;; In the following case:
557;;
558;; A = B0.
559;; ;[AA
560;; A = B1.
561;; ;[BB
562;; A = B2.
563;;
564;; The production A is generated in both files ebnf--AA.eps and ebnf--BB.eps.
565;;
566;;
3ced5caa
VJL
567;; Log Messages
568;; ------------
569;;
570;; The buffer *Ebnf2ps Log* is where the ebnf2ps log messages are inserted.
571;; These messages are intended to help debugging ebnf2ps.
572;;
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.
575;;
576;;
984ae001
GM
577;; Utilities
578;; ---------
579;;
580;; Some tools are provided to help you.
581;;
582;; `ebnf-setup' returns the current setup.
583;;
cd0f9f85
VJL
584;; `ebnf-syntax-directory' does a syntactic analysis of your EBNF files in the
585;; given directory.
586;;
587;; `ebnf-syntax-file' does a syntactic analysis of your EBNF in the given
588;; file.
589;;
ab3256ed 590;; `ebnf-syntax-buffer' does a syntactic analysis of your EBNF in the current
984ae001
GM
591;; buffer.
592;;
ab3256ed 593;; `ebnf-syntax-region' does a syntactic analysis of your EBNF in the current
984ae001
GM
594;; region.
595;;
596;; `ebnf-customize' activates a customization buffer for ebnf2ps options.
597;;
cd0f9f85
VJL
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.
984ae001
GM
601;;
602;;
603;; Hooks
604;; -----
605;;
606;; ebn2ps has the following hook variables:
607;;
608;; `ebnf-hook'
609;; It is evaluated once before any ebnf2ps process.
610;;
611;; `ebnf-production-hook'
612;; It is evaluated on each beginning of production.
613;;
614;; `ebnf-page-hook'
615;; It is evaluated on each beginning of page.
616;;
617;;
618;; Options
619;; -------
620;;
621;; Below it's shown a brief description of ebnf2ps options, please, see the
622;; options declaration in the code for a long documentation.
623;;
624;; `ebnf-horizontal-orientation' Non-nil means productions are drawn
625;; horizontally.
626;;
627;; `ebnf-horizontal-max-height' Non-nil means to use maximum production
628;; height in horizontal orientation.
629;;
630;; `ebnf-production-horizontal-space' Specify horizontal space in points
631;; between productions.
632;;
b685181e
GM
633;; `ebnf-production-vertical-space' Specify vertical space in points
634;; between productions.
984ae001
GM
635;;
636;; `ebnf-justify-sequence' Specify justification of terms in a
637;; sequence inside alternatives.
638;;
639;; `ebnf-terminal-regexp' Specify how it's a terminal name.
640;;
641;; `ebnf-case-fold-search' Non-nil means ignore case on matching.
642;;
643;; `ebnf-terminal-font' Specify terminal font.
644;;
645;; `ebnf-terminal-shape' Specify terminal box shape.
646;;
647;; `ebnf-terminal-shadow' Non-nil means terminal box will have a
648;; shadow.
649;;
650;; `ebnf-terminal-border-width' Specify border width for terminal box.
651;;
652;; `ebnf-terminal-border-color' Specify border color for terminal box.
653;;
ac4780a1
VJL
654;; `ebnf-production-name-p' Non-nil means production name will be
655;; printed.
656;;
984ae001
GM
657;; `ebnf-sort-production' Specify how productions are sorted.
658;;
659;; `ebnf-production-font' Specify production font.
660;;
661;; `ebnf-non-terminal-font' Specify non-terminal font.
662;;
663;; `ebnf-non-terminal-shape' Specify non-terminal box shape.
664;;
b685181e
GM
665;; `ebnf-non-terminal-shadow' Non-nil means non-terminal box will
666;; have a shadow.
984ae001
GM
667;;
668;; `ebnf-non-terminal-border-width' Specify border width for non-terminal
669;; box.
670;;
671;; `ebnf-non-terminal-border-color' Specify border color for non-terminal
672;; box.
673;;
ac4780a1
VJL
674;; `ebnf-special-show-delimiter' Non-nil means special delimiter
675;; (character `?') is shown.
676;;
984ae001
GM
677;; `ebnf-special-font' Specify special font.
678;;
679;; `ebnf-special-shape' Specify special box shape.
680;;
681;; `ebnf-special-shadow' Non-nil means special box will have a
682;; shadow.
683;;
684;; `ebnf-special-border-width' Specify border width for special box.
685;;
686;; `ebnf-special-border-color' Specify border color for special box.
687;;
688;; `ebnf-except-font' Specify except font.
689;;
690;; `ebnf-except-shape' Specify except box shape.
691;;
692;; `ebnf-except-shadow' Non-nil means except box will have a
693;; shadow.
694;;
695;; `ebnf-except-border-width' Specify border width for except box.
696;;
697;; `ebnf-except-border-color' Specify border color for except box.
698;;
699;; `ebnf-repeat-font' Specify repeat font.
700;;
701;; `ebnf-repeat-shape' Specify repeat box shape.
702;;
703;; `ebnf-repeat-shadow' Non-nil means repeat box will have a
704;; shadow.
705;;
706;; `ebnf-repeat-border-width' Specify border width for repeat box.
707;;
708;; `ebnf-repeat-border-color' Specify border color for repeat box.
709;;
710;; `ebnf-entry-percentage' Specify entry height on alternatives.
711;;
712;; `ebnf-arrow-shape' Specify the arrow shape.
713;;
714;; `ebnf-chart-shape' Specify chart flow shape.
715;;
716;; `ebnf-color-p' Non-nil means use color.
717;;
718;; `ebnf-line-width' Specify flow line width.
719;;
720;; `ebnf-line-color' Specify flow line color.
721;;
ed0aa46c
VJL
722;; `ebnf-arrow-extra-width' Specify extra width for arrow shape
723;; drawing.
724;;
725;; `ebnf-arrow-scale' Specify the arrow scale.
726;;
bf061ba6 727;; `ebnf-user-arrow' Specify a sexp for user arrow shape (a
b685181e 728;; PostScript code).
984ae001
GM
729;;
730;; `ebnf-debug-ps' Non-nil means to generate PostScript
731;; debug procedures.
732;;
733;; `ebnf-lex-comment-char' Specify the line comment character.
734;;
b685181e
GM
735;; `ebnf-lex-eop-char' Specify the end of production
736;; character.
984ae001
GM
737;;
738;; `ebnf-syntax' Specify syntax to be recognized.
739;;
740;; `ebnf-iso-alternative-p' Non-nil means use alternative ISO EBNF.
741;;
742;; `ebnf-iso-normalize-p' Non-nil means normalize ISO EBNF syntax
743;; names.
744;;
745;; `ebnf-default-width' Specify additional border width over
746;; default terminal, non-terminal or
747;; special.
748;;
ac4780a1
VJL
749;; `ebnf-file-suffix-regexp' Specify file name suffix that contains
750;; EBNF.
751;;
984ae001
GM
752;; `ebnf-eps-prefix' Specify EPS prefix file name.
753;;
3ced5caa
VJL
754;; `ebnf-eps-header-font' Specify EPS header font.
755;;
756;; `ebnf-eps-header' Specify EPS header.
757;;
758;; `ebnf-eps-footer-font' Specify EPS footer font.
759;;
760;; `ebnf-eps-footer' Specify EPS footer.
761;;
984ae001
GM
762;; `ebnf-use-float-format' Non-nil means use `%f' float format.
763;;
ac4780a1
VJL
764;; `ebnf-stop-on-error' Non-nil means signal error and stop.
765;; Nil means signal error and continue.
766;;
984ae001
GM
767;; `ebnf-yac-ignore-error-recovery' Non-nil means ignore error recovery.
768;;
769;; `ebnf-ignore-empty-rule' Non-nil means ignore empty rules.
770;;
ab3256ed 771;; `ebnf-optimize' Non-nil means optimize syntactic chart
b685181e 772;; of rules.
984ae001 773;;
3ced5caa
VJL
774;; `ebnf-log' Non-nil means generate log messages.
775;;
984ae001
GM
776;; To set the above options you may:
777;;
778;; a) insert the code in your ~/.emacs, like:
779;;
780;; (setq ebnf-terminal-shape 'bevel)
781;;
782;; This way always keep your default settings when you enter a new Emacs
783;; session.
784;;
785;; b) or use `set-variable' in your Emacs session, like:
786;;
787;; M-x set-variable RET ebnf-terminal-shape RET bevel RET
788;;
789;; This way keep your settings only during the current Emacs session.
790;;
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.
800;;
801;; d) or see the option value:
802;;
803;; C-h v ebnf-terminal-shape RET
804;;
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.
808;;
809;; e) or invoke:
810;;
811;; M-x ebnf-customize RET
812;;
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.
816;;
817;;
818;; Styles
819;; ------
820;;
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.
824;;
825;; To help to handle this situation, ebnf2ps has the following commands to
826;; handle styles:
827;;
3ced5caa
VJL
828;; `ebnf-find-style' Return style definition if NAME is already defined;
829;; otherwise, return nil.
830;;
984ae001
GM
831;; `ebnf-insert-style' Insert a new style NAME with inheritance INHERITS and
832;; values VALUES.
833;;
ac4780a1
VJL
834;; `ebnf-delete-style' Delete style NAME.
835;;
984ae001
GM
836;; `ebnf-merge-style' Merge values of style NAME with style VALUES.
837;;
ac4780a1 838;; `ebnf-apply-style' Set STYLE as the current style.
984ae001
GM
839;;
840;; `ebnf-reset-style' Reset current style.
841;;
ac4780a1 842;; `ebnf-push-style' Push the current style and set STYLE as the current
6f19f70a 843;; style.
984ae001 844;;
ac4780a1 845;; `ebnf-pop-style' Pop a style and set it as the current style.
984ae001 846;;
ac4780a1 847;; These commands help to put together a lot of variable settings in a group
984ae001
GM
848;; and name this group. So when you wish to apply these settings it's only
849;; needed to give the name.
850;;
4303661c
VJL
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.
984ae001
GM
855;;
856;; See documentation for `ebnf-style-database'.
857;;
858;;
859;; Layout
860;; ------
861;;
862;; Below it is the layout of minimum area to draw each element, and it's used
863;; the following terms:
864;;
865;; font height is given by:
866;; (terminal font height + non-terminal font height) / 2
867;;
b685181e
GM
868;; entry is the vertical position used to know where it should
869;; be drawn the flow line in the current element.
984ae001 870;;
ed0aa46c
VJL
871;; extra is given by `ebnf-arrow-extra-width'.
872;;
984ae001
GM
873;;
874;; * SPECIAL, TERMINAL and NON-TERMINAL
875;;
876;; +==============+...................................
877;; | | } font height / 2 } entry }
878;; | XXXXXXXX...|....... } }
879;; ====+ XXXXXXXX +==== } text height ...... } height
880;; : | XXXXXXXX...|...:... }
881;; : | : : | : } font height / 2 }
882;; : +==============+...:...............................
883;; : : : : : :
ed0aa46c
VJL
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;; :.................................................
984ae001
GM
895;;
896;;
897;; * OPTIONAL
898;;
899;; +==========+.....................................
900;; | | } } }
901;; | | } entry } }
902;; | | } } }
903;; ===+===+ +===+===... } element height } height
904;; : \ | | / : } }
905;; : + | | + : } }
906;; : | +==========+.|................. }
907;; : | : : | : } font height }
908;; : +==============+...................................
909;; : : : :
910;; : : : :......................
911;; : : : } font height * 2 }
912;; : : :.......... }
913;; : : } element width } width
914;; : :..................... }
915;; : } font height * 2 }
916;; :...............................................
917;;
918;;
919;; * ALTERNATIVE
920;;
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;; : : +===+...................................
932;; : : : :
933;; : : : :......................
934;; : : : } font height * 2 }
935;; : : :......... }
936;; : : } max width } width
937;; : :................. }
938;; : } font height * 2 }
939;; :..........................................
940;;
941;; NOTES:
942;; 1. An empty alternative has zero of height.
943;;
944;; 2. The variable `ebnf-entry-percentage' is used to determine the
945;; entry point.
946;;
947;;
948;; * ZERO OR MORE
949;;
950;; +===========+...............................
951;; +=+ separator +=+ } separator height }
952;; / +===========+..\........ }
953;; + + } }
954;; | | } font height }
955;; + + } }
956;; \ +===========+../........ } height = entry
957;; +=+ element +=+ } element height }
958;; /: +===========+..\........ }
959;; + : : + } }
960;; + : : + } font height }
961;; / : : \ } }
962;; ==+=======================+==.......................
963;; : : : :
964;; : : : :.......................
965;; : : : } font height * 2 }
966;; : : :......... }
967;; : : } max width } width
968;; : :......................... }
969;; : } font height * 2 }
970;; :...................................................
971;;
972;;
973;; * ONE OR MORE
974;;
975;; +===========+......................................
976;; +=+ separator +=+ } separator height } }
977;; / +===========+..\...... } }
978;; + + } } entry }
979;; | | } font height } } height
980;; + + } } }
981;; \ +===========+../...... } }
982;; ===+=+ element +=+=== } element height .... }
983;; : : +===========+......................................
984;; : : : :
985;; : : : :........................
986;; : : : } font height * 2 }
987;; : : :....... }
988;; : : } max width } width
989;; : :....................... }
990;; : } font height * 2 }
991;; :..............................................
992;;
993;;
994;; * PRODUCTION
995;;
996;; XXXXXX:......................................
997;; XXXXXX: } production font height }
998;; XXXXXX:............ }
999;; } font height }
1000;; +======+....... } height = entry
1001;; | | } }
1002;; ====+ +==== } element height }
1003;; : | | : } }
1004;; : +======+.................................
1005;; : : : :
1006;; : : : :......................
1007;; : : : } font height * 2 }
1008;; : : :....... }
1009;; : : } element width } width
1010;; : :.............. }
1011;; : } font height * 2 }
1012;; :.....................................
1013;;
1014;;
1015;; * REPEAT
1016;;
1017;; +================+...................................
1018;; | | } font height / 2 } entry }
1019;; | +===+...|....... } }
1020;; ====+ N * | X | +==== } X height ......... } height
1021;; : | : : +===+...|...:... }
1022;; : | : : : : | : } font height / 2 }
1023;; : +================+...:...............................
1024;; : : : : : : : :
ed0aa46c
VJL
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;; :...................................................
984ae001
GM
1040;;
1041;;
1042;; * EXCEPT
1043;;
1044;; +==================+...................................
1045;; | | } font height / 2 } entry }
1046;; | +===+ +===+...|....... } }
1047;; ====+ | X | - | y | +==== } max height ....... } height
1048;; : | +===+ +===+...|...:... }
1049;; : | : : : : | : } font height / 2 }
1050;; : +==================+...:...............................
1051;; : : : : : : : :
ed0aa46c
VJL
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;; :.....................................................
984ae001
GM
1067;;
1068;; NOTE: If Y element is empty, it's draw nothing at Y place.
1069;;
1070;;
1071;; Internal Structures
1072;; -------------------
1073;;
ab3256ed 1074;; ebnf2ps has two passes. The first pass does a lexical and syntactic analysis
984ae001 1075;; of current buffer and generates an intermediate representation. The second
b685181e 1076;; pass uses the intermediate representation to generate the PostScript
ab3256ed 1077;; syntactic chart.
984ae001
GM
1078;;
1079;; The intermediate representation is a list of vectors, the vector element
ab3256ed
JB
1080;; represents a syntactic chart element. Below is a vector representation for
1081;; each syntactic chart element.
984ae001 1082;;
b685181e 1083;; [production WIDTH-FUN DIM-FUN ENTRY HEIGHT WIDTH NAME PRODUCTION ACTION]
984ae001
GM
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]
1095;;
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
1105;; one.
1106;; LIST is a list of vector that represents the list part for alternatives and
1107;; sequences.
1108;; SEPARATOR is a vector that represents the sub-element used to separate the
1109;; list elements.
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:
1114;;
1115;; nil no action.
1116;;
1117;; form-feed current production starts on a new page.
1118;;
1119;; newline current production starts on next line, this is useful
1120;; when `ebnf-horizontal-orientation' is non-nil.
1121;;
1122;; keep-line current production continues on the current line, this
1123;; is useful when `ebnf-horizontal-orientation' is nil.
1124;;
1125;;
1126;; Things To Change
1127;; ----------------
1128;;
ab3256ed 1129;; . Handle situations when syntactic chart is out of paper.
984ae001
GM
1130;; . Use other alphabet than ascii.
1131;; . Optimizations...
1132;;
1133;;
1134;; Acknowledgements
1135;; ----------------
1136;;
4303661c
VJL
1137;; Thanks to Eli Zaretskii <eliz@gnu.org> for some doc fixes.
1138;;
ea946fcc 1139;; Thanks to Drew Adams <drew.adams@oracle.com> for suggestions:
ed0aa46c
VJL
1140;; - `ebnf-arrow-extra-width', `ebnf-arrow-scale',
1141;; `ebnf-production-name-p', `ebnf-stop-on-error',
ac4780a1
VJL
1142;; `ebnf-file-suffix-regexp'and `ebnf-special-show-delimiter' variables.
1143;; - `ebnf-delete-style', `ebnf-eps-file' and `ebnf-eps-directory'
1144;; commands.
1145;; - some docs fix.
1146;;
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.
1150;;
984ae001
GM
1151;; Thanks to all who emailed comments.
1152;;
1153;;
1154;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1155
e8af40ee 1156;;; Code:
984ae001
GM
1157
1158
1159(require 'ps-print)
1160
b685181e
GM
1161(and (string< ps-print-version "5.2.3")
1162 (error "`ebnf2ps' requires `ps-print' package version 5.2.3 or later"))
984ae001 1163
ea946fcc
VJL
1164
1165;; to avoid gripes with Emacs 20
99439846
VJL
1166(or (fboundp 'assq-delete-all)
1167 (defun assq-delete-all (key alist)
1168 "Delete from ALIST all elements whose car is KEY.
ea946fcc
VJL
1169Return the modified alist.
1170Elements of ALIST that are not conses are ignored."
99439846
VJL
1171 (let ((tail alist))
1172 (while tail
1173 (if (and (consp (car tail))
1174 (eq (car (car tail)) key))
1175 (setq alist (delq (car tail) alist)))
1176 (setq tail (cdr tail)))
1177 alist)))
ea946fcc 1178
984ae001
GM
1179\f
1180;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1181;; User Variables:
1182
1183
1184;;; Interface to the command system
1185
1186(defgroup postscript nil
dfbe3e71 1187 "PostScript Group."
984ae001 1188 :tag "PostScript"
b11b1870 1189 :version "20"
984ae001
GM
1190 :group 'emacs)
1191
1192
1193(defgroup ebnf2ps nil
dfbe3e71 1194 "Translate an EBNF to a syntactic chart on PostScript."
984ae001 1195 :prefix "ebnf-"
b11b1870 1196 :version "20"
984ae001
GM
1197 :group 'wp
1198 :group 'postscript)
1199
1200
1201(defgroup ebnf-special nil
dfbe3e71 1202 "Special customization."
984ae001
GM
1203 :prefix "ebnf-"
1204 :tag "Special"
b11b1870 1205 :version "20"
984ae001
GM
1206 :group 'ebnf2ps)
1207
1208
1209(defgroup ebnf-except nil
dfbe3e71 1210 "Except customization."
984ae001
GM
1211 :prefix "ebnf-"
1212 :tag "Except"
b11b1870 1213 :version "20"
984ae001
GM
1214 :group 'ebnf2ps)
1215
1216
1217(defgroup ebnf-repeat nil
dfbe3e71 1218 "Repeat customization."
984ae001
GM
1219 :prefix "ebnf-"
1220 :tag "Repeat"
b11b1870 1221 :version "20"
984ae001
GM
1222 :group 'ebnf2ps)
1223
1224
1225(defgroup ebnf-terminal nil
dfbe3e71 1226 "Terminal customization."
984ae001
GM
1227 :prefix "ebnf-"
1228 :tag "Terminal"
b11b1870 1229 :version "20"
984ae001
GM
1230 :group 'ebnf2ps)
1231
1232
1233(defgroup ebnf-non-terminal nil
dfbe3e71 1234 "Non-Terminal customization."
984ae001
GM
1235 :prefix "ebnf-"
1236 :tag "Non-Terminal"
b11b1870 1237 :version "20"
984ae001
GM
1238 :group 'ebnf2ps)
1239
1240
1241(defgroup ebnf-production nil
dfbe3e71 1242 "Production customization."
984ae001
GM
1243 :prefix "ebnf-"
1244 :tag "Production"
b11b1870 1245 :version "20"
984ae001
GM
1246 :group 'ebnf2ps)
1247
1248
1249(defgroup ebnf-shape nil
dfbe3e71 1250 "Shapes customization."
984ae001
GM
1251 :prefix "ebnf-"
1252 :tag "Shape"
b11b1870 1253 :version "20"
984ae001
GM
1254 :group 'ebnf2ps)
1255
1256
1257(defgroup ebnf-displacement nil
dfbe3e71 1258 "Displacement customization."
984ae001
GM
1259 :prefix "ebnf-"
1260 :tag "Displacement"
b11b1870 1261 :version "20"
984ae001
GM
1262 :group 'ebnf2ps)
1263
1264
ab3256ed 1265(defgroup ebnf-syntactic nil
dfbe3e71 1266 "Syntactic customization."
984ae001 1267 :prefix "ebnf-"
ab3256ed 1268 :tag "Syntactic"
b11b1870 1269 :version "20"
984ae001
GM
1270 :group 'ebnf2ps)
1271
1272
1273(defgroup ebnf-optimization nil
dfbe3e71 1274 "Optimization customization."
984ae001
GM
1275 :prefix "ebnf-"
1276 :tag "Optimization"
b11b1870 1277 :version "20"
984ae001
GM
1278 :group 'ebnf2ps)
1279
1280
1281(defcustom ebnf-horizontal-orientation nil
1282 "*Non-nil means productions are drawn horizontally."
1283 :type 'boolean
b11b1870 1284 :version "20"
984ae001
GM
1285 :group 'ebnf-displacement)
1286
1287
1288(defcustom ebnf-horizontal-max-height nil
1289 "*Non-nil means to use maximum production height in horizontal orientation.
1290
1291It is only used when `ebnf-horizontal-orientation' is non-nil."
1292 :type 'boolean
b11b1870 1293 :version "20"
984ae001
GM
1294 :group 'ebnf-displacement)
1295
1296
1297(defcustom ebnf-production-horizontal-space 0.0 ; use ebnf2ps default value
1298 "*Specify horizontal space in points between productions.
1299
1300Value less or equal to zero forces ebnf2ps to set a proper default value."
1301 :type 'number
b11b1870 1302 :version "20"
984ae001
GM
1303 :group 'ebnf-displacement)
1304
1305
1306(defcustom ebnf-production-vertical-space 0.0 ; use ebnf2ps default value
1307 "*Specify vertical space in points between productions.
1308
1309Value less or equal to zero forces ebnf2ps to set a proper default value."
1310 :type 'number
b11b1870 1311 :version "20"
984ae001
GM
1312 :group 'ebnf-displacement)
1313
1314
1315(defcustom ebnf-justify-sequence 'center
1316 "*Specify justification of terms in a sequence inside alternatives.
1317
1318Valid values are:
1319
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))
b11b1870 1325 :version "20"
984ae001
GM
1326 :group 'ebnf-displacement)
1327
1328
ac4780a1
VJL
1329(defcustom ebnf-special-show-delimiter t
1330 "*Non-nil means special delimiter (character `?') is shown."
1331 :type 'boolean
b11b1870 1332 :version "20"
ac4780a1
VJL
1333 :group 'ebnf-special)
1334
1335
984ae001
GM
1336(defcustom ebnf-special-font '(7 Courier "Black" "Gray95" bold italic)
1337 "*Specify special font.
1338
1339See 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))))
b11b1870 1354 :version "20"
984ae001
GM
1355 :group 'ebnf-special)
1356
1357
1358(defcustom ebnf-special-shape 'bevel
1359 "*Specify special box shape.
1360
1361See documentation for `ebnf-non-terminal-shape'."
1362 :type '(radio :tag "Special Shape"
1363 (const miter) (const round) (const bevel))
b11b1870 1364 :version "20"
984ae001
GM
1365 :group 'ebnf-special)
1366
1367
1368(defcustom ebnf-special-shadow nil
1369 "*Non-nil means special box will have a shadow."
1370 :type 'boolean
b11b1870 1371 :version "20"
984ae001
GM
1372 :group 'ebnf-special)
1373
1374
1375(defcustom ebnf-special-border-width 0.5
1376 "*Specify border width for special box."
1377 :type 'number
b11b1870 1378 :version "20"
984ae001
GM
1379 :group 'ebnf-special)
1380
1381
1382(defcustom ebnf-special-border-color "Black"
1383 "*Specify border color for special box."
1384 :type 'string
b11b1870 1385 :version "20"
984ae001
GM
1386 :group 'ebnf-special)
1387
1388
1389(defcustom ebnf-except-font '(7 Courier "Black" "Gray90" bold italic)
1390 "*Specify except font.
1391
1392See 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))))
b11b1870 1407 :version "20"
984ae001
GM
1408 :group 'ebnf-except)
1409
1410
1411(defcustom ebnf-except-shape 'bevel
1412 "*Specify except box shape.
1413
1414See documentation for `ebnf-non-terminal-shape'."
1415 :type '(radio :tag "Except Shape"
1416 (const miter) (const round) (const bevel))
b11b1870 1417 :version "20"
984ae001
GM
1418 :group 'ebnf-except)
1419
1420
1421(defcustom ebnf-except-shadow nil
1422 "*Non-nil means except box will have a shadow."
1423 :type 'boolean
b11b1870 1424 :version "20"
984ae001
GM
1425 :group 'ebnf-except)
1426
1427
1428(defcustom ebnf-except-border-width 0.25
1429 "*Specify border width for except box."
1430 :type 'number
b11b1870 1431 :version "20"
984ae001
GM
1432 :group 'ebnf-except)
1433
1434
1435(defcustom ebnf-except-border-color "Black"
1436 "*Specify border color for except box."
1437 :type 'string
b11b1870 1438 :version "20"
984ae001
GM
1439 :group 'ebnf-except)
1440
1441
1442(defcustom ebnf-repeat-font '(7 Courier "Black" "Gray85" bold italic)
1443 "*Specify repeat font.
1444
1445See 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))))
b11b1870 1460 :version "20"
984ae001
GM
1461 :group 'ebnf-repeat)
1462
1463
1464(defcustom ebnf-repeat-shape 'bevel
1465 "*Specify repeat box shape.
1466
1467See documentation for `ebnf-non-terminal-shape'."
1468 :type '(radio :tag "Repeat Shape"
1469 (const miter) (const round) (const bevel))
b11b1870 1470 :version "20"
984ae001
GM
1471 :group 'ebnf-repeat)
1472
1473
1474(defcustom ebnf-repeat-shadow nil
1475 "*Non-nil means repeat box will have a shadow."
1476 :type 'boolean
b11b1870 1477 :version "20"
984ae001
GM
1478 :group 'ebnf-repeat)
1479
1480
1481(defcustom ebnf-repeat-border-width 0.0
1482 "*Specify border width for repeat box."
1483 :type 'number
b11b1870 1484 :version "20"
984ae001
GM
1485 :group 'ebnf-repeat)
1486
1487
1488(defcustom ebnf-repeat-border-color "Black"
1489 "*Specify border color for repeat box."
1490 :type 'string
b11b1870 1491 :version "20"
984ae001
GM
1492 :group 'ebnf-repeat)
1493
1494
1495(defcustom ebnf-terminal-font '(7 Courier "Black" "White")
1496 "*Specify terminal font.
1497
1498See 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))))
b11b1870 1513 :version "20"
984ae001
GM
1514 :group 'ebnf-terminal)
1515
1516
1517(defcustom ebnf-terminal-shape 'miter
1518 "*Specify terminal box shape.
1519
1520See documentation for `ebnf-non-terminal-shape'."
1521 :type '(radio :tag "Terminal Shape"
1522 (const miter) (const round) (const bevel))
b11b1870 1523 :version "20"
984ae001
GM
1524 :group 'ebnf-terminal)
1525
1526
1527(defcustom ebnf-terminal-shadow nil
1528 "*Non-nil means terminal box will have a shadow."
1529 :type 'boolean
b11b1870 1530 :version "20"
984ae001
GM
1531 :group 'ebnf-terminal)
1532
1533
1534(defcustom ebnf-terminal-border-width 1.0
1535 "*Specify border width for terminal box."
1536 :type 'number
b11b1870 1537 :version "20"
984ae001
GM
1538 :group 'ebnf-terminal)
1539
1540
1541(defcustom ebnf-terminal-border-color "Black"
1542 "*Specify border color for terminal box."
1543 :type 'string
b11b1870 1544 :version "20"
984ae001
GM
1545 :group 'ebnf-terminal)
1546
1547
ac4780a1
VJL
1548(defcustom ebnf-production-name-p t
1549 "*Non-nil means production name will be printed."
1550 :type 'boolean
b11b1870 1551 :version "20"
ac4780a1
VJL
1552 :group 'ebnf-production)
1553
1554
984ae001
GM
1555(defcustom ebnf-sort-production nil
1556 "*Specify how productions are sorted.
1557
1558Valid values are:
1559
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))
b11b1870 1567 :version "20"
984ae001
GM
1568 :group 'ebnf-production)
1569
1570
1571(defcustom ebnf-production-font '(10 Helvetica "Black" "White" bold)
1572 "*Specify production header font.
1573
1574It is a list with the following form:
1575
1576 (SIZE NAME FOREGROUND BACKGROUND ATTRIBUTE...)
1577
1578Where:
1579SIZE is the font size.
1580NAME is the font name symbol.
1581ATTRIBUTE 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.
1590FOREGROUND is a foreground string color name; if it's nil, the default color is
1591\"Black\".
1592BACKGROUND is a background string color name; if it's nil, the default color is
1593\"White\".
1594
1595See `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))))
b11b1870 1610 :version "20"
984ae001
GM
1611 :group 'ebnf-production)
1612
1613
1614(defcustom ebnf-non-terminal-font '(7 Helvetica "Black" "White")
1615 "*Specify non-terminal font.
1616
1617See 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))))
b11b1870 1632 :version "20"
984ae001
GM
1633 :group 'ebnf-non-terminal)
1634
1635
1636(defcustom ebnf-non-terminal-shape 'round
1637 "*Specify non-terminal box shape.
1638
1639Valid values are:
1640
1641 `miter' +-------+
1642 | |
1643 +-------+
1644
1645 `round' -------
1646 ( )
1647 -------
1648
1649 `bevel' /-------\\
1650 | |
1651 \\-------/
1652
1653Any other value is treated as `miter'."
1654 :type '(radio :tag "Non-Terminal Shape"
1655 (const miter) (const round) (const bevel))
b11b1870 1656 :version "20"
984ae001
GM
1657 :group 'ebnf-non-terminal)
1658
1659
1660(defcustom ebnf-non-terminal-shadow nil
1661 "*Non-nil means non-terminal box will have a shadow."
1662 :type 'boolean
b11b1870 1663 :version "20"
984ae001
GM
1664 :group 'ebnf-non-terminal)
1665
1666
1667(defcustom ebnf-non-terminal-border-width 1.0
1668 "*Specify border width for non-terminal box."
1669 :type 'number
b11b1870 1670 :version "20"
984ae001
GM
1671 :group 'ebnf-non-terminal)
1672
1673
1674(defcustom ebnf-non-terminal-border-color "Black"
1675 "*Specify border color for non-terminal box."
1676 :type 'string
b11b1870 1677 :version "20"
984ae001
GM
1678 :group 'ebnf-non-terminal)
1679
1680
1681(defcustom ebnf-arrow-shape 'hollow
1682 "*Specify the arrow shape.
1683
1684Valid values are:
1685
1686 `none' ======
1687
1688 `semi-up' * `transparent' *
1689 * |*
1690 =====* | *
1691 ==+==*
1692 | *
1693 |*
1694 *
1695
1696 `semi-down' =====* `hollow' *
1697 * |*
1698 * | *
1699 ==+ *
1700 | *
1701 |*
1702 *
1703
1704 `simple' * `full' *
1705 * |*
1706 =====* |X*
1707 * ==+XX*
1708 * |X*
1709 |*
1710 *
1711
ac4780a1
VJL
1712 `semi-up-hollow' `semi-up-full'
1713 * *
1714 |* |*
1715 | * |X*
1716 ==+==* ==+==*
1717
1718 `semi-down-hollow' `semi-down-full'
1719 ==+==* ==+==*
1720 | * |X*
1721 |* |*
1722 * *
1723
984ae001
GM
1724 `user' See also documentation for variable `ebnf-user-arrow'.
1725
1726Any other value is treated as `none'."
1727 :type '(radio :tag "Arrow Shape"
ac4780a1
VJL
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))
b11b1870 1734 :version "20"
984ae001
GM
1735 :group 'ebnf-shape)
1736
1737
1738(defcustom ebnf-chart-shape 'round
1739 "*Specify chart flow shape.
1740
1741See documentation for `ebnf-non-terminal-shape'."
1742 :type '(radio :tag "Chart Flow Shape"
1743 (const miter) (const round) (const bevel))
b11b1870 1744 :version "20"
984ae001
GM
1745 :group 'ebnf-shape)
1746
1747
1748(defcustom ebnf-user-arrow nil
bf061ba6 1749 "*Specify a sexp for user arrow shape (a PostScript code).
984ae001 1750
bf061ba6
GM
1751When evaluated, the sexp should return nil or a string containing PostScript
1752code. PostScript code should draw a right arrow.
984ae001
GM
1753
1754The anatomy of a right arrow is:
1755
1756 ...... Initial position
1757 :
1758 : *.................
1759 : | * } }
1760 : | * } hT4 }
1761 v | * } }
1762 ======+======*... } hT2
1763 : | *: } }
1764 : | * : } hT4 }
1765 : | * : } }
1766 : *.................
1767 : : :
1768 : : :..........
1769 : : } hT2 }
1770 : :.......... } hT
1771 : } hT2 }
1772 :.......................
1773
b685181e
GM
1774Where `hT', `hT2' and `hT4' are predefined PostScript variable names that can
1775be used to generate your own arrow. As these variables are used along
1776PostScript execution, *DON'T* modify the values of them. Instead, copy the
1777values, if you need to modify them.
984ae001
GM
1778
1779The relation between these variables is: hT = 2 * hT2 = 4 * hT4.
1780
1781The variable `ebnf-user-arrow' is only used when `ebnf-arrow-shape' is set to
bf061ba6
GM
1782symbol `user'."
1783 :type '(sexp :tag "User Arrow Shape")
b11b1870 1784 :version "20"
984ae001
GM
1785 :group 'ebnf-shape)
1786
1787
1788(defcustom ebnf-syntax 'ebnf
1789 "*Specify syntax to be recognized.
1790
1791Valid values are:
1792
887448e1
GM
1793 `ebnf' ebnf2ps recognizes the syntax described in ebnf2ps
1794 documentation.
984ae001
GM
1795 The following variables *ONLY* have effect with this
1796 setting:
1797 `ebnf-terminal-regexp', `ebnf-case-fold-search',
1798 `ebnf-lex-comment-char' and `ebnf-lex-eop-char'.
1799
ac4780a1 1800 `abnf' ebnf2ps recognizes the syntax described in the URL:
97818b07 1801 `http://www.ietf.org/rfc/rfc2234.txt'
ac4780a1
VJL
1802 (\"Augmented BNF for Syntax Specifications: ABNF\").
1803
984ae001
GM
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
1808 setting:
1809 `ebnf-iso-alternative-p' and `ebnf-iso-normalize-p'.
1810
1811 `yacc' ebnf2ps recognizes the Yacc/Bison syntax.
1812 The following variable *ONLY* has effect with this
1813 setting:
1814 `ebnf-yac-ignore-error-recovery'.
1815
6ca94f87
VJL
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)\")
1819
6411a60a
VJL
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)\")
1823
984ae001
GM
1824Any other value is treated as `ebnf'."
1825 :type '(radio :tag "Syntax"
6ca94f87 1826 (const ebnf) (const abnf) (const iso-ebnf)
6411a60a 1827 (const yacc) (const ebnfx) (const dtd))
b11b1870 1828 :version "20"
ab3256ed 1829 :group 'ebnf-syntactic)
984ae001
GM
1830
1831
1832(defcustom ebnf-lex-comment-char ?\;
1833 "*Specify the line comment character.
1834
1835It's used only when `ebnf-syntax' is `ebnf'."
1836 :type 'character
b11b1870 1837 :version "20"
ab3256ed 1838 :group 'ebnf-syntactic)
984ae001
GM
1839
1840
1841(defcustom ebnf-lex-eop-char ?.
1842 "*Specify the end of production character.
1843
1844It's used only when `ebnf-syntax' is `ebnf'."
1845 :type 'character
b11b1870 1846 :version "20"
ab3256ed 1847 :group 'ebnf-syntactic)
984ae001
GM
1848
1849
1850(defcustom ebnf-terminal-regexp nil
1851 "*Specify how it's a terminal name.
1852
1853If it's nil, the terminal name must be enclosed by `\"'.
1854If it's a string, it should be a regexp that it'll be used to determine a
1855terminal name; terminal name may also be enclosed by `\"'.
1856
1857It's used only when `ebnf-syntax' is `ebnf'."
1858 :type '(radio :tag "Terminal Name"
1859 (const nil) regexp)
b11b1870 1860 :version "20"
ab3256ed 1861 :group 'ebnf-syntactic)
984ae001
GM
1862
1863
1864(defcustom ebnf-case-fold-search nil
1865 "*Non-nil means ignore case on matching.
1866
1867It's only used when `ebnf-terminal-regexp' is non-nil and when `ebnf-syntax' is
1868`ebnf'."
1869 :type 'boolean
b11b1870 1870 :version "20"
ab3256ed 1871 :group 'ebnf-syntactic)
984ae001
GM
1872
1873
1874(defcustom ebnf-iso-alternative-p nil
1875 "*Non-nil means use alternative ISO EBNF.
1876
1877It's only used when `ebnf-syntax' is `iso-ebnf'.
1878
1879This variable affects the following symbol set:
1880
1881 STANDARD ALTERNATIVE
1882 | ==> / or !
1883 [ ==> (/
1884 ] ==> /)
1885 { ==> (:
1886 } ==> :)
1887 ; ==> ."
1888 :type 'boolean
b11b1870 1889 :version "20"
ab3256ed 1890 :group 'ebnf-syntactic)
984ae001
GM
1891
1892
1893(defcustom ebnf-iso-normalize-p nil
1894 "*Non-nil means normalize ISO EBNF syntax names.
1895
1896Normalize a name means that several contiguous spaces inside name become a
1897single space, so \"A B C\" is normalized to \"A B C\".
1898
1899It's only used when `ebnf-syntax' is `iso-ebnf'."
1900 :type 'boolean
b11b1870 1901 :version "20"
ab3256ed 1902 :group 'ebnf-syntactic)
984ae001
GM
1903
1904
ac4780a1
VJL
1905(defcustom ebnf-file-suffix-regexp "\.[Bb][Nn][Ff]$"
1906 "*Specify file name suffix that contains EBNF.
1907
1908See `ebnf-eps-directory' command."
1909 :type 'regexp
b11b1870 1910 :version "20"
ac4780a1
VJL
1911 :group 'ebnf2ps)
1912
1913
984ae001
GM
1914(defcustom ebnf-eps-prefix "ebnf--"
1915 "*Specify EPS prefix file name.
1916
1917See `ebnf-eps-buffer' and `ebnf-eps-region' commands."
1918 :type 'string
b11b1870 1919 :version "20"
984ae001
GM
1920 :group 'ebnf2ps)
1921
1922
3ced5caa
VJL
1923(defcustom ebnf-eps-header-font '(11 Helvetica "Black" "White" bold)
1924 "*Specify EPS header font.
1925
1926See documentation for `ebnf-production-font'.
1927
1928See `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))))
1943 :version "22"
1944 :group 'ebnf2ps)
1945
1946
1947(defcustom ebnf-eps-header nil
1948 "*Specify EPS header.
1949
1950The value should be a string, a symbol or nil.
1951
1952String is inserted unchanged.
1953
1954For symbol bounded to a function, the function is called and should return a
1955string. For symbol bounded to a value, the value should be a string.
1956
1957If symbol is unbounded, it is silently ignored.
1958
1959Empty string or nil mean that no header will be generated.
1960
1961Note that when the header action comment (;H in EBNF syntax) is specified, the
1962string in the header action comment is processed and, if it returns a non-empty
1963string, it's used to generate the header. The header action comment accepts
1964the following formats:
1965
1966 %% prints a % character.
1967
1968 %H prints the `ebnf-eps-header' value.
1969
1970 %F prints the `ebnf-eps-footer' (which see) value.
1971
1972Any other format is ignored, that is, if, for example, it's used %s then %s
1973characters are stripped out from the header. If header action comment is an
1974empty 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"
1977 :tag "EPS Header"
1978 string symbol (const :tag "No Header" nil )))
1979 :version "22"
1980 :group 'ebnf2ps)
1981
1982
1983(defcustom ebnf-eps-footer-font '(7 Helvetica "Black" "White" bold)
1984 "*Specify EPS footer font.
1985
1986See documentation for `ebnf-production-font'.
1987
1988See `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))))
2003 :version "22"
2004 :group 'ebnf2ps)
2005
2006
2007(defcustom ebnf-eps-footer nil
2008 "*Specify EPS footer.
2009
2010The value should be a string, a symbol or nil.
2011
2012String is inserted unchanged.
2013
2014For symbol bounded to a function, the function is called and should return a
2015string. For symbol bounded to a value, the value should be a string.
2016
2017If symbol is unbounded, it is silently ignored.
2018
2019Empty string or nil mean that no footer will be generated.
2020
2021Note that when the footer action comment (;F in EBNF syntax) is specified, the
2022string in the footer action comment is processed and, if it returns a non-empty
2023string, it's used to generate the footer. The footer action comment accepts
2024the following formats:
2025
2026 %% prints a % character.
2027
2028 %H prints the `ebnf-eps-header' (which see) value.
2029
2030 %F prints the `ebnf-eps-footer' value.
2031
2032Any other format is ignored, that is, if, for example, it's used %s then %s
2033characters are stripped out from the footer. If footer action comment is an
2034empty 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"
2037 :tag "EPS Footer"
2038 string symbol (const :tag "No Footer" nil )))
2039 :version "22"
2040 :group 'ebnf2ps)
2041
2042
984ae001
GM
2043(defcustom ebnf-entry-percentage 0.5 ; middle
2044 "*Specify entry height on alternatives.
2045
2046It must be a float between 0.0 (top) and 1.0 (bottom)."
2047 :type 'number
b11b1870 2048 :version "20"
984ae001
GM
2049 :group 'ebnf2ps)
2050
2051
2052(defcustom ebnf-default-width 0.6
2053 "*Specify additional border width over default terminal, non-terminal or
2054special."
2055 :type 'number
b11b1870 2056 :version "20"
984ae001
GM
2057 :group 'ebnf2ps)
2058
2059
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."
2064 :type 'boolean
b11b1870 2065 :version "20"
984ae001
GM
2066 :group 'ebnf2ps)
2067
2068
2069(defcustom ebnf-line-width 1.0
2070 "*Specify flow line width."
2071 :type 'number
b11b1870 2072 :version "20"
984ae001
GM
2073 :group 'ebnf2ps)
2074
2075
2076(defcustom ebnf-line-color "Black"
2077 "*Specify flow line color."
2078 :type 'string
b11b1870 2079 :version "20"
984ae001
GM
2080 :group 'ebnf2ps)
2081
2082
ed0aa46c
VJL
2083(defcustom ebnf-arrow-extra-width
2084 (if (eq ebnf-arrow-shape 'none)
2085 0.0
2086 (* (sqrt 5.0) 0.65 ebnf-line-width))
2087 "*Specify extra width for arrow shape drawing.
2088
2089The extra width is used to avoid that the arrowhead and the terminal border
2090overlap. It depens on `ebnf-arrow-shape' and `ebnf-line-width'."
2091 :type 'number
2092 :version "22"
2093 :group 'ebnf-shape)
2094
2095
2096(defcustom ebnf-arrow-scale 1.0
2097 "*Specify the arrow scale.
2098
2099Values lower than 1.0, shrink the arrow.
2100Values greater than 1.0, expand the arrow."
2101 :type 'number
2102 :version "22"
2103 :group 'ebnf-shape)
2104
2105
984ae001
GM
2106(defcustom ebnf-debug-ps nil
2107 "*Non-nil means to generate PostScript debug procedures.
2108
2109It is intended to help PostScript programmers in debugging."
2110 :type 'boolean
b11b1870 2111 :version "20"
984ae001
GM
2112 :group 'ebnf2ps)
2113
2114
2115(defcustom ebnf-use-float-format t
2116 "*Non-nil means use `%f' float format.
2117
2118The advantage of using float format is that ebnf2ps generates a little short
2119PostScript file.
2120
2121If it occurs the error message:
2122
2123 Invalid format operation %f
2124
2125when executing ebnf2ps, set `ebnf-use-float-format' to nil."
2126 :type 'boolean
b11b1870 2127 :version "20"
984ae001
GM
2128 :group 'ebnf2ps)
2129
2130
ac4780a1 2131(defcustom ebnf-stop-on-error nil
6f19f70a 2132 "*Non-nil means signal error and stop. Otherwise, signal error and continue."
ac4780a1 2133 :type 'boolean
b11b1870 2134 :version "20"
ac4780a1
VJL
2135 :group 'ebnf2ps)
2136
2137
984ae001
GM
2138(defcustom ebnf-yac-ignore-error-recovery nil
2139 "*Non-nil means ignore error recovery.
2140
2141It's only used when `ebnf-syntax' is `yacc'."
2142 :type 'boolean
b11b1870 2143 :version "20"
ab3256ed 2144 :group 'ebnf-syntactic)
984ae001
GM
2145
2146
2147(defcustom ebnf-ignore-empty-rule nil
2148 "*Non-nil means ignore empty rules.
2149
2150It's interesting to set this variable if your Yacc/Bison grammar has a lot of
2151middle action rule."
2152 :type 'boolean
b11b1870 2153 :version "20"
984ae001
GM
2154 :group 'ebnf-optimization)
2155
2156
2157(defcustom ebnf-optimize nil
ab3256ed 2158 "*Non-nil means optimize syntactic chart of rules.
984ae001
GM
2159
2160The following optimizations are done:
2161
2162 left recursion:
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 }*.
2168
2169 optional:
2170 6. A = B | . ==> A = [B].
2171 7. A = | B . ==> A = [B].
2172
ad96a7ef 2173 factorization:
984ae001
GM
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.
2177
2178The above optimizations are specially useful when `ebnf-syntax' is `yacc'."
2179 :type 'boolean
b11b1870 2180 :version "20"
984ae001
GM
2181 :group 'ebnf-optimization)
2182
3ced5caa
VJL
2183
2184(defcustom ebnf-log nil
2185 "*Non-nil means generate log messages.
2186
2187The log messages are generated into the buffer *Ebnf2ps Log*.
2188These messages are intended to help debugging ebnf2ps."
2189 :type 'boolean
2190 :version "22"
2191 :group 'ebnf2ps)
2192
984ae001 2193\f
6411a60a
VJL
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.
2198
2199(autoload 'ebnf-eliminate-empty-rules "ebnf-otz"
2200 "Eliminate empty rules.")
2201
2202(autoload 'ebnf-optimize "ebnf-otz"
2203 "Syntactic chart optimizer.")
2204
2205(autoload 'ebnf-otz-initialize "ebnf-otz"
2206 "Initialize optimizer.")
2207
2208\f
984ae001
GM
2209;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2210;; Customization
2211
2212
2213;;;###autoload
2214(defun ebnf-customize ()
2215 "Customization for ebnf group."
2216 (interactive)
2217 (customize-group 'ebnf2ps))
2218
2219\f
2220;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2221;; User commands
2222
2223
ac4780a1
VJL
2224;;;###autoload
2225(defun ebnf-print-directory (&optional directory)
2226 "Generate and print a PostScript syntactic chart image of DIRECTORY.
2227
2228If DIRECTORY is nil, it's used `default-directory'.
2229
2230The files in DIRECTORY that matches `ebnf-file-suffix-regexp' (which see) are
2231processed.
2232
2233See also `ebnf-print-buffer'."
2234 (interactive
2235 (list (read-file-name "Directory containing EBNF files (print): "
2236 nil default-directory)))
3ced5caa 2237 (ebnf-log-header "(ebnf-print-directory %S)" directory)
ac4780a1
VJL
2238 (ebnf-directory 'ebnf-print-buffer directory))
2239
2240
2241;;;###autoload
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.
2244
2245If optional arg DO-NOT-KILL-BUFFER-WHEN-DONE is non-nil, the buffer isn't
2246killed after process termination.
2247
2248See also `ebnf-print-buffer'."
2249 (interactive "fEBNF file to generate PostScript and print from: ")
3ced5caa 2250 (ebnf-log-header "(ebnf-print-file %S %S)" file do-not-kill-buffer-when-done)
ac4780a1
VJL
2251 (ebnf-file 'ebnf-print-buffer file do-not-kill-buffer-when-done))
2252
2253
984ae001
GM
2254;;;###autoload
2255(defun ebnf-print-buffer (&optional filename)
ab3256ed 2256 "Generate and print a PostScript syntactic chart image of the buffer.
984ae001
GM
2257
2258When called with a numeric prefix argument (C-u), prompts the user for
2259the name of a file to save the PostScript image in, instead of sending
2260it to the printer.
2261
2262More specifically, the FILENAME argument is treated as follows: if it
2263is nil, send the image to the printer. If FILENAME is a string, save
2264the PostScript image in a file with that name. If FILENAME is a
2265number, prompt the user for the name of the file to save in."
2266 (interactive (list (ps-print-preprint current-prefix-arg)))
3ced5caa 2267 (ebnf-log-header "(ebnf-print-buffer %S)" filename)
984ae001
GM
2268 (ebnf-print-region (point-min) (point-max) filename))
2269
2270
2271;;;###autoload
2272(defun ebnf-print-region (from to &optional filename)
ab3256ed 2273 "Generate and print a PostScript syntactic chart image of the region.
984ae001
GM
2274Like `ebnf-print-buffer', but prints just the current region."
2275 (interactive (list (point) (mark) (ps-print-preprint current-prefix-arg)))
3ced5caa 2276 (ebnf-log-header "(ebnf-print-region %S %S %S)" from to filename)
984ae001
GM
2277 (run-hooks 'ebnf-hook)
2278 (or (ebnf-spool-region from to)
2279 (ps-do-despool filename)))
2280
2281
ac4780a1
VJL
2282;;;###autoload
2283(defun ebnf-spool-directory (&optional directory)
2284 "Generate and spool a PostScript syntactic chart image of DIRECTORY.
2285
2286If DIRECTORY is nil, it's used `default-directory'.
2287
2288The files in DIRECTORY that matches `ebnf-file-suffix-regexp' (which see) are
2289processed.
2290
2291See also `ebnf-spool-buffer'."
2292 (interactive
2293 (list (read-file-name "Directory containing EBNF files (spool): "
2294 nil default-directory)))
3ced5caa 2295 (ebnf-log-header "(ebnf-spool-directory %S)" directory)
ac4780a1
VJL
2296 (ebnf-directory 'ebnf-spool-buffer directory))
2297
2298
2299;;;###autoload
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.
2302
2303If optional arg DO-NOT-KILL-BUFFER-WHEN-DONE is non-nil, the buffer isn't
2304killed after process termination.
2305
2306See also `ebnf-spool-buffer'."
2307 (interactive "fEBNF file to generate PostScript and spool from: ")
3ced5caa 2308 (ebnf-log-header "(ebnf-spool-file %S %S)" file do-not-kill-buffer-when-done)
ac4780a1
VJL
2309 (ebnf-file 'ebnf-spool-buffer file do-not-kill-buffer-when-done))
2310
2311
984ae001
GM
2312;;;###autoload
2313(defun ebnf-spool-buffer ()
ab3256ed 2314 "Generate and spool a PostScript syntactic chart image of the buffer.
984ae001
GM
2315Like `ebnf-print-buffer' except that the PostScript image is saved in a
2316local buffer to be sent to the printer later.
2317
2318Use the command `ebnf-despool' to send the spooled images to the printer."
2319 (interactive)
3ced5caa 2320 (ebnf-log-header "(ebnf-spool-buffer)")
984ae001
GM
2321 (ebnf-spool-region (point-min) (point-max)))
2322
2323
2324;;;###autoload
2325(defun ebnf-spool-region (from to)
ab3256ed 2326 "Generate a PostScript syntactic chart image of the region and spool locally.
984ae001
GM
2327Like `ebnf-spool-buffer', but spools just the current region.
2328
2329Use the command `ebnf-despool' to send the spooled images to the printer."
2330 (interactive "r")
3ced5caa 2331 (ebnf-log-header "(ebnf-spool-region %S)" from to)
984ae001
GM
2332 (ebnf-generate-region from to 'ebnf-generate))
2333
2334
ac4780a1
VJL
2335;;;###autoload
2336(defun ebnf-eps-directory (&optional directory)
2337 "Generate EPS files from EBNF files in DIRECTORY.
2338
2339If DIRECTORY is nil, it's used `default-directory'.
2340
2341The files in DIRECTORY that matches `ebnf-file-suffix-regexp' (which see) are
2342processed.
2343
2344See also `ebnf-eps-buffer'."
2345 (interactive
2346 (list (read-file-name "Directory containing EBNF files (EPS): "
2347 nil default-directory)))
3ced5caa 2348 (ebnf-log-header "(ebnf-eps-directory %S)" directory)
ac4780a1
VJL
2349 (ebnf-directory 'ebnf-eps-buffer directory))
2350
2351
2352;;;###autoload
2353(defun ebnf-eps-file (file &optional do-not-kill-buffer-when-done)
2354 "Generate an EPS file from EBNF file FILE.
2355
2356If optional arg DO-NOT-KILL-BUFFER-WHEN-DONE is non-nil, the buffer isn't
2357killed after EPS generation.
2358
2359See also `ebnf-eps-buffer'."
2360 (interactive "fEBNF file to generate EPS file from: ")
3ced5caa 2361 (ebnf-log-header "(ebnf-eps-file %S %S)" file do-not-kill-buffer-when-done)
ac4780a1
VJL
2362 (ebnf-file 'ebnf-eps-buffer file do-not-kill-buffer-when-done))
2363
2364
984ae001
GM
2365;;;###autoload
2366(defun ebnf-eps-buffer ()
4303661c 2367 "Generate a PostScript syntactic chart image of the buffer in an EPS file.
984ae001 2368
815cbda2 2369Generate an EPS file for each production in the buffer.
984ae001
GM
2370The EPS file name has the following form:
2371
2372 <PREFIX><PRODUCTION>.eps
2373
2374<PREFIX> is given by variable `ebnf-eps-prefix'.
2375 The default value is \"ebnf--\".
2376
2377<PRODUCTION> is the production name.
815cbda2
EZ
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\".
984ae001 2382
815cbda2 2383WARNING: This function does *NOT* ask any confirmation to override existing
3ced5caa 2384 files."
984ae001 2385 (interactive)
3ced5caa 2386 (ebnf-log-header "(ebnf-eps-buffer)")
984ae001
GM
2387 (ebnf-eps-region (point-min) (point-max)))
2388
2389
2390;;;###autoload
2391(defun ebnf-eps-region (from to)
4303661c 2392 "Generate a PostScript syntactic chart image of the region in an EPS file.
984ae001 2393
815cbda2 2394Generate an EPS file for each production in the region.
984ae001
GM
2395The EPS file name has the following form:
2396
2397 <PREFIX><PRODUCTION>.eps
2398
2399<PREFIX> is given by variable `ebnf-eps-prefix'.
2400 The default value is \"ebnf--\".
2401
2402<PRODUCTION> is the production name.
815cbda2
EZ
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\".
984ae001 2407
815cbda2 2408WARNING: This function does *NOT* ask any confirmation to override existing
3ced5caa 2409 files."
984ae001 2410 (interactive "r")
3ced5caa 2411 (ebnf-log-header "(ebnf-eps-region %S %S)" from to)
984ae001
GM
2412 (let ((ebnf-eps-executing t))
2413 (ebnf-generate-region from to 'ebnf-generate-eps)))
2414
2415
2416;;;###autoload
2417(defalias 'ebnf-despool 'ps-despool)
2418
2419
cd0f9f85
VJL
2420;;;###autoload
2421(defun ebnf-syntax-directory (&optional directory)
815cbda2 2422 "Do a syntactic analysis of the files in DIRECTORY.
cd0f9f85 2423
815cbda2 2424If DIRECTORY is nil, use `default-directory'.
cd0f9f85 2425
815cbda2
EZ
2426Only the files in DIRECTORY that match `ebnf-file-suffix-regexp' (which see)
2427are processed.
cd0f9f85
VJL
2428
2429See also `ebnf-syntax-buffer'."
2430 (interactive
2431 (list (read-file-name "Directory containing EBNF files (syntax): "
2432 nil default-directory)))
3ced5caa 2433 (ebnf-log-header "(ebnf-syntax-directory %S)" directory)
cd0f9f85
VJL
2434 (ebnf-directory 'ebnf-syntax-buffer directory))
2435
2436
2437;;;###autoload
2438(defun ebnf-syntax-file (file &optional do-not-kill-buffer-when-done)
815cbda2 2439 "Do a syntactic analysis of the named FILE.
cd0f9f85
VJL
2440
2441If optional arg DO-NOT-KILL-BUFFER-WHEN-DONE is non-nil, the buffer isn't
4e7d3274 2442killed after syntax checking.
cd0f9f85
VJL
2443
2444See also `ebnf-syntax-buffer'."
2445 (interactive "fEBNF file to check syntax: ")
3ced5caa 2446 (ebnf-log-header "(ebnf-syntax-file %S %S)" file do-not-kill-buffer-when-done)
cd0f9f85
VJL
2447 (ebnf-file 'ebnf-syntax-buffer file do-not-kill-buffer-when-done))
2448
2449
984ae001
GM
2450;;;###autoload
2451(defun ebnf-syntax-buffer ()
815cbda2 2452 "Do a syntactic analysis of the current buffer."
984ae001 2453 (interactive)
3ced5caa 2454 (ebnf-log-header "(ebnf-syntax-buffer)")
984ae001
GM
2455 (ebnf-syntax-region (point-min) (point-max)))
2456
2457
2458;;;###autoload
2459(defun ebnf-syntax-region (from to)
3ced5caa 2460 "Do a syntactic analysis of a region."
984ae001 2461 (interactive "r")
3ced5caa 2462 (ebnf-log-header "(ebnf-syntax-region %S %S)" from to)
984ae001
GM
2463 (ebnf-generate-region from to nil))
2464
2465\f
2466;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2467;; Utilities
2468
2469
2470;;;###autoload
2471(defun ebnf-setup ()
2472 "Return the current ebnf2ps setup."
2473 (format
2474 "
6a5275dc
GM
2475;;; ebnf2ps.el version %s
2476
3ced5caa
VJL
2477;;; Emacs version %S
2478
ac4780a1
VJL
2479\(setq ebnf-special-show-delimiter %S
2480 ebnf-special-font %s
984ae001
GM
2481 ebnf-special-shape %s
2482 ebnf-special-shadow %S
2483 ebnf-special-border-width %S
2484 ebnf-special-border-color %S
2485 ebnf-except-font %s
2486 ebnf-except-shape %s
2487 ebnf-except-shadow %S
2488 ebnf-except-border-width %S
2489 ebnf-except-border-color %S
2490 ebnf-repeat-font %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
ac4780a1 2507 ebnf-production-name-p %S
984ae001
GM
2508 ebnf-sort-production %s
2509 ebnf-production-font %s
2510 ebnf-arrow-shape %s
2511 ebnf-chart-shape %s
2512 ebnf-user-arrow %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
2520 ebnf-syntax %s
2521 ebnf-iso-alternative-p %S
2522 ebnf-iso-normalize-p %S
ac4780a1 2523 ebnf-file-suffix-regexp %S
984ae001 2524 ebnf-eps-prefix %S
3ced5caa
VJL
2525 ebnf-eps-header-font %s
2526 ebnf-eps-header %s
2527 ebnf-eps-footer-font %s
2528 ebnf-eps-footer %s
984ae001
GM
2529 ebnf-entry-percentage %S
2530 ebnf-color-p %S
2531 ebnf-line-width %S
2532 ebnf-line-color %S
3ced5caa
VJL
2533 ebnf-arrow-extra-width %S
2534 ebnf-arrow-scale %S
984ae001
GM
2535 ebnf-debug-ps %S
2536 ebnf-use-float-format %S
ac4780a1 2537 ebnf-stop-on-error %S
984ae001
GM
2538 ebnf-yac-ignore-error-recovery %S
2539 ebnf-ignore-empty-rule %S
3ced5caa
VJL
2540 ebnf-optimize %S
2541 ebnf-log %S)
6a5275dc
GM
2542
2543;;; ebnf2ps.el - end of settings
984ae001 2544"
6a5275dc 2545 ebnf-version
3ced5caa 2546 emacs-version
ac4780a1 2547 ebnf-special-show-delimiter
984ae001
GM
2548 (ps-print-quote ebnf-special-font)
2549 (ps-print-quote ebnf-special-shape)
2550 ebnf-special-shadow
2551 ebnf-special-border-width
2552 ebnf-special-border-color
2553 (ps-print-quote ebnf-except-font)
2554 (ps-print-quote ebnf-except-shape)
2555 ebnf-except-shadow
2556 ebnf-except-border-width
2557 ebnf-except-border-color
2558 (ps-print-quote ebnf-repeat-font)
2559 (ps-print-quote ebnf-repeat-shape)
2560 ebnf-repeat-shadow
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
ac4780a1 2575 ebnf-production-name-p
984ae001
GM
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
2587 ebnf-lex-eop-char
2588 (ps-print-quote ebnf-syntax)
2589 ebnf-iso-alternative-p
2590 ebnf-iso-normalize-p
ac4780a1 2591 ebnf-file-suffix-regexp
984ae001 2592 ebnf-eps-prefix
3ced5caa
VJL
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)
984ae001
GM
2597 ebnf-entry-percentage
2598 ebnf-color-p
2599 ebnf-line-width
2600 ebnf-line-color
3ced5caa
VJL
2601 ebnf-arrow-extra-width
2602 ebnf-arrow-scale
984ae001
GM
2603 ebnf-debug-ps
2604 ebnf-use-float-format
ac4780a1 2605 ebnf-stop-on-error
984ae001
GM
2606 ebnf-yac-ignore-error-recovery
2607 ebnf-ignore-empty-rule
3ced5caa
VJL
2608 ebnf-optimize
2609 ebnf-log))
984ae001
GM
2610
2611\f
2612;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2613;; Style variables
2614
2615
2616(defvar ebnf-stack-style nil
2617 "Used in functions `ebnf-reset-style', `ebnf-push-style' and
2618`ebnf-pop-style'.")
2619
2620
2621(defvar ebnf-current-style 'default
2622 "Used in functions `ebnf-apply-style' and `ebnf-push-style'.")
2623
2624
2625(defconst ebnf-style-custom-list
ac4780a1
VJL
2626 '(ebnf-special-show-delimiter
2627 ebnf-special-font
984ae001
GM
2628 ebnf-special-shape
2629 ebnf-special-shadow
2630 ebnf-special-border-width
2631 ebnf-special-border-color
2632 ebnf-except-font
2633 ebnf-except-shape
2634 ebnf-except-shadow
2635 ebnf-except-border-width
2636 ebnf-except-border-color
2637 ebnf-repeat-font
2638 ebnf-repeat-shape
2639 ebnf-repeat-shadow
2640 ebnf-repeat-border-width
2641 ebnf-repeat-border-color
2642 ebnf-terminal-regexp
2643 ebnf-case-fold-search
2644 ebnf-terminal-font
2645 ebnf-terminal-shape
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
ac4780a1 2654 ebnf-production-name-p
984ae001
GM
2655 ebnf-sort-production
2656 ebnf-production-font
2657 ebnf-arrow-shape
2658 ebnf-chart-shape
2659 ebnf-user-arrow
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
2666 ebnf-lex-eop-char
2667 ebnf-syntax
2668 ebnf-iso-alternative-p
2669 ebnf-iso-normalize-p
ac4780a1 2670 ebnf-file-suffix-regexp
984ae001 2671 ebnf-eps-prefix
3ced5caa
VJL
2672 ebnf-eps-header-font
2673 ebnf-eps-header
2674 ebnf-eps-footer-font
2675 ebnf-eps-footer
984ae001
GM
2676 ebnf-entry-percentage
2677 ebnf-color-p
2678 ebnf-line-width
2679 ebnf-line-color
2680 ebnf-debug-ps
2681 ebnf-use-float-format
ac4780a1 2682 ebnf-stop-on-error
984ae001
GM
2683 ebnf-yac-ignore-error-recovery
2684 ebnf-ignore-empty-rule
2685 ebnf-optimize)
2686 "List of valid symbol custom variable.")
2687
2688
2689(defvar ebnf-style-database
2690 '(;; EBNF default
2691 (default
2692 nil
ac4780a1 2693 (ebnf-special-show-delimiter . t)
984ae001
GM
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")
ac4780a1 2721 (ebnf-production-name-p . t)
984ae001
GM
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)
ac4780a1 2737 (ebnf-file-suffix-regexp . "\.[Bb][Nn][Ff]$")
984ae001 2738 (ebnf-eps-prefix . "ebnf--")
3ced5caa
VJL
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)
984ae001
GM
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)
ac4780a1 2750 (ebnf-stop-on-error . nil)
984ae001
GM
2751 (ebnf-yac-ignore-error-recovery . nil)
2752 (ebnf-ignore-empty-rule . nil)
2753 (ebnf-optimize . nil))
2754 ;; Happy EBNF default
2755 (happy
2756 default
2757 (ebnf-justify-sequence . 'left)
2758 (ebnf-lex-comment-char . ?\#)
2759 (ebnf-lex-eop-char . ?\;))
ac4780a1
VJL
2760 ;; ABNF default
2761 (abnf
2762 default
2763 (ebnf-syntax . 'abnf))
984ae001
GM
2764 ;; ISO EBNF default
2765 (iso-ebnf
2766 default
2767 (ebnf-syntax . 'iso-ebnf))
2768 ;; Yacc/Bison default
2769 (yacc
2770 default
2771 (ebnf-syntax . 'yacc))
6ca94f87
VJL
2772 ;; ebnfx default
2773 (ebnfx
2774 default
2775 (ebnf-syntax . 'ebnfx))
6411a60a
VJL
2776 ;; dtd default
2777 (dtd
2778 default
2779 (ebnf-syntax . 'dtd))
984ae001
GM
2780 )
2781 "Style database.
2782
2783Each element has the following form:
2784
ac4780a1 2785 (NAME INHERITS (VAR . VALUE)...)
984ae001 2786
ac4780a1 2787Where:
984ae001 2788
ac4780a1
VJL
2789NAME is a symbol name style.
2790
2791INHERITS is a symbol name style from which the current style inherits
815cbda2 2792 the context. If INHERITS is nil, then there is no inheritance.
ac4780a1 2793
815cbda2
EZ
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
ac4780a1 2797 when you wish to modify some aspects of an existing style, but
815cbda2 2798 at the same time wish to keep it unmodified.
ac4780a1
VJL
2799
2800VAR is a valid ebnf2ps symbol custom variable.
815cbda2 2801 See `ebnf-style-custom-list' for valid symbol variables.
ac4780a1 2802
815cbda2
EZ
2803VALUE is a sexp which will be evaluated to set the value of VAR.
2804 Don't forget to quote symbols and constant lists.
ac4780a1
VJL
2805 See `default' style for an example.
2806
815cbda2 2807Don't use this variable directly. Use functions `ebnf-insert-style',
ac4780a1 2808`ebnf-delete-style' and `ebnf-merge-style'.")
984ae001
GM
2809
2810\f
2811;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2812;; Style commands
2813
2814
3ced5caa
VJL
2815;;;###autoload
2816(defun ebnf-find-style (name)
2817 "Return style definition if NAME is already defined; otherwise, return nil.
2818
2819See `ebnf-style-database' documentation."
2820 (interactive "SStyle name: ")
2821 (assoc name ebnf-style-database))
2822
2823
984ae001
GM
2824;;;###autoload
2825(defun ebnf-insert-style (name inherits &rest values)
ac4780a1
VJL
2826 "Insert a new style NAME with inheritance INHERITS and values VALUES.
2827
2828See `ebnf-style-database' documentation."
2829 (interactive "SStyle name: \nSStyle inherits from: \nXStyle values: ")
984ae001
GM
2830 (and (assoc name ebnf-style-database)
2831 (error "Style name already exists: %s" name))
2832 (or (assoc inherits ebnf-style-database)
0e816a43 2833 (error "Style inheritance name doesn't exist: %s" inherits))
984ae001
GM
2834 (setq ebnf-style-database
2835 (cons (cons name (cons inherits (ebnf-check-style-values values)))
2836 ebnf-style-database)))
2837
2838
ac4780a1
VJL
2839;;;###autoload
2840(defun ebnf-delete-style (name)
2841 "Delete style NAME.
2842
2843See `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))
2848 (while db
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)))
2854
2855
984ae001
GM
2856;;;###autoload
2857(defun ebnf-merge-style (name &rest values)
ac4780a1
VJL
2858 "Merge values of style NAME with style VALUES.
2859
2860See `ebnf-style-database' documentation."
2861 (interactive "SStyle name: \nXStyle values: ")
984ae001 2862 (let ((style (or (assoc name ebnf-style-database)
0e816a43 2863 (error "Style name doesn't exist: %s" name)))
984ae001
GM
2864 (merge (ebnf-check-style-values values))
2865 val elt new check)
2866 ;; modify value of existing variables
2867 (setq val (nthcdr 2 style))
2868 (while merge
2869 (setq check (car merge)
2870 merge (cdr merge)
2871 elt (assoc (car check) val))
2872 (if elt
2873 (setcdr elt (cdr check))
2874 (setq new (cons check new))))
2875 ;; insert new variables
2876 (nconc style (nreverse new))))
2877
2878
2879;;;###autoload
2880(defun ebnf-apply-style (style)
ac4780a1 2881 "Set STYLE as the current style.
984ae001 2882
815cbda2 2883Returns the old style symbol.
ac4780a1
VJL
2884
2885See `ebnf-style-database' documentation."
2886 (interactive "SApply style: ")
984ae001
GM
2887 (prog1
2888 ebnf-current-style
2889 (and (ebnf-apply-style1 style)
2890 (setq ebnf-current-style style))))
2891
2892
2893;;;###autoload
2894(defun ebnf-reset-style (&optional style)
2895 "Reset current style.
2896
815cbda2 2897Returns the old style symbol.
ac4780a1
VJL
2898
2899See `ebnf-style-database' documentation."
2900 (interactive "SReset style: ")
984ae001
GM
2901 (setq ebnf-stack-style nil)
2902 (ebnf-apply-style (or style 'default)))
2903
2904
2905;;;###autoload
2906(defun ebnf-push-style (&optional style)
815cbda2
EZ
2907 "Push the current style onto a stack and set STYLE as the current style.
2908
2909Returns the old style symbol.
984ae001 2910
815cbda2 2911See also `ebnf-pop-style'.
ac4780a1
VJL
2912
2913See `ebnf-style-database' documentation."
2914 (interactive "SPush style: ")
984ae001
GM
2915 (prog1
2916 ebnf-current-style
2917 (setq ebnf-stack-style (cons ebnf-current-style ebnf-stack-style))
2918 (and style
2919 (ebnf-apply-style style))))
2920
2921
2922;;;###autoload
2923(defun ebnf-pop-style ()
815cbda2 2924 "Pop a style from the stack of pushed styles and set it as the current style.
ac4780a1 2925
815cbda2
EZ
2926Returns the old style symbol.
2927
2928See also `ebnf-push-style'.
984ae001 2929
ac4780a1 2930See `ebnf-style-database' documentation."
984ae001
GM
2931 (interactive)
2932 (prog1
2933 (ebnf-apply-style (car ebnf-stack-style))
2934 (setq ebnf-stack-style (cdr ebnf-stack-style))))
2935
2936
2937(defun ebnf-apply-style1 (style)
2938 (let ((value (cdr (assoc style ebnf-style-database))))
2939 (prog1
2940 value
2941 (and (car value) (ebnf-apply-style1 (car value)))
2942 (while (setq value (cdr value))
2943 (set (caar value) (eval (cdar value)))))))
2944
2945
2946(defun ebnf-check-style-values (values)
2947 (let (style)
2948 (while values
ac4780a1 2949 (and (memq (caar values) ebnf-style-custom-list)
984ae001
GM
2950 (setq style (cons (car values) style)))
2951 (setq values (cdr values)))
2952 (nreverse style)))
2953
2954\f
2955;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2956;; Internal variables
2957
2958
3ced5caa
VJL
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)
984ae001 2965(make-variable-buffer-local 'ebnf-eps-upper-x)
3ced5caa 2966(defvar ebnf-eps-upper-y 0.0)
984ae001 2967(make-variable-buffer-local 'ebnf-eps-upper-y)
3ced5caa 2968(defvar ebnf-eps-prod-width 0.0)
984ae001 2969(make-variable-buffer-local 'ebnf-eps-prod-width)
3ced5caa 2970(defvar ebnf-eps-max-height 0.0)
984ae001 2971(make-variable-buffer-local 'ebnf-eps-max-height)
3ced5caa 2972(defvar ebnf-eps-max-width 0.0)
984ae001
GM
2973(make-variable-buffer-local 'ebnf-eps-max-width)
2974
2975
2976(defvar ebnf-eps-context nil
2977 "List of EPS file name during parsing.
2978
2979See section \"Actions in Comments\" in ebnf2ps documentation.")
2980
2981
3ced5caa
VJL
2982(defvar ebnf-eps-file-alist nil
2983"Alist associating file name with EPS header and footer.
2984
2985Each element has the following form:
2986
2987 (EPS-FILENAME HEADER FOOTER)
2988
2989EPS-FILENAME is the EPS file name.
2990HEADER is the header string or nil.
2991FOOTER is the footer string or nil.
2992
2993It's generated during parsing and used during EPS generation.
2994
2995See `ebnf-eps-context' and section \"Actions in Comments\" in ebnf2ps
2996documentation.")
2997
2998
984ae001
GM
2999(defvar ebnf-eps-production-list nil
3000 "Alist associating production name with EPS file name list.
3001
3002Each element has the following form:
3003
3004 (PRODUCTION EPS-FILENAME...)
3005
3006PRODUCTION is the production name.
3007EPS-FILENAME is the EPS file name.
3008
815cbda2 3009This is generated during parsing and used during EPS generation.
984ae001
GM
3010
3011See `ebnf-eps-context' and section \"Actions in Comments\" in ebnf2ps
3012documentation.")
3013
3014
3015(defconst ebnf-arrow-shape-alist
ac4780a1
VJL
3016 '((none . 0)
3017 (semi-up . 1)
3018 (semi-down . 2)
3019 (simple . 3)
3020 (transparent . 4)
3021 (hollow . 5)
3022 (full . 6)
3023 (semi-up-hollow . 7)
3024 (semi-up-full . 8)
3025 (semi-down-hollow . 9)
3026 (semi-down-full . 10)
3027 (user . 11))
984ae001
GM
3028 "Alist associating values for `ebnf-arrow-shape'.
3029
3030See documentation for `ebnf-arrow-shape'.")
3031
3032
3033(defconst ebnf-terminal-shape-alist
3034 '((miter . 0)
3035 (round . 1)
3036 (bevel . 2))
3037 "Alist associating values from `ebnf-terminal-shape' to a bit vector.
3038
3039See documentation for `ebnf-terminal-shape', `ebnf-non-terminal-shape' and
3040`ebnf-chart-shape'.")
3041
3042
3ced5caa
VJL
3043(defvar ebnf-limit nil)
3044(defvar ebnf-action nil)
3045(defvar ebnf-action-list nil)
984ae001
GM
3046
3047
3ced5caa 3048(defvar ebnf-default-p nil)
984ae001
GM
3049
3050
3ced5caa
VJL
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)
984ae001
GM
3068
3069
3ced5caa
VJL
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)
984ae001
GM
3076
3077
3ced5caa
VJL
3078(defvar ebnf-settings nil)
3079(defvar ebnf-fonts-required nil)
984ae001
GM
3080
3081
3082(defconst ebnf-debug
3083 "
3084% === begin EBNF procedures to help debugging
3085
3086% Mark visually current point: string debug
3087/debug
3088{/-s- exch def
3089 currentpoint
3090 gsave -s- show grestore
3091 gsave
3092 20 20 rlineto
3093 0 -40 rlineto
3094 -40 40 rlineto
3095 0 -40 rlineto
3096 20 20 rlineto
3097 stroke
3098 grestore
3099 moveto
3100}def
3101
3102% Show number value: number string debug-number
3103/debug-number
3104{gsave
3105 20 0 rmoveto show ([) show 60 string cvs show (]) show
3106 grestore
3107}def
3108
3109% === end EBNF procedures to help debugging
3110
3111"
3112 "This is intended to help debugging PostScript programming.")
3113
3114
3115(defconst ebnf-prologue
3116 "
3117% === begin EBNF engine
3118
3119% --- Basic Definitions
3120
3121/fS F
3122/SpaceS FontHeight 0.5 mul def
3123/HeightS FontHeight FontHeight add def
3124
3125/fE F
3126/SpaceE FontHeight 0.5 mul def
3127/HeightE FontHeight FontHeight add def
3128
3129/fR F
3130/SpaceR FontHeight 0.5 mul def
3131/HeightR FontHeight FontHeight add def
3132
3133/fT F
3134/SpaceT FontHeight 0.5 mul def
3135/HeightT FontHeight FontHeight add def
3136
3137/fNT F
3138/SpaceNT FontHeight 0.5 mul def
3139/HeightNT FontHeight FontHeight add def
3140
3141/T HeightT HeightNT add 0.5 mul def
ed0aa46c
VJL
3142/hT T 0.5 mul def
3143/hT2 hT 0.5 mul ArrowScale mul def
3144/hT4 hT 0.25 mul ArrowScale mul def
984ae001
GM
3145
3146/Er 0.1 def % Error factor
3147
3148
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
3154
3155% vertical movement: x y height vm
3156/vm{add moveto}bind def
3157
3158% horizontal movement: x y width hm
3159/hm{3 -1 roll exch add exch moveto}bind def
3160
3161% set color: [R G B] SetRGB
3162/SetRGB{aload pop setrgbcolor}bind def
3163
3164% filling gray area: gray-scale FillGray
3165/FillGray{gsave setgray fill grestore}bind def
3166
3167% filling color area: [R G B] FillRGB
3168/FillRGB{gsave SetRGB fill grestore}bind def
3169
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
3173
3174% Empty Line: width EL
3175/EL{0 rlineto Gstroke}bind def
3176
3177% --- Arrows
3178
3179/Down{hT2 neg hT4 neg rlineto}bind def
3180
3181/Arrow
3182{hT2 neg hT4 rmoveto
3183 hT2 hT4 neg rlineto
3184 Down
3185}bind def
3186
3187/ArrowPath{c newpath moveto Arrow closepath}bind def
3188
ac4780a1
VJL
3189/UpPath
3190{c newpath moveto
3191 hT2 neg 0 rmoveto
3192 0 hT4 rlineto
3193 hT2 hT4 neg rlineto
3194 closepath
3195}bind def
3196
3197/DownPath
3198{c newpath moveto
3199 hT2 neg 0 rmoveto
3200 0 hT4 neg rlineto
3201 hT2 hT4 rlineto
3202 closepath
3203}bind def
3204
984ae001
GM
3205%>Right Arrow: RA
3206% \\
3207% *---+
3208% /
3209/RA-vector
ac4780a1
VJL
3210[{} % 0 - none
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
984ae001
GM
3222]def
3223
3224/RA
3225{hT 0 rlineto
3226 c
3227 RA-vector ArrowShape get exec
3228 Gstroke
3229 moveto
ed0aa46c 3230 ExtraWidth 0 rmoveto
984ae001
GM
3231}def
3232
3233% rotation DrawArrow
3234/DrawArrow
3235{gsave
3236 0 0 translate
3237 rotate
3238 RA
3239 c
3240 grestore
3241 rmoveto
3242}def
3243
3244%>Left Arrow: LA
3245% /
3246% +---*
3247% \\
3248/LA{180 DrawArrow}def
3249
3250%>Up Arrow: UA
3251% +
3252% /|\\
3253% |
3254% *
3255/UA{90 DrawArrow}def
3256
3257%>Down Arrow: DA
3258% *
3259% |
3260% \\|/
3261% +
3262/DA{270 DrawArrow}def
3263
3264% --- Corners
3265
3266%>corner Right Descendent: height arrow corner_RD
3267% _ | arrow
3268% / height > 0 | 0 - none
3269% | | 1 - right
3270% * ---------- | 2 - left
3271% | | 3 - vertical
3272% \\ height < 0 |
3273% - |
3274/cRD0-vector
3275[% 0 - none
3276 {0 h rlineto
3277 hT 0 rlineto}
3278 % 1 - right
3279 {0 h rlineto
3280 RA}
3281 % 2 - left
3282 {hT 0 rmoveto xyi
3283 LA
3284 0 h neg rlineto
3285 xi yi moveto}
3286 % 3 - vertical
3287 {hT h rmoveto xyi
3288 hT neg 0 rlineto
3289 h 0 gt{DA}{UA}ifelse
3290 xi yi moveto}
3291]def
3292
3293/cRD-vector
3294[{cRD0-vector arrow get exec} % 0 - miter
3295 {0 0 0 h hT h rcurveto} % 1 - rounded
3296 {hT h rlineto} % 2 - bevel
3297]def
3298
3299/corner_RD
3300{/arrow exch def /h exch def
3301 cRD-vector ChartShape get exec
3302 Gstroke
3303}def
3304
3305%>corner Right Ascendent: height arrow corner_RA
3306% | arrow
3307% | height > 0 | 0 - none
3308% / | 1 - right
3309% *- ---------- | 2 - left
3310% \\ | 3 - vertical
3311% | height < 0 |
3312% |
3313/cRA0-vector
3314[% 0 - none
3315 {hT 0 rlineto
3316 0 h rlineto}
3317 % 1 - right
3318 {RA
3319 0 h rlineto}
3320 % 2 - left
3321 {hT h rmoveto xyi
3322 0 h neg rlineto
3323 LA
3324 xi yi moveto}
3325 % 3 - vertical
3326 {hT h rmoveto xyi
3327 h 0 gt{DA}{UA}ifelse
3328 hT neg 0 rlineto
3329 xi yi moveto}
3330]def
3331
3332/cRA-vector
3333[{cRA0-vector arrow get exec} % 0 - miter
3334 {0 0 hT 0 hT h rcurveto} % 1 - rounded
3335 {hT h rlineto} % 2 - bevel
3336]def
3337
3338/corner_RA
3339{/arrow exch def /h exch def
3340 cRA-vector ChartShape get exec
3341 Gstroke
3342}def
3343
3344%>corner Left Descendent: height arrow corner_LD
3345% _ | arrow
3346% \\ height > 0 | 0 - none
3347% | | 1 - right
3348% * ---------- | 2 - left
3349% | | 3 - vertical
3350% / height < 0 |
3351% - |
3352/cLD0-vector
3353[% 0 - none
3354 {0 h rlineto
3355 hT neg 0 rlineto}
3356 % 1 - right
3357 {hT neg h rmoveto xyi
3358 RA
3359 0 h neg rlineto
3360 xi yi moveto}
3361 % 2 - left
3362 {0 h rlineto
3363 LA}
3364 % 3 - vertical
3365 {hT neg h rmoveto xyi
3366 hT 0 rlineto
3367 h 0 gt{DA}{UA}ifelse
3368 xi yi moveto}
3369]def
3370
3371/cLD-vector
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
3375]def
3376
3377/corner_LD
3378{/arrow exch def /h exch def
3379 cLD-vector ChartShape get exec
3380 Gstroke
3381}def
3382
3383%>corner Left Ascendent: height arrow corner_LA
3384% | arrow
3385% | height > 0 | 0 - none
3386% \\ | 1 - right
3387% -* ---------- | 2 - left
3388% / | 3 - vertical
3389% | height < 0 |
3390% |
3391/cLA0-vector
3392[% 0 - none
3393 {hT neg 0 rlineto
3394 0 h rlineto}
3395 % 1 - right
3396 {hT neg h rmoveto xyi
3397 0 h neg rlineto
3398 RA
3399 xi yi moveto}
3400 % 2 - left
3401 {LA
3402 0 h rlineto}
3403 % 3 - vertical
3404 {hT neg h rmoveto xyi
3405 h 0 gt{DA}{UA}ifelse
3406 hT 0 rlineto
3407 xi yi moveto}
3408]def
3409
3410/cLA-vector
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
3414]def
3415
3416/corner_LA
3417{/arrow exch def /h exch def
3418 cLA-vector ChartShape get exec
3419 Gstroke
3420}def
3421
3422% --- Flow Stuff
3423
3ced5caa
VJL
3424% height prepare-height |- line_height corner_height corner_height
3425/prepare-height
984ae001
GM
3426{dup 0 gt
3427 {T sub hT}
3428 {T add hT neg}ifelse
3429 dup
3430}def
3431
3432%>Left Alternative: height LAlt
3433% _
3434% /
3435% | height > 0
3436% |
3437% /
3438% *- ----------
3439% \\
3440% |
3441% | height < 0
3442% \\
3443% -
3444/LAlt
3445{dup 0 eq
3446 {T exch rlineto}
3447 {dup abs T lt
3448 {0.5 mul dup
3449 1 corner_RA
3450 0 corner_RD}
3ced5caa 3451 {prepare-height
984ae001
GM
3452 1 corner_RA
3453 exch 0 exch rlineto
3454 0 corner_RD
3455 }ifelse
3456 }ifelse
3457}def
3458
3459%>Left Loop: height LLoop
3460% _
3461% /
3462% | height > 0
3463% |
3464% \\
3465% -* ----------
3466% /
3467% |
3468% | height < 0
3469% \\
3470% -
3471/LLoop
3ced5caa 3472{prepare-height
984ae001
GM
3473 3 corner_LA
3474 exch 0 exch rlineto
3475 0 corner_RD
3476}def
3477
3478%>Right Alternative: height RAlt
3479% _
3480% \\
3481% | height > 0
3482% |
3483% \\
3484% -* ----------
3485% /
3486% |
3487% | height < 0
3488% /
3489% -
3490/RAlt
3491{dup 0 eq
3492 {T neg exch rlineto}
3493 {dup abs T lt
3494 {0.5 mul dup
3495 1 corner_LA
3496 0 corner_LD}
3ced5caa 3497 {prepare-height
984ae001
GM
3498 1 corner_LA
3499 exch 0 exch rlineto
3500 0 corner_LD
3501 }ifelse
3502 }ifelse
3503}def
3504
3505%>Right Loop: height RLoop
3506% _
3507% \\
3508% | height > 0
3509% |
3510% /
3511% *- ----------
3512% \\
3513% |
3514% | height < 0
3515% /
3516% -
3517/RLoop
3ced5caa 3518{prepare-height
984ae001
GM
3519 1 corner_RA
3520 exch 0 exch rlineto
3521 0 corner_LD
3522}def
3523
3524% --- Terminal, Non-terminal and Special Basics
3525
3526% string width prepare-width |- string
3527/prepare-width
3528{/width exch def
ed0aa46c 3529 dup stringwidth pop space add space add width exch sub ExtraWidth sub 0.5 mul
984ae001
GM
3530 /w exch def
3531}def
3532
3533% string width begin-right
3534/begin-right
3535{xyo
3536 prepare-width
3537 w hT sub EL
3538 RA
3539}def
3540
3541% end-right
3542/end-right
3543{xo width add Er add yo moveto
3544 w Er add neg EL
3545 xo yo moveto
3546}def
3547
3548% string width begin-left
3549/begin-left
3550{xyo
3551 prepare-width
3552 w EL
3553}def
3554
3555% end-left
3556/end-left
3557{xo width add Er add yo moveto
3558 hT w sub Er add EL
3559 LA
3560 xo yo moveto
3561}def
3562
3563/ShapePath-vector
3564[% 0 - miter
3565 {xx yy moveto
3566 xx YY lineto
3567 XX YY lineto
3568 XX yy lineto}
3569 % 1 - rounded
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}
3577 % 2 - bevel
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}
3587]def
3588
3589/doShapePath
3590{newpath
3591 ShapePath-vector shape get exec
3592 closepath
3593}def
3594
3595/doShapeShadow
3596{gsave
3597 Xshadow Xshadow add Xshadow add
3598 Yshadow Yshadow add Yshadow add translate
3599 doShapePath
3600 0.9 FillGray
3601 grestore
3602}def
3603
3604/doShape
3605{gsave
3606 doShapePath
3607 shapecolor FillRGB
3608 StrokeShape
3609 grestore
3610}def
3611
3612% string SBound |- string
3613/SBound
3614{/xx c dup /yy exch def
3615 FontHeight add /YY exch def def
3616 dup stringwidth pop xx add /XX exch def
3617 Effect 8 and 0 ne
3618 {/yy yy YShadow add def
3619 /XX XX XShadow add def
3620 }if
3621}def
3622
3623% string SBox
3624/SBox
3625{gsave
3626 c space sub moveto
3627 SBound
3628 /XX XX space add space add def
3629 /YY YY space add def
3630 /yy yy space sub def
3631 shadow{doShapeShadow}if
3632 doShape
3633 space Descent abs rmoveto
3634 foreground SetRGB S
3635 grestore
3636}def
3637
3638% --- Terminal
3639
3640% TeRminal: string TR
3641/TR
3642{/Effect EffectT def
3643 /shape ShapeT def
3644 /shapecolor BackgroundT def
3645 /borderwidth BorderWidthT def
3646 /bordercolor BorderColorT def
3647 /foreground ForegroundT def
3648 /shadow ShadowT def
3649 SBox
3650}def
3651
3652%>Right Terminal: string width RT |- x y
3653/RT
3654{xyt
3655 /fT F
3656 /space SpaceT def
3657 begin-right
3658 TR
3659 end-right
3660 xt yt
3661}def
3662
3663%>Left Terminal: string width LT |- x y
3664/LT
3665{xyt
3666 /fT F
3667 /space SpaceT def
3668 begin-left
3669 TR
3670 end-left
3671 xt yt
3672}def
3673
3674%>Right Terminal Default: string width RTD |- x y
3675/RTD
3676{/-save- BorderWidthT def
3677 /BorderWidthT BorderWidthT DefaultWidth add def
3678 RT
3679 /BorderWidthT -save- def
3680}def
3681
3682%>Left Terminal Default: string width LTD |- x y
3683/LTD
3684{/-save- BorderWidthT def
3685 /BorderWidthT BorderWidthT DefaultWidth add def
3686 LT
3687 /BorderWidthT -save- def
3688}def
3689
3690% --- Non-Terminal
3691
3692% Non-Terminal: string NT
3693/NT
3694{/Effect EffectNT def
3695 /shape ShapeNT def
3696 /shapecolor BackgroundNT def
3697 /borderwidth BorderWidthNT def
3698 /bordercolor BorderColorNT def
3699 /foreground ForegroundNT def
3700 /shadow ShadowNT def
3701 SBox
3702}def
3703
3704%>Right Non-Terminal: string width RNT |- x y
3705/RNT
3706{xyt
3707 /fNT F
3708 /space SpaceNT def
3709 begin-right
3710 NT
3711 end-right
3712 xt yt
3713}def
3714
3715%>Left Non-Terminal: string width LNT |- x y
3716/LNT
3717{xyt
3718 /fNT F
3719 /space SpaceNT def
3720 begin-left
3721 NT
3722 end-left
3723 xt yt
3724}def
3725
3726%>Right Non-Terminal Default: string width RNTD |- x y
3727/RNTD
3728{/-save- BorderWidthNT def
3729 /BorderWidthNT BorderWidthNT DefaultWidth add def
3730 RNT
3731 /BorderWidthNT -save- def
3732}def
3733
3734%>Left Non-Terminal Default: string width LNTD |- x y
3735/LNTD
3736{/-save- BorderWidthNT def
3737 /BorderWidthNT BorderWidthNT DefaultWidth add def
3738 LNT
3739 /BorderWidthNT -save- def
3740}def
3741
3742% --- Special
3743
3744% SPecial: string SP
3745/SP
3746{/Effect EffectS def
3747 /shape ShapeS def
3748 /shapecolor BackgroundS def
3749 /borderwidth BorderWidthS def
3750 /bordercolor BorderColorS def
3751 /foreground ForegroundS def
3752 /shadow ShadowS def
3753 SBox
3754}def
3755
3756%>Right SPecial: string width RSP |- x y
3757/RSP
3758{xyt
3759 /fS F
3760 /space SpaceS def
3761 begin-right
3762 SP
3763 end-right
3764 xt yt
3765}def
3766
3767%>Left SPecial: string width LSP |- x y
3768/LSP
3769{xyt
3770 /fS F
3771 /space SpaceS def
3772 begin-left
3773 SP
3774 end-left
3775 xt yt
3776}def
3777
3778%>Right SPecial Default: string width RSPD |- x y
3779/RSPD
3780{/-save- BorderWidthS def
3781 /BorderWidthS BorderWidthS DefaultWidth add def
3782 RSP
3783 /BorderWidthS -save- def
3784}def
3785
3786%>Left SPecial Default: string width LSPD |- x y
3787/LSPD
3788{/-save- BorderWidthS def
3789 /BorderWidthS BorderWidthS DefaultWidth add def
3790 LSP
3791 /BorderWidthS -save- def
3792}def
3793
3794% --- Repeat and Except basics
3795
3796/begin-direction
3797{/w width rwidth sub 0.5 mul def
3798 width 0 rmoveto}def
3799
3800/end-direction
3801{gsave
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
3806 doShape
3807 grestore
3808}def
3809
3810/right-direction
3811{begin-direction
3812 w neg EL
3813 xt yt moveto
3814 w hT sub EL RA
3815 end-direction
3816}def
3817
3818/left-direction
3819{begin-direction
3820 hT w sub EL LA
3821 xt yt moveto
3822 w EL
3823 end-direction
3824}def
3825
3826% --- Repeat
3827
3828% entry height width rwidth begin-repeat
3829/begin-repeat
3830{/rwidth exch def
3831 /width exch def
3832 /height exch def
3833 /entry exch def
3834 /fR F
3835 /space SpaceR def
3836 /Effect EffectR def
3837 /shape ShapeR def
3838 /shapecolor BackgroundR def
3839 /borderwidth BorderWidthR def
3840 /bordercolor BorderColorR def
3841 /foreground ForegroundR def
3842 /shadow ShadowR def
3843 xyt
3844}def
3845
3846% string end-repeat |- x y
3847/end-repeat
3848{gsave
3849 space Descent rmoveto
3850 foreground SetRGB S
3851 c Descent sub
3852 grestore
3853 exch space add exch moveto
3854 xt yt
3855}def
3856
3857%>Right RePeat: string entry height width rwidth RRP |- x y
3858/RRP{begin-repeat right-direction end-repeat}def
3859
3860%>Left RePeat: string entry height width rwidth LRP |- x y
3861/LRP{begin-repeat left-direction end-repeat}def
3862
3863% --- Except
3864
3865% entry height width rwidth begin-except
3866/begin-except
3867{/rwidth exch def
3868 /width exch def
3869 /height exch def
3870 /entry exch def
3871 /fE F
3872 /space SpaceE def
3873 /Effect EffectE def
3874 /shape ShapeE def
3875 /shapecolor BackgroundE def
3876 /borderwidth BorderWidthE def
3877 /bordercolor BorderColorE def
3878 /foreground ForegroundE def
3879 /shadow ShadowE def
3880 xyt
3881}def
3882
3883% x-width end-except |- x y
3884/end-except
3885{gsave
3886 space space add add Descent rmoveto
3887 (-) foreground SetRGB S
3888 grestore
3889 space 0 rmoveto
3890 xt yt
3891}def
3892
3893%>Right EXcept: x-width entry height width rwidth REX |- x y
3894/REX{begin-except right-direction end-except}def
3895
3896%>Left EXcept: x-width entry height width rwidth LEX |- x y
3897/LEX{begin-except left-direction end-except}def
3898
3899% --- Sequence
3900
3901%>Beginning Of Sequence: BOS |- x y
3902/BOS{currentpoint}bind def
3903
3904%>End Of Sequence: x y x1 y1 EOS |- x y
3905/EOS{pop pop}bind def
3906
3907% --- Production
3908
3909%>Beginning Of Production: string width height BOP |- y x
3910/BOP
3911{xyp
3912 neg yp add /yw exch def
3913 xp add T sub /xw exch def
ac4780a1
VJL
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
3917 /Effect 0 def
3918 ( :) S false BG}if
984ae001
GM
3919 xw yw moveto
3920 hT EL RA
3921 xp yw moveto
3922 T EL
3923 yp xp
3924}def
3925
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
3929
3930% --- Empty Alternative
3931
3932%>Empty Alternative: width EA |- x y
3933/EA
3934{gsave
3935 Er add 0 rlineto
3936 Stroke
3937 grestore
3938 c
3939}def
3940
3941% --- Alternative
3942
3943%>AlTernative: h1 h2 ... hn n width AT |- x y
3944/AT
3945{xyo xo add /xw exch def
3946 xw yo moveto
3947 Er EL
3948 {xw yo moveto
3949 dup RAlt
3950 xo yo moveto
3951 LAlt}repeat
3952 xo yo
3953}def
3954
3955% --- Optional
3956
3957%>OPtional: height width OP |- x y
3958/OP
3959{xyo
3960 T sub /ow exch def
3961 ow Er sub 0 rmoveto
3962 T Er add EL
3963 neg dup RAlt
3964 ow T sub neg EL
3965 xo yo moveto
3966 LAlt
3967 xo yo moveto
3968 T EL
3969 xo yo
3970}def
3971
3972% --- List Flow
3973
3974%>One or More: height width OM |- x y
3975/OM
3976{xyo
3977 /ow exch def
3978 ow Er add 0 rmoveto
3979 T Er add neg EL
3980 dup RLoop
3981 xo T add yo moveto
3982 LLoop
3983 xo yo moveto
3984 T EL
3985 xo yo
3986}def
3987
3988%>Zero or More: h2 h1 width ZM |- x y
3989/ZM
3990{xyo
3991 Er add EL
3992 Er neg 0 rmoveto
3993 dup RAlt
3994 exch dup RLoop
3995 xo yo moveto
3996 exch dup LAlt
3997 exch LLoop
3998 yo add xo T add exch moveto
3999 xo yo
4000}def
4001
4002% === end EBNF engine
4003
4004"
4005 "EBNF PostScript prologue")
4006
4007
4008(defconst ebnf-eps-prologue
4009 "
4010/#ebnf2ps#dict 230 dict def
4011#ebnf2ps#dict begin
4012
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
4032/YY 0 def /xi 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
4039/dd 0 def /yo 0 def
4040/entry 0 def /yp 0 def
4041/foreground 0 def /yt 0 def
4042 /yy 0 def
4043
4044
4045% ISOLatin1Encoding stolen from ps_init.ps in GhostScript 2.6.1.4:
4046/ISOLatin1Encoding where
4047{pop}
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.
4051 /ISOLatin1Encoding
4052 StandardEncoding 0 45 getinterval aload pop
4053 /minus
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.
4058 % 0200 (128)
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
4063 % 0240 (160)
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
4072 % 0300 (192)
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
4081 % 0340 (224)
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
4090 256 packedarray def
4091}ifelse
4092
4093/reencodeFontISO %def
4094{dup
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.
4097
4098 begin % Make the new font the current dictionary.
4099 {1 index /FID ne
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.
4103
4104 currentdict /FontType get 0 ne
4105 {/Encoding ISOLatin1Encoding def}if % Override the encoding with
4106 % the ISOLatin1 encoding.
4107
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.
4111
4112 % ^ (x2 y2)
4113 % | |
4114 % | v
4115 % | +----+ - -
4116 % | | | ^
4117 % | | | | Ascent (usually > 0)
4118 % | | | |
4119 % (0 0) -> +--+----+-------->
4120 % | | |
4121 % | | v Descent (usually < 0)
4122 % (x1 y1) --> +----+ - -
4123
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
4132 }ifelse
4133
4134 /FontHeight Ascent Descent sub def % use `sub' because descent < 0
4135
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
4147
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
4152}bind def
4153
4154% Font definition
4155/DefFont{findfont exch scalefont reencodeFontISO}def
4156
4157% Font selection
4158/F
4159{findfont
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
4172 setfont
4173}def
4174
4175/BG
4176{dup /bg exch def
4177 {mark 4 1 roll ]}
4178 {[ 1.0 1.0 1.0 ]}
4179 ifelse
4180 /bgcolor exch def
4181}def
4182
4183% stack: --
4184/FillBgColor{bgcolor aload pop setrgbcolor fill}bind def
4185
4186% stack: fill-or-not lower-x lower-y upper-x upper-y |- --
4187/doRect
4188{/rYY exch def
4189 /rXX exch def
4190 /ryy exch def
4191 /rxx exch def
4192 gsave
4193 newpath
4194 rXX rYY moveto
4195 rxx rYY lineto
4196 rxx ryy lineto
4197 rXX ryy lineto
4198 closepath
4199 % top of stack: fill-or-not
4200 {FillBgColor}
4201 {LineThickness setlinewidth stroke}
4202 ifelse
4203 grestore
4204}bind def
4205
4206% stack: string fill-or-not |- --
4207/doOutline
4208{/-fillp- exch def
4209 /-ox- currentpoint /-oy- exch def def
4210 gsave
4211 LineThickness setlinewidth
4212 {st 0 3 -1 roll put
4213 st dup true charpath
4214 -fillp- {gsave FillBgColor grestore}if
4215 stroke stringwidth
4216 -oy- add /-oy- exch def
4217 -ox- add /-ox- exch def
4218 -ox- -oy- moveto
4219 }forall
4220 grestore
4221 -ox- -oy- moveto
4222}bind def
4223
4224% stack: fill-or-not delta |- --
4225/doBox
4226{/dd exch def
4227 xx XBox sub dd sub yy YBox sub dd sub
4228 XX XBox add dd add YY YBox add dd add
4229 doRect
4230}bind def
4231
4232% stack: string |- --
4233/doShadow
4234{gsave
4235 Xshadow Yshadow rmoveto
4236 false doOutline
4237 grestore
4238}bind def
4239
4240% stack: position |- --
4241/Hline
4242{currentpoint exch pop add dup
4243 gsave
4244 newpath
4245 xx exch moveto
4246 XX exch lineto
4247 closepath
4248 LineThickness setlinewidth stroke
4249 grestore
4250}bind def
4251
4252% stack: string |- --
4253% effect: 1 - underline 2 - strikeout 4 - overline
4254% 8 - shadow 16 - box 32 - outline
4255/S
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
4259 Effect 8 and 0 ne
4260 {/yy yy Yshadow add def
4261 /XX XX Xshadow add def
4262 }if
4263 bg
4264 {true
4265 Effect 16 and 0 ne
4266 {SpaceBackground doBox}
4267 {xx yy XX YY doRect}
4268 ifelse
4269 }if % background
4270 Effect 16 and 0 ne{false 0 doBox}if % box
4271 Effect 8 and 0 ne{dup doShadow}if % shadow
4272 Effect 32 and 0 ne
4273 {true doOutline} % outline
4274 {show} % normal text
4275 ifelse
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
4279}bind def
4280
4281"
4282 "EBNF EPS prologue")
4283
4284
4285(defconst ebnf-eps-begin
4286 "
4287end
4288
4289% x y #ebnf2ps#begin
4290/#ebnf2ps#begin
4291{#ebnf2ps#dict begin /#ebnf2ps#save save def
4292 moveto false BG 0.0 0.0 0.0 setrgbcolor}def
4293
4294/#ebnf2ps#end{showpage #ebnf2ps#save restore end}def
4295
0b5ecd6d 4296%%EndProlog
984ae001
GM
4297"
4298 "EBNF EPS begin")
4299
4300
4301(defconst ebnf-eps-end
4302 "#ebnf2ps#end
4303%%EOF
4304"
4305 "EBNF EPS end")
4306
4307\f
3ced5caa
VJL
4308;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4309;; Header & Footer
4310
4311
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))
4318 (t nil))
4319 value)))
4320 (and (stringp tmp) tmp)))
4321
4322
4323(defun ebnf-eps-header ()
4324 ;; evaluate header value
4325 (ebnf-eps-header-footer ebnf-eps-header))
4326
4327
4328(defun ebnf-eps-footer ()
4329 ;; evaluate footer value
4330 (ebnf-eps-header-footer ebnf-eps-footer))
4331
4332
4333;; hacked fom `ps-output-string-prim' (ps-print.el)
4334(defun ebnf-eps-string (string)
4335 (let* ((str (string-as-unibyte string))
4336 (len (length str))
4337 (index 0)
4338 (new "(") ; insert start-string delimiter
4339 start special)
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)
4344 new (concat new
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)))
4351 index (1+ start)))
4352 (concat new
4353 (and (< index len)
4354 (substring str index len))
4355 ")"))) ; insert end-string delimiter
4356
4357
4358(defun ebnf-eps-header-footer-comment (str)
4359 ;; parse header/footer comment string
4360 (let ((len (1- (length str)))
4361 (index 0)
4362 new start fmt)
4363 (while (setq start (string-match "%" str index))
4364 (setq fmt (if (< start len) (aref str (1+ start)) ?\?)
4365 new (concat new
4366 (substring str index start)
4367 (cond ((= fmt ?%) "%")
4368 ((= fmt ?H) (ebnf-eps-header))
4369 ((= fmt ?F) (ebnf-eps-footer))
4370 (t nil)
4371 ))
4372 index (+ start 2)))
4373 (ebnf-eps-string (concat new
4374 (and (<= index len)
4375 (substring str index (1+ len)))))))
4376
4377
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 "")))))
4382
4383
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))))
4388
4389
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))))
4394
4395
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))))
4401 (if (null filehf)
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))))
4406
4407
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))))
4413
4414\f
984ae001
GM
4415;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4416;; Formatting
4417
4418
4419(defvar ebnf-format-float "%1.3f")
4420
4421
4422(defun ebnf-format-float (&rest floats)
4423 (mapconcat
4424 #'(lambda (float)
4425 (format ebnf-format-float float))
4426 floats
4427 " "))
4428
4429
4430(defun ebnf-format-color (format-str color default)
4431 (let* ((the-color (or color default))
b685181e 4432 (rgb (ps-color-scale the-color)))
984ae001
GM
4433 (format format-str
4434 (concat "["
4435 (ebnf-format-float (nth 0 rgb) (nth 1 rgb) (nth 2 rgb))
4436 "]")
4437 the-color)))
4438
4439
4440(defvar ebnf-message-float "%3.2f")
4441
4442
4443(defsubst ebnf-message-float (format-str value)
4444 (message format-str
4445 (format ebnf-message-float value)))
4446
4447
30fa28b4
VJL
4448(defvar ebnf-total 0)
4449(defvar ebnf-nprod 0)
4450
4451
984ae001
GM
4452(defsubst ebnf-message-info (messag)
4453 (message "%s...%3d%%"
4454 messag
4455 (round (/ (* (setq ebnf-nprod (1+ ebnf-nprod)) 100.0) ebnf-total))))
4456
4457\f
4458;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4459;; Macros
4460
4461
4462(defmacro ebnf-node-kind (vec &optional value)
4463 (if value
4464 `(aset ,vec 0 ,value)
4465 `(aref ,vec 0)))
4466
4467
4468(defmacro ebnf-node-width-func (node width)
4469 `(funcall (aref ,node 1) ,node ,width))
4470
4471
4472(defmacro ebnf-node-dimension-func (node &optional value)
4473 (if value
4474 `(aset ,node 2 ,value)
4475 `(funcall (aref ,node 2) ,node)))
4476
4477
4478(defmacro ebnf-node-entry (vec &optional value)
4479 (if value
4480 `(aset ,vec 3 ,value)
4481 `(aref ,vec 3)))
4482
4483
4484(defmacro ebnf-node-height (vec &optional value)
4485 (if value
4486 `(aset ,vec 4 ,value)
4487 `(aref ,vec 4)))
4488
4489
4490(defmacro ebnf-node-width (vec &optional value)
4491 (if value
4492 `(aset ,vec 5 ,value)
4493 `(aref ,vec 5)))
4494
4495
4496(defmacro ebnf-node-name (vec)
4497 `(aref ,vec 6))
4498
4499
4500(defmacro ebnf-node-list (vec &optional value)
4501 (if value
4502 `(aset ,vec 6 ,value)
4503 `(aref ,vec 6)))
4504
4505
4506(defmacro ebnf-node-default (vec)
4507 `(aref ,vec 7))
4508
4509
4510(defmacro ebnf-node-production (vec &optional value)
4511 (if value
4512 `(aset ,vec 7 ,value)
4513 `(aref ,vec 7)))
4514
4515
4516(defmacro ebnf-node-separator (vec &optional value)
4517 (if value
4518 `(aset ,vec 7 ,value)
4519 `(aref ,vec 7)))
4520
4521
4522(defmacro ebnf-node-action (vec &optional value)
4523 (if value
4524 `(aset ,vec 8 ,value)
4525 `(aref ,vec 8)))
4526
4527
4528(defmacro ebnf-node-generation (node)
4529 `(funcall (ebnf-node-kind ,node) ,node))
4530
4531
4532(defmacro ebnf-max-width (prod)
4533 `(max (ebnf-node-width ,prod)
4534 (+ (* (length (ebnf-node-name ,prod))
4535 ebnf-font-width-P)
4536 ebnf-production-horizontal-space)))
4537
4538\f
4539;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4540;; PostScript generation
4541
4542
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")))
4547 1.0))
4548 (ebnf-total (length ebnf-tree))
4549 (ebnf-nprod 0)
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
4559 (save-excursion
4560 (condition-case data
4561 (progn
4562 (while ebnf-tree
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)
b685181e
GM
4567 horizontal (memq (ebnf-node-action prod)
4568 ebnf-action-list))
984ae001
GM
4569 ;; generate production in EPS buffer
4570 (save-excursion
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
4586 (save-excursion
4587 (set-buffer eps-buffer)
4588 (erase-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))
4593 ;; handler
4594 ((quit error)
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))
4603 (message " ")))
4604
4605
4606;; write and kill temporary buffers
4607(defun ebnf-eps-write-kill-temp (file-list write-p)
4608 (while file-list
4609 (let ((buffer (get-buffer (concat " *" (car file-list) "*"))))
4610 (when buffer
4611 (and write-p
4612 (ebnf-eps-finish-and-write buffer (car file-list)))
4613 (kill-buffer buffer)))
4614 (setq file-list (cdr file-list))))
4615
4616
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)
4620 (while prod-list
4621 (add-to-list file-list-sym (car prod-list))
4622 (save-excursion
4623 (set-buffer (get-buffer-create (concat " *" (car prod-list) "*")))
4624 (goto-char (point-max))
4625 (cond
4626 ;; first production
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))
4632 ;; horizontal
4633 (horizontal
4634 (ebnf-eop-horizontal ebnf-eps-prod-width)
4635 (setq ebnf-eps-max-width (+ ebnf-eps-max-width
4636 ebnf-production-horizontal-space
4637 prod-width)
4638 ebnf-eps-max-height (max ebnf-eps-max-height prod-height)))
4639 ;; vertical
4640 (t
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)
4644 ebnf-eps-max-height
4645 (+ 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))
4650 )
4651 (setq ebnf-eps-prod-width prod-width)
b0de446f 4652 (insert-buffer-substring eps-buffer))
984ae001
GM
4653 (setq prod-list (cdr prod-list))))
4654
4655
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")))
4660 1.0))
4661 ps-zebra-stripes ps-line-number ps-razzle-dazzle
4662 ps-print-hook
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)))
4668
4669
4670(defvar ebnf-tree nil)
4671(defvar ebnf-direction "R")
984ae001
GM
4672
4673
4674(defun ebnf-generate-postscript (from to)
4675 (ebnf-begin-file)
4676 (if ebnf-horizontal-max-height
4677 (ebnf-generate-with-max-height)
4678 (ebnf-generate-without-max-height))
4679 (message " "))
4680
4681
4682(defun ebnf-generate-with-max-height ()
4683 (let ((ebnf-total (length ebnf-tree))
4684 (ebnf-nprod 0)
4685 next-line max-height prod the-width)
4686 (while ebnf-tree
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
4699 (+ the-width
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))))
4710
4711
4712(defun ebnf-generate-without-max-height ()
4713 (let ((ebnf-total (length ebnf-tree))
4714 (ebnf-nprod 0)
4715 max-height prod bef-width cur-width)
4716 (while ebnf-tree
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
4734 (+ cur-width
4735 ebnf-production-horizontal-space))))
4736 (ebnf-eop-vertical max-height)
4737 ;; prepare next line
4738 (ebnf-newline max-height))))
4739
4740
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))
4744 (ebnf-new-page))
4745 (setq ps-width-remaining (- ps-width-remaining
4746 (+ width
4747 ebnf-production-horizontal-space))))
4748
4749
4750(defun ebnf-newline (height)
4751 (and (> height ps-height-remaining)
4752 (ebnf-new-page))
4753 (setq ps-width-remaining ps-print-width
4754 ps-height-remaining (- ps-height-remaining
4755 (+ height
4756 ebnf-production-vertical-space))))
4757
4758
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)
ac4780a1
VJL
4763 (ps-output-string (if ebnf-production-name-p
4764 (ebnf-node-name production)
4765 ""))
984ae001
GM
4766 (ps-output " "
4767 (ebnf-format-float
4768 (ebnf-node-width production)
ac4780a1
VJL
4769 (+ (if ebnf-production-name-p
4770 ebnf-basic-height
4771 0.0)
984ae001
GM
4772 (ebnf-node-entry (ebnf-node-production production))))
4773 " BOP\n")
4774 (ebnf-node-generation (ebnf-node-production production))
4775 (ps-output "EOS\n"))
4776
4777
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))
4782 (nlist 0)
4783 alt-height alt-entry)
4784 (while alt
4785 (ps-output (ebnf-format-float (- entry (ebnf-node-entry (car alt))))
4786 " ")
4787 (setq entry (- entry (ebnf-node-height (car alt)) ebnf-vertical-space)
4788 nlist (1+ nlist)
4789 alt (cdr alt)))
4790 (ps-output (format "%d " nlist)
4791 (ebnf-format-float (ebnf-node-width alternative))
4792 " AT\n")
4793 (setq alt (ebnf-node-list alternative))
4794 (when alt
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"))
4805
4806
4807;; [sequence width-fun dim-fun entry height width list]
4808(defun ebnf-generate-sequence (sequence)
4809 (ps-output "BOS\n")
4810 (let ((seq (ebnf-node-list sequence))
4811 seq-width)
4812 (when seq
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"))
4820
4821
4822;; [terminal width-fun dim-fun entry height width name]
4823(defun ebnf-generate-terminal (terminal)
4824 (ebnf-gen-terminal terminal "T"))
4825
4826
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"))
4830
4831
4832;; [empty width-fun dim-fun entry height width]
4833(defun ebnf-generate-empty (empty)
4834 (ebnf-empty-alternative (ebnf-node-width empty)))
4835
4836
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))
4845 " OP\n")
4846 (ebnf-node-generation the-optional)
4847 (ps-output "EOS\n")))
4848
4849
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)
4855 (if sep
4856 (ebnf-node-entry sep)
4857 0))))
4858 (ps-output (ebnf-format-float entry width)
4859 " OM\n")
4860 (ebnf-node-generation (ebnf-node-list one-or-more))
4861 (ebnf-vertical-movement entry)
4862 (if sep
4863 (let ((ebnf-direction "L"))
4864 (ebnf-node-generation sep))
3ced5caa
VJL
4865 (ebnf-empty-alternative (- width
4866 ebnf-horizontal-space
4867 ebnf-basic-width-extra))))
984ae001
GM
4868 (ps-output "EOS\n"))
4869
4870
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
4878 ebnf-vertical-space
4879 (if node-sep
4880 (- (ebnf-node-height node-sep)
4881 (ebnf-node-entry node-sep))
3ced5caa 4882 ebnf-basic-empty-height))))
984ae001
GM
4883 (ps-output (ebnf-format-float entry
4884 (+ (- (ebnf-node-height node-list)
4885 list-entry)
4886 ebnf-vertical-space)
4887 width)
4888 " ZM\n")
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)))
3ced5caa
VJL
4894 (ebnf-empty-alternative (- width
4895 ebnf-horizontal-space
4896 ebnf-basic-width-extra))))
984ae001
GM
4897 (ps-output "EOS\n"))
4898
4899
4900;; [special width-fun dim-fun entry height width name]
4901(defun ebnf-generate-special (special)
4902 (ebnf-gen-terminal special "SP"))
4903
4904
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)
4910 (ps-output " "
4911 (ebnf-format-float
4912 (ebnf-node-entry repeat)
4913 (ebnf-node-height repeat)
4914 (ebnf-node-width repeat)
4915 (if element
4916 (+ (ebnf-node-width element)
4917 ebnf-space-R ebnf-space-R ebnf-space-R
4918 (* (length times) ebnf-font-width-R))
4919 0.0))
4920 " " ebnf-direction "RP\n")
4921 (and element
4922 (ebnf-node-generation element)))
4923 (ps-output "EOS\n"))
4924
4925
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
4932 width
4933 (ebnf-node-entry except)
4934 (ebnf-node-height except)
4935 (ebnf-node-width except)
4936 (+ width
4937 ebnf-space-E ebnf-space-E ebnf-space-E
4938 ebnf-font-width-E
4939 (if exception
4940 (+ (ebnf-node-width exception) ebnf-space-E)
4941 0.0)))
4942 " " ebnf-direction "EX\n")
4943 (ebnf-node-generation (ebnf-node-list except))
4944 (when exception
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"))
4949
4950
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)
4956 "D\n"
4957 "\n")))
4958
4959\f
4960;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4961;; Internal functions
4962
4963
ac4780a1
VJL
4964(defun ebnf-directory (fun &optional directory)
4965 "Process files in DIRECTORY applying function FUN on each file.
4966
815cbda2 4967If DIRECTORY is nil, use `default-directory'.
ac4780a1 4968
815cbda2 4969Only files in DIRECTORY that match `ebnf-file-suffix-regexp' (which see) are
ac4780a1
VJL
4970processed."
4971 (let ((files (directory-files (or directory default-directory)
4972 t ebnf-file-suffix-regexp)))
4973 (while files
4974 (set-buffer (find-file-noselect (car files)))
4975 (funcall fun)
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)))))
4980
4981
4982(defun ebnf-file (fun file &optional do-not-kill-buffer-when-done)
815cbda2 4983 "Process the named FILE applying function FUN.
ac4780a1
VJL
4984
4985If optional arg DO-NOT-KILL-BUFFER-WHEN-DONE is non-nil, the buffer isn't
4986killed after process termination."
4987 (set-buffer (find-file-noselect file))
4988 (funcall fun)
4989 (or do-not-kill-buffer-when-done
4990 (kill-buffer (current-buffer))))
4991
4992
6a5275dc
GM
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)
4998 (let (str)
4999 (while (<= from to)
5000 (setq str (concat str (char-to-string from))
5001 from (1+ from)))
5002 (concat prefix str)))
5003
5004
984ae001
GM
5005(defvar ebnf-map-name
5006 (let ((map (make-vector 256 ?\_)))
a6d6a87a
GM
5007 (mapc #'(lambda (char)
5008 (aset map char char))
5009 (concat "#$%&+-.0123456789=?@~"
5010 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
5011 "abcdefghijklmnopqrstuvwxyz"))
984ae001
GM
5012 map))
5013
5014
5015(defun ebnf-eps-filename (str)
5016 (let* ((len (length str))
5017 (stri 0)
3ced5caa
VJL
5018 ;; to keep compatibility with Emacs 20 & 21:
5019 ;; DO NOT REPLACE `?\ ' BY `?\s'
5020 (new (make-string len ?\ )))
984ae001
GM
5021 (while (< stri len)
5022 (aset new stri (aref ebnf-map-name (aref str stri)))
5023 (setq stri (1+ stri)))
5024 (concat ebnf-eps-prefix new ".eps")))
5025
5026
5027(defun ebnf-eps-output (&rest args)
5028 (while args
5029 (insert (car args))
5030 (setq args (cdr args))))
5031
5032
5033(defun ebnf-generate-region (from to gen-func)
5034 (run-hooks 'ebnf-hook)
5035 (let ((ebnf-limit (max from to))
ac4780a1 5036 (error-msg "SYNTAX")
984ae001
GM
5037 the-point)
5038 (save-excursion
5039 (save-restriction
5040 (save-match-data
5041 (condition-case data
5042 (let ((tree (ebnf-parse-and-sort (min from to))))
5043 (when gen-func
ac4780a1
VJL
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
984ae001
GM
5053 ;; handler
5054 ((quit error)
5055 (ding)
ac4780a1
VJL
5056 (setq the-point (max (1- (point)) (point-min))
5057 error-msg (concat error-msg ": "
5058 (error-message-string data)
ea946fcc
VJL
5059 ", "
5060 (and (string= error-msg "SYNTAX")
5061 (format "at position %d "
5062 the-point))
5063 (format "in buffer \"%s\"."
5064 (buffer-name)))))))))
984ae001 5065 (cond
ac4780a1
VJL
5066 ;; error occurred
5067 (error-msg
5068 (goto-char the-point)
5069 (if ebnf-stop-on-error
5070 (error error-msg)
29a4e67d 5071 (message "%s" error-msg)))
ac4780a1 5072 ;; generated output OK
984ae001
GM
5073 (gen-func
5074 nil)
ac4780a1 5075 ;; syntax checked OK
984ae001 5076 (t
ab3256ed 5077 (message "EBNF syntactic analysis: NO ERRORS.")))))
984ae001
GM
5078
5079
5080(defun ebnf-parse-and-sort (start)
3ced5caa 5081 (ebnf-log "(ebnf-parse-and-sort %S)" start)
984ae001
GM
5082 (ebnf-begin-job)
5083 (let ((tree (funcall ebnf-parser-func start)))
5084 (if ebnf-sort-production
5085 (progn
5086 (message "Sorting...")
5087 (sort tree
5088 (if (eq ebnf-sort-production 'ascending)
5089 'ebnf-sorter-ascending
5090 'ebnf-sorter-descending)))
5091 (nreverse tree))))
5092
5093
5094(defun ebnf-sorter-ascending (first second)
5095 (string< (ebnf-node-name first)
5096 (ebnf-node-name second)))
5097
5098
5099(defun ebnf-sorter-descending (first second)
5100 (string< (ebnf-node-name second)
5101 (ebnf-node-name first)))
5102
5103
5104(defun ebnf-empty-alternative (width)
5105 (ps-output (ebnf-format-float width) " EA\n"))
5106
5107
5108(defun ebnf-vertical-movement (height)
5109 (ps-output (ebnf-format-float height) " vm\n"))
5110
5111
5112(defun ebnf-horizontal-movement (width)
5113 (ps-output (ebnf-format-float width) " hm\n"))
5114
5115
5116(defun ebnf-entry (height)
5117 (* height ebnf-entry-percentage))
5118
5119
5120(defun ebnf-eop-vertical (height)
5121 (ps-output (ebnf-format-float (+ height ebnf-production-vertical-space))
5122 " EOPV\n\n"))
5123
5124
5125(defun ebnf-eop-horizontal (width)
5126 (ps-output (ebnf-format-float (+ width ebnf-production-horizontal-space))
5127 " EOPH\n\n"))
5128
5129
5130(defun ebnf-new-page ()
5131 (when (< ps-height-remaining ps-print-height)
5132 (run-hooks 'ebnf-page-hook)
5133 (ps-next-page)
5134 (ps-output "\n")))
5135
5136
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))
5144
5145
5146(defconst ebnf-font-name-select
5147 (vector 'normal 'bold 'italic 'bold-italic))
5148
5149
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)
5159 info-list))
5160 (error "Invalid attributes for font %s" name))))
5161
5162
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))))
5168 (if (and size base)
5169 (/ (* (ebnf-font-size font) base)
5170 size)
5171 (error "Invalid font: %s" name))))
5172
5173
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))
5178
5179
ac4780a1
VJL
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)
6ca94f87 5185 (ebnf ebnf-bnf-parser ebnf-bnf-initialize)
6411a60a
VJL
5186 (ebnfx ebnf-ebx-parser ebnf-ebx-initialize)
5187 (dtd ebnf-dtd-parser ebnf-dtd-initialize))
4303661c 5188 "Alist associating EBNF syntax with a parser and an initializer.")
ac4780a1
VJL
5189
5190
984ae001 5191(defun ebnf-begin-job ()
ae6f46f9 5192 (ps-printing-region nil nil nil)
984ae001
GM
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
ac4780a1
VJL
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)))
984ae001
GM
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
5213 '(nil keep-line)
5214 '(keep-line))
5215 ebnf-settings nil
5216 ebnf-fonts-required nil
5217 ebnf-action nil
5218 ebnf-default-p nil
5219 ebnf-eps-context nil
3ced5caa 5220 ebnf-eps-file-alist nil
984ae001 5221 ebnf-eps-production-list nil
3ced5caa
VJL
5222 ebnf-eps-header-comment nil
5223 ebnf-eps-footer-comment nil
984ae001
GM
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)))
3ced5caa
VJL
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
984ae001
GM
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))
3ced5caa
VJL
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))
984ae001
GM
5271
5272
5273(defsubst ebnf-shape-value (sym alist)
5274 (or (cdr (assq sym alist)) 0))
5275
5276
5277(defsubst ebnf-boolean (value)
5278 (if value "true" "false"))
5279
5280
5281(defun ebnf-begin-file ()
5282 (ps-flush-output)
5283 (save-excursion
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))
5289 t))
5290 (progn
5291 ;; adjust creator comment
5292 (end-of-line)
3ced5caa 5293 ;; (backward-char)
984ae001
GM
5294 (insert " & ebnf2ps v" ebnf-version)
5295 ;; insert ebnf settings & engine
5296 (goto-char (point-max))
0b5ecd6d 5297 (search-backward "\n%%EndProlog\n")
984ae001
GM
5298 (ebnf-insert-ebnf-prologue)
5299 (ps-output "\n")))))
5300
5301
5302(defun ebnf-eps-finish-and-write (buffer filename)
1ede99a8
VJL
5303 (when (buffer-modified-p buffer)
5304 (save-excursion
5305 (set-buffer buffer)
3ced5caa 5306 (ebnf-eps-header-footer-set filename)
1ede99a8
VJL
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)
5309 ebnf-eps-max-height
5310 (+ ebnf-eps-upper-y
5311 ebnf-production-vertical-space
5312 ebnf-eps-max-height)))
5313 ;; prologue
5314 (goto-char (point-min))
5315 (insert
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
5329 ebnf-terminal-font
5330 ebnf-non-terminal-font
5331 ebnf-special-font
5332 ebnf-except-font
3ced5caa
VJL
5333 ebnf-repeat-font
5334 ebnf-eps-header-font
5335 ebnf-eps-footer-font)))
1ede99a8
VJL
5336 "\n%%+ font ")))
5337 "\n%%Pages: 0\n%%EndComments\n\n%%BeginProlog\n"
5338 ebnf-eps-prologue)
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")
5344 ;; epilogue
5345 (goto-char (point-max))
5346 (insert ebnf-eps-end)
5347 ;; write file
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))))
984ae001
GM
5353
5354
5355(defun ebnf-insert-ebnf-prologue ()
5356 (insert
5357 (or ebnf-settings
5358 (setq ebnf-settings
5359 (concat
5360 "\n\n% === begin EBNF settings\n\n"
3ced5caa
VJL
5361 (format "/Header %s def\n"
5362 (or ebnf-eps-header-comment "()"))
5363 (format "/Footer %s def\n"
5364 (or ebnf-eps-footer-comment "()"))
5365 ;; header
5366 (format "/ShowHeader %s def\n"
5367 (ebnf-boolean
5368 (ebnf-eps-header-footer-p ebnf-eps-header)))
5369 (format "/fH %s /%s DefFont\n"
5370 (ebnf-format-float
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)
5375 "Black")
5376 (ebnf-format-color "/BackgroundH %s def %% %s\n"
5377 (ebnf-font-background ebnf-eps-header-font)
5378 "White")
5379 (format "/EffectH %d def\n"
5380 (ebnf-font-attributes ebnf-eps-header-font))
5381 ;; footer
5382 (format "/ShowFooter %s def\n"
5383 (ebnf-boolean
5384 (ebnf-eps-header-footer-p ebnf-eps-footer)))
5385 (format "/fF %s /%s DefFont\n"
5386 (ebnf-format-float
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)
5391 "Black")
5392 (ebnf-format-color "/BackgroundF %s def %% %s\n"
5393 (ebnf-font-background ebnf-eps-footer-font)
5394 "White")
5395 (format "/EffectF %d def\n"
5396 (ebnf-font-attributes ebnf-eps-footer-font))
984ae001
GM
5397 ;; production
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)
5403 "Black")
5404 (ebnf-format-color "/BackgroundP %s def %% %s\n"
5405 (ebnf-font-background ebnf-production-font)
5406 "White")
5407 (format "/EffectP %d def\n"
5408 (ebnf-font-attributes ebnf-production-font))
5409 ;; terminal
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)
5415 "Black")
5416 (ebnf-format-color "/BackgroundT %s def %% %s\n"
5417 (ebnf-font-background ebnf-terminal-font)
5418 "White")
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
5425 "Black")
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))
5431 ;; non-terminal
5432 (format "/fNT %s /%s DefFont\n"
5433 (ebnf-format-float
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)
5438 "Black")
5439 (ebnf-format-color "/BackgroundNT %s def %% %s\n"
5440 (ebnf-font-background ebnf-non-terminal-font)
5441 "White")
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
5448 "Black")
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))
5454 ;; special
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)
5460 "Black")
5461 (ebnf-format-color "/BackgroundS %s def %% %s\n"
5462 (ebnf-font-background ebnf-special-font)
5463 "Gray95")
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
5470 "Black")
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))
5476 ;; except
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)
5482 "Black")
5483 (ebnf-format-color "/BackgroundE %s def %% %s\n"
5484 (ebnf-font-background ebnf-except-font)
5485 "Gray90")
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
5492 "Black")
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))
5498 ;; repeat
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)
5504 "Black")
5505 (ebnf-format-color "/BackgroundR %s def %% %s\n"
5506 (ebnf-font-background ebnf-repeat-font)
5507 "Gray85")
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
5514 "Black")
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))
5520 ;; miscellaneous
ed0aa46c
VJL
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))
984ae001
GM
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"
5530 ebnf-line-color
5531 "Black")
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"
bf061ba6
GM
5539 (let ((arrow (eval ebnf-user-arrow)))
5540 (if (stringp arrow)
5541 arrow
5542 "")))
984ae001
GM
5543 "\n% === end EBNF settings\n\n"
5544 (and ebnf-debug-ps ebnf-debug))))
5545 ebnf-prologue))
5546
984ae001
GM
5547\f
5548;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5549;; Adjusting dimensions
5550
5551
5552(defun ebnf-dimensions (tree)
3ced5caa 5553 (ebnf-log "(ebnf-dimensions tree)")
984ae001
GM
5554 (let ((ebnf-total (length tree))
5555 (ebnf-nprod 0))
a6d6a87a 5556 (mapc 'ebnf-production-dimension tree))
984ae001
GM
5557 tree)
5558
5559
5560;; [empty width-fun dim-fun entry height width]
5561;;(defun ebnf-empty-dimension (empty)
5562;; )
5563
5564
5565;; [production width-fun dim-fun entry height width name production action]
5566(defun ebnf-production-dimension (production)
3ced5caa 5567 (ebnf-log "(ebnf-production-dimension production)")
984ae001
GM
5568 (ebnf-message-info "Calculating dimensions")
5569 (ebnf-node-dimension-func (ebnf-node-production production))
5570 (let* ((prod (ebnf-node-production production))
ac4780a1
VJL
5571 (height (+ (if ebnf-production-name-p
5572 ebnf-font-height-P
5573 0.0)
5574 ebnf-line-width ebnf-line-width
984ae001
GM
5575 ebnf-basic-height
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)
ac4780a1 5580 ebnf-line-width
3ced5caa
VJL
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)))
984ae001
GM
5587
5588
5589;; [terminal width-fun dim-fun entry height width name]
5590(defun ebnf-terminal-dimension (terminal)
3ced5caa 5591 (ebnf-log "(ebnf-terminal-dimension terminal)")
984ae001
GM
5592 (ebnf-terminal-dimension1 terminal
5593 ebnf-font-height-T
5594 ebnf-font-width-T
5595 ebnf-space-T))
5596
5597
5598;; [non-terminal width-fun dim-fun entry height width name]
5599(defun ebnf-non-terminal-dimension (non-terminal)
3ced5caa 5600 (ebnf-log "(ebnf-non-terminal-dimension non-terminal)")
984ae001
GM
5601 (ebnf-terminal-dimension1 non-terminal
5602 ebnf-font-height-NT
5603 ebnf-font-width-NT
5604 ebnf-space-NT))
5605
5606
5607;; [special width-fun dim-fun entry height width name]
5608(defun ebnf-special-dimension (special)
3ced5caa 5609 (ebnf-log "(ebnf-special-dimension special)")
984ae001
GM
5610 (ebnf-terminal-dimension1 special
5611 ebnf-font-height-S
5612 ebnf-font-width-S
5613 ebnf-space-S))
5614
5615
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)
3ced5caa
VJL
5621 (ebnf-node-width node (+ ebnf-basic-width
5622 ebnf-arrow-extra-width
5623 space
984ae001 5624 (* len font-width)
3ced5caa
VJL
5625 space
5626 ebnf-basic-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)))
984ae001
GM
5631
5632
5633(defconst ebnf-null-vector (vector t t t 0.0 0.0 0.0))
5634
5635
5636;; [repeat width-fun dim-fun entry height width times element]
5637(defun ebnf-repeat-dimension (repeat)
3ced5caa 5638 (ebnf-log "(ebnf-repeat-dimension repeat)")
984ae001
GM
5639 (let ((times (ebnf-node-name repeat))
5640 (element (ebnf-node-separator repeat)))
5641 (if element
5642 (ebnf-node-dimension-func element)
5643 (setq element ebnf-null-vector))
5644 (ebnf-node-entry repeat (+ (ebnf-node-entry element)
5645 ebnf-space-R))
5646 (ebnf-node-height repeat (+ (max (ebnf-node-height element)
5647 ebnf-font-height-S)
5648 ebnf-space-R ebnf-space-R))
5649 (ebnf-node-width repeat (+ (ebnf-node-width element)
ed0aa46c 5650 ebnf-arrow-extra-width
984ae001
GM
5651 ebnf-space-R ebnf-space-R ebnf-space-R
5652 ebnf-horizontal-space
3ced5caa
VJL
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)))
984ae001
GM
5657
5658
5659;; [except width-fun dim-fun entry height width element element]
5660(defun ebnf-except-dimension (except)
3ced5caa 5661 (ebnf-log "(ebnf-except-dimension except)")
984ae001
GM
5662 (let ((factor (ebnf-node-list except))
5663 (element (ebnf-node-separator except)))
5664 (ebnf-node-dimension-func factor)
5665 (if element
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))
5670 ebnf-space-E))
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)
ed0aa46c 5676 ebnf-arrow-extra-width
984ae001
GM
5677 ebnf-space-E ebnf-space-E
5678 ebnf-space-E ebnf-space-E
5679 ebnf-font-width-E
3ced5caa
VJL
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)))
984ae001
GM
5684
5685
5686;; [alternative width-fun dim-fun entry height width list]
5687(defun ebnf-alternative-dimension (alternative)
3ced5caa 5688 (ebnf-log "(ebnf-alternative-dimension alternative)")
984ae001
GM
5689 (let ((body (ebnf-node-list alternative))
5690 (lis (ebnf-node-list alternative)))
5691 (while lis
5692 (ebnf-node-dimension-func (car lis))
5693 (setq lis (cdr lis)))
5694 (let ((height 0.0)
5695 (width 0.0)
5696 (alt body)
5697 (tail (car (last body)))
5698 (entry (ebnf-node-entry (car body)))
5699 node)
5700 (while alt
5701 (setq node (car alt)
5702 alt (cdr 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
5708 (ebnf-entry
5709 (- height entry
5710 (- (ebnf-node-height tail)
5711 (ebnf-node-entry tail))))))
5712 (ebnf-node-height alternative height)
3ced5caa
VJL
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)))
984ae001
GM
5720
5721
5722;; [optional width-fun dim-fun entry height width element]
5723(defun ebnf-optional-dimension (optional)
3ced5caa 5724 (ebnf-log "(ebnf-optional-dimension optional)")
984ae001
GM
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)
3ced5caa
VJL
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)))
984ae001
GM
5735
5736
5737;; [one-or-more width-fun dim-fun entry height width element separator]
5738(defun ebnf-one-or-more-dimension (or-more)
3ced5caa 5739 (ebnf-log "(ebnf-one-or-more-dimension or-more)")
984ae001
GM
5740 (let ((list-part (ebnf-node-list or-more))
5741 (sep-part (ebnf-node-separator or-more)))
5742 (ebnf-node-dimension-func list-part)
5743 (and sep-part
5744 (ebnf-node-dimension-func sep-part))
5745 (let ((height (+ (if sep-part
5746 (ebnf-node-height sep-part)
3ced5caa 5747 ebnf-basic-empty-height)
984ae001
GM
5748 ebnf-vertical-space
5749 (ebnf-node-height list-part)))
5750 (width (max (if sep-part
5751 (ebnf-node-width sep-part)
5752 0.0)
5753 (ebnf-node-width list-part))))
5754 (when sep-part
5755 (ebnf-adjust-width list-part width)
5756 (ebnf-adjust-width sep-part width))
3ced5caa
VJL
5757 (ebnf-node-entry or-more (+ (- height
5758 (ebnf-node-height list-part))
984ae001
GM
5759 (ebnf-node-entry list-part)))
5760 (ebnf-node-height or-more height)
3ced5caa
VJL
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)))
984ae001
GM
5767
5768
5769;; [zero-or-more width-fun dim-fun entry height width element separator]
5770(defun ebnf-zero-or-more-dimension (or-more)
3ced5caa 5771 (ebnf-log "(ebnf-zero-or-more-dimension or-more)")
984ae001
GM
5772 (let ((list-part (ebnf-node-list or-more))
5773 (sep-part (ebnf-node-separator or-more)))
5774 (ebnf-node-dimension-func list-part)
5775 (and sep-part
5776 (ebnf-node-dimension-func sep-part))
5777 (let ((height (+ (if sep-part
5778 (ebnf-node-height sep-part)
3ced5caa 5779 ebnf-basic-empty-height)
984ae001
GM
5780 ebnf-vertical-space
5781 (ebnf-node-height list-part)
5782 ebnf-vertical-space))
5783 (width (max (if sep-part
5784 (ebnf-node-width sep-part)
5785 0.0)
5786 (ebnf-node-width list-part))))
5787 (when sep-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)
3ced5caa
VJL
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)))
984ae001
GM
5798
5799
5800;; [sequence width-fun dim-fun entry height width list]
5801(defun ebnf-sequence-dimension (sequence)
3ced5caa 5802 (ebnf-log "(ebnf-sequence-dimension sequence)")
984ae001
GM
5803 (let ((above 0.0)
5804 (below 0.0)
5805 (width 0.0)
5806 (lis (ebnf-node-list sequence))
5807 entry node)
5808 (while lis
5809 (setq node (car lis)
5810 lis (cdr 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))
3ced5caa
VJL
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)))
984ae001
GM
5822
5823\f
5824;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5825;; Adjusting width
5826
5827
5828(defun ebnf-adjust-width (node width)
5829 (cond
5830 ((listp node)
5831 (prog1
5832 node
5833 (while node
5834 (setcar node (ebnf-adjust-width (car node) width))
5835 (setq node (cdr node)))))
5836 ((vectorp node)
5837 (cond
5838 ;; nothing to be done
5839 ((= width (ebnf-node-width node))
5840 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))
5847 ;; centralize terms
5848 (t
5849 (ebnf-node-width-func node width)
5850 (ebnf-node-width node width)
5851 node)
5852 ))
5853 (t
5854 node)
5855 ))
5856
5857
5858(defun ebnf-adjust-empty (node width last-p)
5859 (if (eq (ebnf-node-kind node) 'ebnf-generate-empty)
5860 (progn
5861 (ebnf-node-width node width)
5862 node)
5863 (let ((empty (ebnf-make-empty (- width (ebnf-node-width node)))))
5864 (ebnf-make-dup-sequence node
5865 (if last-p
5866 (list empty node)
5867 (list node empty))))))
5868
5869
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)
5877;; )
5878
5879
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)))
5885
5886
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]
ac4780a1 5889(defun ebnf-element-width (or-more width)
984ae001
GM
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)
5894 width))
5895 (ebnf-node-separator or-more
5896 (ebnf-justify-list or-more
5897 (ebnf-node-separator or-more)
5898 width)))
5899
5900
5901;; [sequence width-fun dim-fun entry height width list]
5902(defun ebnf-sequence-width (sequence width)
5903 (ebnf-node-list sequence
b685181e
GM
5904 (ebnf-justify-list sequence
5905 (ebnf-node-list sequence)
5906 width)))
984ae001
GM
5907
5908
5909(defun ebnf-justify-list (node seq width)
5910 (let ((seq-width (ebnf-node-width node)))
5911 (if (= width seq-width)
5912 seq
5913 (cond
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))
ac4780a1
VJL
5920 ;; centralize terms -- element
5921 ((vectorp seq)
5922 (ebnf-adjust-width seq width))
5923 ;; centralize terms -- list
984ae001
GM
5924 (t
5925 (let ((the-width (/ (- width seq-width) (length seq)))
5926 (lis seq))
5927 (while lis
5928 (ebnf-adjust-width (car lis)
5929 (+ (ebnf-node-width (car lis))
5930 the-width))
5931 (setq lis (cdr lis)))
5932 seq))
5933 ))))
5934
5935
5936(defun ebnf-justify (node seq seq-width width last-p)
5937 (let ((term (car (if last-p (last seq) seq))))
5938 (cond
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)))
5943 seq)
5944 ;; insert empty at end ==> left justify
5945 (last-p
5946 (nconc seq
5947 (list (ebnf-make-empty (- width seq-width)))))
5948 ;; insert empty at beginning ==> right justify
5949 (t
5950 (cons (ebnf-make-empty (- width seq-width))
5951 seq))
5952 )))
5953
5954\f
5955;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5956;; Functions used by parsers
5957
5958
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)
3ced5caa
VJL
5963 (setq ebnf-eps-context (cons filename ebnf-eps-context)))
5964 (ebnf-eps-header-footer-file filename)))
984ae001
GM
5965
5966
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))))
5972
5973
5974(defun ebnf-eps-add-production (header)
3ced5caa
VJL
5975 (when ebnf-eps-executing
5976 (if ebnf-eps-context
5977 (let ((prod (assoc header ebnf-eps-production-list)))
5978 (if prod
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)))))
984ae001
GM
5985
5986
5987(defun ebnf-dup-list (old)
5988 (let (new)
5989 (while old
5990 (setq new (cons (car old) new)
5991 old (cdr old)))
5992 (nreverse new)))
5993
5994
5995(defun ebnf-buffer-substring (chars)
5996 (buffer-substring-no-properties
5997 (point)
5998 (progn
5999 (skip-chars-forward chars ebnf-limit)
6000 (point))))
6001
6002
6a5275dc
GM
6003;; replace the range "\240-\377" (see `ebnf-range-regexp').
6004(defconst ebnf-8-bit-chars (ebnf-range-regexp "" ?\240 ?\377))
5268b442
GM
6005
6006
984ae001
GM
6007(defun ebnf-string (chars eos-char kind)
6008 (forward-char)
6009 (buffer-substring-no-properties
6010 (point)
6011 (progn
5268b442
GM
6012 ;;(skip-chars-forward (concat chars "\240-\377") ebnf-limit)
6013 (skip-chars-forward (concat chars ebnf-8-bit-chars) ebnf-limit)
984ae001 6014 (if (or (eobp) (/= (following-char) eos-char))
eac9c0ef 6015 (error "Invalid %s: missing `%c'" kind eos-char)
984ae001
GM
6016 (forward-char)
6017 (1- (point))))))
6018
6019
6020(defun ebnf-get-string ()
6021 (forward-char)
6022 (buffer-substring-no-properties (point) (ebnf-end-of-string)))
6023
6024
6025(defun ebnf-end-of-string ()
6026 (let ((n 1))
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) ?\")
6032 (1- (point))
e8af40ee 6033 (error "Missing `\"'")))
984ae001
GM
6034
6035
6036(defun ebnf-trim-right (str)
6037 (let* ((len (1- (length str)))
6038 (index len))
3ced5caa
VJL
6039 ;; to keep compatibility with Emacs 20 & 21:
6040 ;; DO NOT REPLACE `?\ ' BY `?\s'
6041 (while (and (> index 0) (= (aref str index) ?\ ))
984ae001
GM
6042 (setq index (1- index)))
6043 (if (= index len)
6044 str
6045 (substring str 0 (1+ index)))))
6046
6047\f
6048;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6049;; Vector creation
6050
6051
6052(defun ebnf-make-empty (&optional width)
3ced5caa
VJL
6053 (vector 'ebnf-generate-empty ; 0 generator
6054 'ignore ; 1 width fun
6055 'ignore ; 2 dimension fun
6056 0.0 ; 3 entry
6057 0.0 ; 4 height
6058 (or width ebnf-horizontal-space))) ; 5 width
984ae001
GM
6059
6060
6061(defun ebnf-make-terminal (name)
6062 (ebnf-make-terminal1 name
6063 'ebnf-generate-terminal
6064 'ebnf-terminal-dimension))
6065
6066
6067(defun ebnf-make-non-terminal (name)
6068 (ebnf-make-terminal1 name
6069 'ebnf-generate-non-terminal
6070 'ebnf-non-terminal-dimension))
6071
6072
6073(defun ebnf-make-special (name)
6074 (ebnf-make-terminal1 name
6075 'ebnf-generate-special
6076 'ebnf-special-dimension))
6077
6078
6079(defun ebnf-make-terminal1 (name gen-func dim-func)
3ced5caa
VJL
6080 (vector gen-func ; 0 generatore
6081 'ignore ; 1 width fun
6082 dim-func ; 2 dimension fun
6083 0.0 ; 3 entry
6084 0.0 ; 4 height
6085 0.0 ; 5 width
6086 (let ((len (length name))) ; 6 name
ac4780a1
VJL
6087 (cond ((> len 3) name)
6088 ((= len 3) (concat name " "))
6089 ((= len 2) (concat " " name " "))
6090 ((= len 1) (concat " " name " "))
6091 (t " ")))
3ced5caa 6092 ebnf-default-p)) ; 7 is default?
984ae001
GM
6093
6094
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
6098 list-part
6099 sep-part))
6100
6101
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
6105 list-part
6106 sep-part))
6107
6108
6109(defun ebnf-make-or-more1 (gen-func dim-func list-part sep-part)
3ced5caa
VJL
6110 (vector gen-func ; 0 generator
6111 'ebnf-element-width ; 1 width fun
6112 dim-func ; 2 dimension fun
6113 0.0 ; 3 entry
6114 0.0 ; 4 height
6115 0.0 ; 5 width
6116 (if (listp list-part) ; 6 element
984ae001
GM
6117 (ebnf-make-sequence list-part)
6118 list-part)
3ced5caa 6119 (if (and sep-part (listp sep-part)) ; 7 separator
984ae001
GM
6120 (ebnf-make-sequence sep-part)
6121 sep-part)))
6122
6123
6124(defun ebnf-make-production (name prod action)
3ced5caa
VJL
6125 (vector 'ebnf-generate-production ; 0 generator
6126 'ignore ; 1 width fun
6127 'ebnf-production-dimension ; 2 dimension fun
6128 0.0 ; 3 entry
6129 0.0 ; 4 height
6130 0.0 ; 5 width
6131 name ; 6 production name
6132 prod ; 7 production body
6133 action)) ; 8 production action
984ae001
GM
6134
6135
6136(defun ebnf-make-alternative (body)
3ced5caa
VJL
6137 (vector 'ebnf-generate-alternative ; 0 generator
6138 'ebnf-alternative-width ; 1 width fun
6139 'ebnf-alternative-dimension ; 2 dimension fun
6140 0.0 ; 3 entry
6141 0.0 ; 4 height
6142 0.0 ; 5 width
6143 body)) ; 6 alternative list
984ae001
GM
6144
6145
6146(defun ebnf-make-optional (body)
3ced5caa
VJL
6147 (vector 'ebnf-generate-optional ; 0 generator
6148 'ebnf-alternative-width ; 1 width fun
6149 'ebnf-optional-dimension ; 2 dimension fun
6150 0.0 ; 3 entry
6151 0.0 ; 4 height
6152 0.0 ; 5 width
6153 body)) ; 6 optional element
984ae001
GM
6154
6155
6156(defun ebnf-make-except (factor exception)
3ced5caa
VJL
6157 (vector 'ebnf-generate-except ; 0 generator
6158 'ignore ; 1 width fun
6159 'ebnf-except-dimension ; 2 dimension fun
6160 0.0 ; 3 entry
6161 0.0 ; 4 height
6162 0.0 ; 5 width
6163 factor ; 6 base element
6164 exception)) ; 7 exception element
984ae001
GM
6165
6166
ac4780a1 6167(defun ebnf-make-repeat (times primary &optional upper)
3ced5caa
VJL
6168 (vector 'ebnf-generate-repeat ; 0 generator
6169 'ignore ; 1 width fun
6170 'ebnf-repeat-dimension ; 2 dimension fun
6171 0.0 ; 3 entry
6172 0.0 ; 4 height
6173 0.0 ; 5 width
6174 ; 6 times
ac4780a1
VJL
6175 (cond ((and times upper) ; L * U, L * L
6176 (if (string= times upper)
6177 (if (string= times "")
6178 " * "
6179 times)
6180 (concat times " * " upper)))
6181 (times ; L *
6182 (concat times " *"))
6183 (upper ; * U
6184 (concat "* " upper))
6185 (t ; *
6186 " * "))
3ced5caa 6187 primary)) ; 7 element
984ae001
GM
6188
6189
6190(defun ebnf-make-sequence (seq)
3ced5caa
VJL
6191 (vector 'ebnf-generate-sequence ; 0 generator
6192 'ebnf-sequence-width ; 1 width fun
6193 'ebnf-sequence-dimension ; 2 dimension fun
6194 0.0 ; 3 entry
6195 0.0 ; 4 height
6196 0.0 ; 5 width
6197 seq)) ; 6 sequence
984ae001
GM
6198
6199
6200(defun ebnf-make-dup-sequence (node seq)
3ced5caa
VJL
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
6207 seq)) ; 6 sequence
984ae001
GM
6208
6209\f
6210;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6211;; Optimizers used by parsers
6212
6213
6214(defun ebnf-token-except (element exception)
6215 (cons (prog1
6216 (car exception)
6217 (setq exception (cdr exception)))
6218 (and element ; EMPTY - A ==> EMPTY
6219 (let ((kind (ebnf-node-kind element)))
6220 (cond
6221 ;; [ A ]- ==> A
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)
6230 element)
6231 ;; ( A | EMPTY )- ==> A
6232 ;; ( A | B | EMPTY )- ==> A | B
6233 ((and (null exception)
6234 (eq kind 'ebnf-generate-alternative)
b685181e
GM
6235 (eq (ebnf-node-kind
6236 (car (last (ebnf-node-list element))))
984ae001
GM
6237 'ebnf-generate-empty))
6238 (let ((elt (ebnf-node-list element))
6239 bef)
6240 (while (cdr elt)
6241 (setq bef elt
6242 elt (cdr elt)))
6243 (if (null bef)
6244 ;; this should not happen!!?!
6245 (setq element (ebnf-make-empty
6246 (ebnf-node-width element)))
6247 (setcdr bef nil)
6248 (setq elt (ebnf-node-list element))
6249 (and (= (length elt) 1)
6250 (setq element (car elt))))
6251 element))
6252 ;; A - B
6253 (t
6254 (ebnf-make-except element exception))
6255 )))))
6256
6257
ac4780a1 6258(defun ebnf-token-repeat (times repeat &optional upper)
984ae001
GM
6259 (if (null (cdr repeat))
6260 ;; n * EMPTY ==> EMPTY
6261 repeat
6262 ;; n * term
6263 (cons (car repeat)
ac4780a1 6264 (ebnf-make-repeat times (cdr repeat) upper))))
984ae001
GM
6265
6266
6267(defun ebnf-token-optional (body)
6268 (let ((kind (ebnf-node-kind body)))
6269 (cond
6270 ;; [ EMPTY ] ==> EMPTY
6271 ((eq kind 'ebnf-generate-empty)
6272 nil)
6273 ;; [ { A }* ] ==> { A }*
6274 ((eq kind 'ebnf-generate-zero-or-more)
6275 body)
6276 ;; [ { A }+ ] ==> { A }*
6277 ((eq kind 'ebnf-generate-one-or-more)
6278 (ebnf-node-kind body 'ebnf-generate-zero-or-more)
6279 body)
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))))
6284 body)
6285 ;; [ A ]
6286 (t
6287 (ebnf-make-optional body))
6288 )))
6289
6290
6291(defun ebnf-token-alternative (body sequence)
6292 (if (null body)
6293 (if (cdr sequence)
3ced5caa 6294 ;; no alternative
984ae001 6295 sequence
3ced5caa
VJL
6296 ;; empty element
6297 (cons (car sequence) ; token
984ae001 6298 (ebnf-make-empty)))
3ced5caa 6299 (cons (car sequence) ; token
984ae001
GM
6300 (let ((seq (cdr sequence)))
6301 (if (and (= (length body) 1) (null seq))
3ced5caa 6302 ;; alternative with one element
984ae001 6303 (car body)
3ced5caa 6304 ;; a real alternative
984ae001
GM
6305 (ebnf-make-alternative (nreverse (if seq
6306 (cons seq body)
6307 body))))))))
6308
6411a60a
VJL
6309
6310(defun ebnf-token-sequence (sequence)
6311 (cond
6312 ;; null sequence
6313 ((null sequence)
6314 (ebnf-make-empty))
6315 ;; sequence with only one element
6316 ((= (length sequence) 1)
6317 (car sequence))
6318 ;; a real sequence
6319 (t
6320 (ebnf-make-sequence (nreverse sequence)))
6321 ))
6322
984ae001
GM
6323\f
6324;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6325;; Variables used by parsers
6326
6327
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)
6411a60a 6333 (aset table ?^ 'form-feed)
984ae001
GM
6334 table)
6335 "Vector used to map characters to a special comment token.")
6336
6337\f
3ced5caa
VJL
6338;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6339;; Log message
6340
6341
6342(defun ebnf-log-header (format-str &rest args)
6343 (when ebnf-log
6344 (apply
6345 'ebnf-log
6346 (concat
6347 "\n\n===============================================================\n\n"
6348 format-str)
6349 args)))
6350
6351
6352(defun ebnf-log (format-str &rest args)
6353 (when ebnf-log
6354 (save-excursion
6355 (set-buffer (get-buffer-create "*Ebnf2ps Log*"))
6356 (goto-char (point-max))
6357 (insert (apply 'format format-str args) "\n"))))
6358
6359\f
984ae001
GM
6360;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6361;; To make this file smaller, some commands go in a separate file.
6362;; But autoload them here to make the separation invisible.
6363
ac4780a1
VJL
6364(autoload 'ebnf-abn-parser "ebnf-abn"
6365 "ABNF parser.")
6366
6367(autoload 'ebnf-abn-initialize "ebnf-abn"
6368 "Initialize ABNF token table.")
6369
984ae001
GM
6370(autoload 'ebnf-bnf-parser "ebnf-bnf"
6371 "EBNF parser.")
6372
6373(autoload 'ebnf-bnf-initialize "ebnf-bnf"
6374 "Initialize EBNF token table.")
6375
6376(autoload 'ebnf-iso-parser "ebnf-iso"
6377 "ISO EBNF parser.")
6378
6379(autoload 'ebnf-iso-initialize "ebnf-iso"
6380 "Initialize ISO EBNF token table.")
6381
6382(autoload 'ebnf-yac-parser "ebnf-yac"
6383 "Yacc/Bison parser.")
6384
6385(autoload 'ebnf-yac-initialize "ebnf-yac"
6386 "Initializations for Yacc/Bison parser.")
6387
6ca94f87
VJL
6388(autoload 'ebnf-ebx-parser "ebnf-ebx"
6389 "EBNFX parser.")
6390
6391(autoload 'ebnf-ebx-initialize "ebnf-ebx"
6392 "Initializations for EBNFX parser.")
6393
6411a60a
VJL
6394(autoload 'ebnf-dtd-parser "ebnf-dtd"
6395 "DTD parser.")
984ae001 6396
6411a60a
VJL
6397(autoload 'ebnf-dtd-initialize "ebnf-dtd"
6398 "Initializations for DTD parser.")
984ae001
GM
6399
6400\f
6401;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6402
6403
6404(provide 'ebnf2ps)
6405
cbee283d 6406;; arch-tag: 148bc8af-5398-468b-b922-eeb7afef3e4f
984ae001 6407;;; ebnf2ps.el ends here