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