* hl-line.el (hl-line): New face.
[bpt/emacs.git] / lisp / progmodes / ebnf2ps.el
index d13ed80..bce4381 100644 (file)
@@ -1,13 +1,13 @@
 ;;; ebnf2ps.el --- translate an EBNF to a syntactic chart on PostScript
 
-;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
+;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
 ;; Free Software Foundation, Inc.
 
 ;; Author: Vinicius Jose Latorre <viniciusjl@ig.com.br>
 ;; Maintainer: Vinicius Jose Latorre <viniciusjl@ig.com.br>
-;; Time-stamp: <2004/02/25 20:17:43 vinicius>
+;; Time-stamp: <2005-09-18 07:27:20 deego>
 ;; Keywords: wp, ebnf, PostScript
-;; Version: 4.0
+;; Version: 4.2
 ;; X-URL: http://www.cpqd.com.br/~vinicius/emacs/
 
 ;; This file is part of GNU Emacs.
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
-(defconst ebnf-version "4.0"
-  "ebnf2ps.el, v 4.0 <2004/02/24 vinicius>
+(defconst ebnf-version "4.2"
+  "ebnf2ps.el, v 4.2 <2004/04/04 vinicius>
 
 Vinicius's last change version.  When reporting bugs, please also
 report the version of Emacs, if any, that ebnf2ps was running with.
@@ -70,8 +70,8 @@ Please send all bug fixes and enhancements to
 ;; Using ebnf2ps
 ;; -------------
 ;;
-;; ebnf2ps provides six commands for generating PostScript syntactic chart
-;; images of Emacs buffers:
+;; ebnf2ps provides the following commands for generating PostScript syntactic
+;; chart images of Emacs buffers:
 ;;
 ;;     ebnf-print-directory
 ;;     ebnf-print-file
@@ -177,9 +177,36 @@ Please send all bug fixes and enhancements to
 ;;   (global-set-key '(control f22) 'ebnf-despool)
 ;;
 ;;
+;; Invoking Ebnf2ps in Batch
+;; -------------------------
+;;
+;; It's possible also to run ebnf2ps in batch, this is useful when, for
+;; example, you have a directory with a lot of files containing the EBNF to be
+;; translated to PostScript.
+;;
+;; To run ebnf2ps in batch type, for example:
+;;
+;;    emacs -batch -l setup-ebnf2ps.el -f ebnf-eps-directory
+;;
+;; Where setup-ebnf2ps.el should be a file containing:
+;;
+;;    ;; set load-path if ebnf2ps isn't installed in your Emacs environment
+;;    (setq load-path (append (list "/dir/of/ebnf2ps") load-path))
+;;    (require 'ebnf2ps)
+;;    ;; insert here your ebnf2ps settings
+;;    (setq ebnf-terminal-shape 'bevel)
+;;    ;; etc.
+;;
+;;
 ;; EBNF Syntax
 ;; -----------
 ;;
+;; BNF (Backus Naur Form) notation is defined like languages, and like
+;; languages there are rules about name formation and syntax.  In this section
+;; it's defined a BNF syntax that it's called simply EBNF (Extended BNF).
+;; ebnf2ps package also deal with other BNF notation.  Please, see the variable
+;; `ebnf-syntax' documentation below in this section.
+;;
 ;; The current EBNF that ebnf2ps accepts has the following constructions:
 ;;
 ;;    ;                        comment (until end of line)
@@ -193,7 +220,10 @@ Please send all bug fixes and enhancements to
 ;;    C D              sequence (C occurs before D)
 ;;    C | D            alternative (C or D occurs)
 ;;    A - B            exception (A excluding B, B without any non-terminal)
-;;    n * A            repetition (A repeats n (integer) times)
+;;    n * A            repetition (A repeats at least n (integer) times)
+;;    n * n A          repetition (A repeats exactly n (integer) times)
+;;    n * m A          repetition (A repeats at least n (integer) and at most
+;;                     m (integer) times)
 ;;    (C)              group (expression C is grouped together)
 ;;    [C]              optional (C may or not occurs)
 ;;    C+               one or more occurrences of C
@@ -217,7 +247,7 @@ Please send all bug fixes and enhancements to
 ;;
 ;;    exception = repeat [ "-" repeat].         ;; exception
 ;;
-;;    repeat = [ integer "*" ] term.            ;; repetition
+;;    repeat = [ integer "*" [ integer ]] term. ;; repetition
 ;;
 ;;    term = factor
 ;;         | [factor] "+"                       ;; one-or-more
@@ -302,7 +332,7 @@ Please send all bug fixes and enhancements to
 ;;                     `ebnf-lex-comment-char' and `ebnf-lex-eop-char'.
 ;;
 ;;    `abnf'           ebnf2ps recognizes the syntax described in the URL:
-;;                     `http://www.faqs.org/rfcs/rfc2234.html'
+;;                     `http://www.ietf.org/rfc/rfc2234.txt'
 ;;                     ("Augmented BNF for Syntax Specifications: ABNF").
 ;;
 ;;    `iso-ebnf'       ebnf2ps recognizes the syntax described in the URL:
@@ -317,6 +347,14 @@ Please send all bug fixes and enhancements to
 ;;                     setting:
 ;;                     `ebnf-yac-ignore-error-recovery'.
 ;;
+;;    `ebnfx'          ebnf2ps recognizes the syntax described in the URL:
+;;                  `http://www.w3.org/TR/2004/REC-xml-20040204/#sec-notation'
+;;                  ("Extensible Markup Language (XML) 1.0 (Third Edition)")
+;;
+;;    `dtd'            ebnf2ps recognizes the syntax described in the URL:
+;;                     `http://www.w3.org/TR/2004/REC-xml-20040204/'
+;;                  ("Extensible Markup Language (XML) 1.0 (Third Edition)")
+;;
 ;; Any other value is treated as `ebnf'.
 ;;
 ;; The default value is `ebnf'.
@@ -355,7 +393,7 @@ Please send all bug fixes and enhancements to
 ;;    6.  A = B | .                ==>   A = [B].
 ;;    7.  A =   | B .              ==>   A = [B].
 ;;
-;; factoration:
+;; factorization:
 ;;    8.  A = B C | B D.           ==>   A = B (C | D).
 ;;    9.  A = C B | D B.           ==>   A = (C | D) B.
 ;;    10. A = B C E | B D E.       ==>   A = B (C | D) E.
@@ -388,6 +426,8 @@ Please send all bug fixes and enhancements to
 ;;
 ;; ebnf2ps accepts the following actions in comments:
 ;;
+;;    ;^       same as form feed.  See section Form Feed above.
+;;
 ;;    ;>       the next production starts in the same line as the current one.
 ;;             It is useful when `ebnf-horizontal-orientation' is nil.
 ;;
@@ -452,8 +492,8 @@ Please send all bug fixes and enhancements to
 ;; Only the ;> will take effect, that is, A and B will be drawn in the same
 ;; line.
 ;;
-;; In ISO EBNF the above actions are specified as (*>*), (*<*), (*[EPS*) and
-;; (*]EPS*).  The first example above should be written:
+;; In ISO EBNF the above actions are specified as (*^*), (*>*), (*<*), (*[EPS*)
+;; and (*]EPS*).  The first example above should be written:
 ;;
 ;;    A = t;
 ;;    C = x;
@@ -514,6 +554,12 @@ Please send all bug fixes and enhancements to
 ;;
 ;; `ebnf-setup' returns the current setup.
 ;;
+;; `ebnf-syntax-directory' does a syntactic analysis of your EBNF files in the
+;; given directory.
+;;
+;; `ebnf-syntax-file' does a syntactic analysis of your EBNF in the given
+;; file.
+;;
 ;; `ebnf-syntax-buffer' does a syntactic analysis of your EBNF in the current
 ;; buffer.
 ;;
@@ -522,8 +568,9 @@ Please send all bug fixes and enhancements to
 ;;
 ;; `ebnf-customize' activates a customization buffer for ebnf2ps options.
 ;;
-;; `ebnf-syntax-buffer', `ebnf-syntax-region' and `ebnf-customize' can be bound
-;; to keys in the same way as `ebnf-' commands.
+;; `ebnf-syntax-directory', `ebnf-syntax-file', `ebnf-syntax-buffer',
+;; `ebnf-syntax-region' and `ebnf-customize' can be bound to keys in the same
+;; way as `ebnf-' commands.
 ;;
 ;;
 ;; Hooks
@@ -1067,19 +1114,18 @@ Please send all bug fixes and enhancements to
 
 
 ;; to avoid gripes with Emacs 20
-(eval-and-compile
-  (or (fboundp 'assq-delete-all)
-      (defun assq-delete-all (key alist)
-       "Delete from ALIST all elements whose car is KEY.
+(or (fboundp 'assq-delete-all)
+    (defun assq-delete-all (key alist)
+      "Delete from ALIST all elements whose car is KEY.
 Return the modified alist.
 Elements of ALIST that are not conses are ignored."
-       (let ((tail alist))
-         (while tail
-           (if (and (consp (car tail))
-                    (eq (car (car tail)) key))
-               (setq alist (delq (car tail) alist)))
-           (setq tail (cdr tail)))
-         alist))))
+      (let ((tail alist))
+       (while tail
+         (if (and (consp (car tail))
+                  (eq (car (car tail)) key))
+             (setq alist (delq (car tail) alist)))
+         (setq tail (cdr tail)))
+       alist)))
 
 \f
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -1089,91 +1135,104 @@ Elements of ALIST that are not conses are ignored."
 ;;; Interface to the command system
 
 (defgroup postscript nil
-  "PostScript Group"
+  "PostScript Group."
   :tag "PostScript"
+  :version "20"
   :group 'emacs)
 
 
 (defgroup ebnf2ps nil
-  "Translate an EBNF to a syntactic chart on PostScript"
+  "Translate an EBNF to a syntactic chart on PostScript."
   :prefix "ebnf-"
+  :version "20"
   :group 'wp
   :group 'postscript)
 
 
 (defgroup ebnf-special nil
-  "Special customization"
+  "Special customization."
   :prefix "ebnf-"
   :tag "Special"
+  :version "20"
   :group 'ebnf2ps)
 
 
 (defgroup ebnf-except nil
-  "Except customization"
+  "Except customization."
   :prefix "ebnf-"
   :tag "Except"
+  :version "20"
   :group 'ebnf2ps)
 
 
 (defgroup ebnf-repeat nil
-  "Repeat customization"
+  "Repeat customization."
   :prefix "ebnf-"
   :tag "Repeat"
+  :version "20"
   :group 'ebnf2ps)
 
 
 (defgroup ebnf-terminal nil
-  "Terminal customization"
+  "Terminal customization."
   :prefix "ebnf-"
   :tag "Terminal"
+  :version "20"
   :group 'ebnf2ps)
 
 
 (defgroup ebnf-non-terminal nil
-  "Non-Terminal customization"
+  "Non-Terminal customization."
   :prefix "ebnf-"
   :tag "Non-Terminal"
+  :version "20"
   :group 'ebnf2ps)
 
 
 (defgroup ebnf-production nil
-  "Production customization"
+  "Production customization."
   :prefix "ebnf-"
   :tag "Production"
+  :version "20"
   :group 'ebnf2ps)
 
 
 (defgroup ebnf-shape nil
-  "Shapes customization"
+  "Shapes customization."
   :prefix "ebnf-"
   :tag "Shape"
+  :version "20"
   :group 'ebnf2ps)
 
 
 (defgroup ebnf-displacement nil
-  "Displacement customization"
+  "Displacement customization."
   :prefix "ebnf-"
   :tag "Displacement"
+  :version "20"
   :group 'ebnf2ps)
 
 
 (defgroup ebnf-syntactic nil
-  "Syntactic customization"
+  "Syntactic customization."
   :prefix "ebnf-"
   :tag "Syntactic"
+  :version "20"
   :group 'ebnf2ps)
 
 
 (defgroup ebnf-optimization nil
-  "Optimization customization"
+  "Optimization customization."
   :prefix "ebnf-"
   :tag "Optimization"
+  :version "20"
   :group 'ebnf2ps)
 
 
 (defcustom ebnf-horizontal-orientation nil
   "*Non-nil means productions are drawn horizontally."
   :type 'boolean
+  :version "20"
   :group 'ebnf-displacement)
 
 
@@ -1182,6 +1241,7 @@ Elements of ALIST that are not conses are ignored."
 
 It is only used when `ebnf-horizontal-orientation' is non-nil."
   :type 'boolean
+  :version "20"
   :group 'ebnf-displacement)
 
 
@@ -1190,6 +1250,7 @@ It is only used when `ebnf-horizontal-orientation' is non-nil."
 
 Value less or equal to zero forces ebnf2ps to set a proper default value."
   :type 'number
+  :version "20"
   :group 'ebnf-displacement)
 
 
@@ -1198,6 +1259,7 @@ Value less or equal to zero forces ebnf2ps to set a proper default value."
 
 Value less or equal to zero forces ebnf2ps to set a proper default value."
   :type 'number
+  :version "20"
   :group 'ebnf-displacement)
 
 
@@ -1211,12 +1273,14 @@ Valid values are:
    any other value     centralize"
   :type '(radio :tag "Sequence Justification"
                (const left) (const right) (other :tag "center" center))
+  :version "20"
   :group 'ebnf-displacement)
 
 
 (defcustom ebnf-special-show-delimiter t
   "*Non-nil means special delimiter (character `?') is shown."
   :type 'boolean
+  :version "20"
   :group 'ebnf-special)
 
 
@@ -1238,6 +1302,7 @@ See documentation for `ebnf-production-font'."
                               (const underline) (const strikeout)
                               (const overline)  (const shadow)
                               (const box)       (const outline))))
+  :version "20"
   :group 'ebnf-special)
 
 
@@ -1247,24 +1312,28 @@ See documentation for `ebnf-production-font'."
 See documentation for `ebnf-non-terminal-shape'."
   :type '(radio :tag "Special Shape"
                (const miter) (const round) (const bevel))
+  :version "20"
   :group 'ebnf-special)
 
 
 (defcustom ebnf-special-shadow nil
   "*Non-nil means special box will have a shadow."
   :type 'boolean
+  :version "20"
   :group 'ebnf-special)
 
 
 (defcustom ebnf-special-border-width 0.5
   "*Specify border width for special box."
   :type 'number
+  :version "20"
   :group 'ebnf-special)
 
 
 (defcustom ebnf-special-border-color "Black"
   "*Specify border color for special box."
   :type 'string
+  :version "20"
   :group 'ebnf-special)
 
 
@@ -1286,6 +1355,7 @@ See documentation for `ebnf-production-font'."
                               (const underline) (const strikeout)
                               (const overline)  (const shadow)
                               (const box)       (const outline))))
+  :version "20"
   :group 'ebnf-except)
 
 
@@ -1295,24 +1365,28 @@ See documentation for `ebnf-production-font'."
 See documentation for `ebnf-non-terminal-shape'."
   :type '(radio :tag "Except Shape"
                (const miter) (const round) (const bevel))
+  :version "20"
   :group 'ebnf-except)
 
 
 (defcustom ebnf-except-shadow nil
   "*Non-nil means except box will have a shadow."
   :type 'boolean
+  :version "20"
   :group 'ebnf-except)
 
 
 (defcustom ebnf-except-border-width 0.25
   "*Specify border width for except box."
   :type 'number
+  :version "20"
   :group 'ebnf-except)
 
 
 (defcustom ebnf-except-border-color "Black"
   "*Specify border color for except box."
   :type 'string
+  :version "20"
   :group 'ebnf-except)
 
 
@@ -1334,6 +1408,7 @@ See documentation for `ebnf-production-font'."
                               (const underline) (const strikeout)
                               (const overline)  (const shadow)
                               (const box)       (const outline))))
+  :version "20"
   :group 'ebnf-repeat)
 
 
@@ -1343,24 +1418,28 @@ See documentation for `ebnf-production-font'."
 See documentation for `ebnf-non-terminal-shape'."
   :type '(radio :tag "Repeat Shape"
                (const miter) (const round) (const bevel))
+  :version "20"
   :group 'ebnf-repeat)
 
 
 (defcustom ebnf-repeat-shadow nil
   "*Non-nil means repeat box will have a shadow."
   :type 'boolean
+  :version "20"
   :group 'ebnf-repeat)
 
 
 (defcustom ebnf-repeat-border-width 0.0
   "*Specify border width for repeat box."
   :type 'number
+  :version "20"
   :group 'ebnf-repeat)
 
 
 (defcustom ebnf-repeat-border-color "Black"
   "*Specify border color for repeat box."
   :type 'string
+  :version "20"
   :group 'ebnf-repeat)
 
 
@@ -1382,6 +1461,7 @@ See documentation for `ebnf-production-font'."
                               (const underline) (const strikeout)
                               (const overline)  (const shadow)
                               (const box)       (const outline))))
+  :version "20"
   :group 'ebnf-terminal)
 
 
@@ -1391,30 +1471,35 @@ See documentation for `ebnf-production-font'."
 See documentation for `ebnf-non-terminal-shape'."
   :type '(radio :tag "Terminal Shape"
                (const miter) (const round) (const bevel))
+  :version "20"
   :group 'ebnf-terminal)
 
 
 (defcustom ebnf-terminal-shadow nil
   "*Non-nil means terminal box will have a shadow."
   :type 'boolean
+  :version "20"
   :group 'ebnf-terminal)
 
 
 (defcustom ebnf-terminal-border-width 1.0
   "*Specify border width for terminal box."
   :type 'number
+  :version "20"
   :group 'ebnf-terminal)
 
 
 (defcustom ebnf-terminal-border-color "Black"
   "*Specify border color for terminal box."
   :type 'string
+  :version "20"
   :group 'ebnf-terminal)
 
 
 (defcustom ebnf-production-name-p t
   "*Non-nil means production name will be printed."
   :type 'boolean
+  :version "20"
   :group 'ebnf-production)
 
 
@@ -1430,6 +1515,7 @@ Valid values are:
                (const :tag "Ascending" ascending)
                (const :tag "Descending" descending)
                (other :tag "No Sort" nil))
+  :version "20"
   :group 'ebnf-production)
 
 
@@ -1472,6 +1558,7 @@ See `ps-font-info-database' for valid font name."
                               (const underline) (const strikeout)
                               (const overline)  (const shadow)
                               (const box)       (const outline))))
+  :version "20"
   :group 'ebnf-production)
 
 
@@ -1493,6 +1580,7 @@ See documentation for `ebnf-production-font'."
                               (const underline) (const strikeout)
                               (const overline)  (const shadow)
                               (const box)       (const outline))))
+  :version "20"
   :group 'ebnf-non-terminal)
 
 
@@ -1516,24 +1604,28 @@ Valid values are:
 Any other value is treated as `miter'."
   :type '(radio :tag "Non-Terminal Shape"
                (const miter) (const round) (const bevel))
+  :version "20"
   :group 'ebnf-non-terminal)
 
 
 (defcustom ebnf-non-terminal-shadow nil
   "*Non-nil means non-terminal box will have a shadow."
   :type 'boolean
+  :version "20"
   :group 'ebnf-non-terminal)
 
 
 (defcustom ebnf-non-terminal-border-width 1.0
   "*Specify border width for non-terminal box."
   :type 'number
+  :version "20"
   :group 'ebnf-non-terminal)
 
 
 (defcustom ebnf-non-terminal-border-color "Black"
   "*Specify border color for non-terminal box."
   :type 'string
+  :version "20"
   :group 'ebnf-non-terminal)
 
 
@@ -1590,6 +1682,7 @@ Any other value is treated as `none'."
                (const full)             (const semi-up-hollow)
                (const semi-down-hollow) (const semi-up-full)
                (const semi-down-full)   (const user))
+  :version "20"
   :group 'ebnf-shape)
 
 
@@ -1599,6 +1692,7 @@ Any other value is treated as `none'."
 See documentation for `ebnf-non-terminal-shape'."
   :type '(radio :tag "Chart Flow Shape"
                (const miter) (const round) (const bevel))
+  :version "20"
   :group 'ebnf-shape)
 
 
@@ -1638,6 +1732,7 @@ The relation between these variables is: hT = 2 * hT2 = 4 * hT4.
 The variable `ebnf-user-arrow' is only used when `ebnf-arrow-shape' is set to
 symbol `user'."
   :type '(sexp :tag "User Arrow Shape")
+  :version "20"
   :group 'ebnf-shape)
 
 
@@ -1654,7 +1749,7 @@ Valid values are:
                `ebnf-lex-comment-char' and `ebnf-lex-eop-char'.
 
    `abnf'      ebnf2ps recognizes the syntax described in the URL:
-               `http://www.faqs.org/rfcs/rfc2234.html'
+               `http://www.ietf.org/rfc/rfc2234.txt'
                (\"Augmented BNF for Syntax Specifications: ABNF\").
 
    `iso-ebnf'  ebnf2ps recognizes the syntax described in the URL:
@@ -1669,9 +1764,19 @@ Valid values are:
                setting:
                `ebnf-yac-ignore-error-recovery'.
 
+   `ebnfx'     ebnf2ps recognizes the syntax described in the URL:
+               `http://www.w3.org/TR/2004/REC-xml-20040204/#sec-notation'
+               (\"Extensible Markup Language (XML) 1.0 (Third Edition)\")
+
+   `dtd'       ebnf2ps recognizes the syntax described in the URL:
+               `http://www.w3.org/TR/2004/REC-xml-20040204/'
+               (\"Extensible Markup Language (XML) 1.0 (Third Edition)\")
+
 Any other value is treated as `ebnf'."
   :type '(radio :tag "Syntax"
-               (const ebnf) (const abnf) (const iso-ebnf) (const yacc))
+               (const ebnf) (const abnf)  (const iso-ebnf)
+               (const yacc) (const ebnfx) (const dtd))
+  :version "20"
   :group 'ebnf-syntactic)
 
 
@@ -1680,6 +1785,7 @@ Any other value is treated as `ebnf'."
 
 It's used only when `ebnf-syntax' is `ebnf'."
   :type 'character
+  :version "20"
   :group 'ebnf-syntactic)
 
 
@@ -1688,6 +1794,7 @@ It's used only when `ebnf-syntax' is `ebnf'."
 
 It's used only when `ebnf-syntax' is `ebnf'."
   :type 'character
+  :version "20"
   :group 'ebnf-syntactic)
 
 
@@ -1701,6 +1808,7 @@ terminal name; terminal name may also be enclosed by `\"'.
 It's used only when `ebnf-syntax' is `ebnf'."
   :type '(radio :tag "Terminal Name"
                (const nil) regexp)
+  :version "20"
   :group 'ebnf-syntactic)
 
 
@@ -1710,6 +1818,7 @@ It's used only when `ebnf-syntax' is `ebnf'."
 It's only used when `ebnf-terminal-regexp' is non-nil and when `ebnf-syntax' is
 `ebnf'."
   :type 'boolean
+  :version "20"
   :group 'ebnf-syntactic)
 
 
@@ -1728,6 +1837,7 @@ This variable affects the following symbol set:
       }    ==>   :)
       ;    ==>   ."
   :type 'boolean
+  :version "20"
   :group 'ebnf-syntactic)
 
 
@@ -1739,6 +1849,7 @@ single space, so \"A  B   C\" is normalized to  \"A B C\".
 
 It's only used when `ebnf-syntax' is `iso-ebnf'."
   :type 'boolean
+  :version "20"
   :group 'ebnf-syntactic)
 
 
@@ -1747,6 +1858,7 @@ It's only used when `ebnf-syntax' is `iso-ebnf'."
 
 See `ebnf-eps-directory' command."
   :type 'regexp
+  :version "20"
   :group 'ebnf2ps)
 
 
@@ -1755,6 +1867,7 @@ See `ebnf-eps-directory' command."
 
 See `ebnf-eps-buffer' and `ebnf-eps-region' commands."
   :type 'string
+  :version "20"
   :group 'ebnf2ps)
 
 
@@ -1763,6 +1876,7 @@ See `ebnf-eps-buffer' and `ebnf-eps-region' commands."
 
 It must be a float between 0.0 (top) and 1.0 (bottom)."
   :type 'number
+  :version "20"
   :group 'ebnf2ps)
 
 
@@ -1770,6 +1884,7 @@ It must be a float between 0.0 (top) and 1.0 (bottom)."
   "*Specify additional border width over default terminal, non-terminal or
 special."
   :type 'number
+  :version "20"
   :group 'ebnf2ps)
 
 
@@ -1778,18 +1893,21 @@ special."
                            (fboundp 'color-instance-rgb-components)) ; XEmacs
   "*Non-nil means use color."
   :type 'boolean
+  :version "20"
   :group 'ebnf2ps)
 
 
 (defcustom ebnf-line-width 1.0
   "*Specify flow line width."
   :type 'number
+  :version "20"
   :group 'ebnf2ps)
 
 
 (defcustom ebnf-line-color "Black"
   "*Specify flow line color."
   :type 'string
+  :version "20"
   :group 'ebnf2ps)
 
 
@@ -1798,6 +1916,7 @@ special."
 
 It is intended to help PostScript programmers in debugging."
   :type 'boolean
+  :version "20"
   :group 'ebnf2ps)
 
 
@@ -1813,12 +1932,14 @@ If it occurs the error message:
 
 when executing ebnf2ps, set `ebnf-use-float-format' to nil."
   :type 'boolean
+  :version "20"
   :group 'ebnf2ps)
 
 
 (defcustom ebnf-stop-on-error nil
   "*Non-nil means signal error and stop. Nil means signal error and continue."
   :type 'boolean
+  :version "20"
   :group 'ebnf2ps)
 
 
@@ -1827,6 +1948,7 @@ when executing ebnf2ps, set `ebnf-use-float-format' to nil."
 
 It's only used when `ebnf-syntax' is `yacc'."
   :type 'boolean
+  :version "20"
   :group 'ebnf-syntactic)
 
 
@@ -1836,6 +1958,7 @@ It's only used when `ebnf-syntax' is `yacc'."
 It's interesting to set this variable if your Yacc/Bison grammar has a lot of
 middle action rule."
   :type 'boolean
+  :version "20"
   :group 'ebnf-optimization)
 
 
@@ -1855,16 +1978,32 @@ The following optimizations are done:
    6.  A = B | .                ==>   A = [B].
    7.  A =   | B .              ==>   A = [B].
 
-   factoration:
+   factorization:
    8.  A = B C | B D.           ==>   A = B (C | D).
    9.  A = C B | D B.           ==>   A = (C | D) B.
    10. A = B C E | B D E.       ==>   A = B (C | D) E.
 
 The above optimizations are specially useful when `ebnf-syntax' is `yacc'."
   :type 'boolean
+  :version "20"
   :group 'ebnf-optimization)
 
 \f
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; To make this file smaller, some commands go in a separate file.
+;; But autoload them here to make the separation invisible.
+;; Autoload is here to avoid compilation gripes.
+
+(autoload 'ebnf-eliminate-empty-rules "ebnf-otz"
+  "Eliminate empty rules.")
+
+(autoload 'ebnf-optimize              "ebnf-otz"
+  "Syntactic chart optimizer.")
+
+(autoload 'ebnf-otz-initialize        "ebnf-otz"
+  "Initialize optimizer.")
+
+\f
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Customization
 
@@ -2060,6 +2199,34 @@ WARNING: It's *NOT* asked any confirmation to override an existing file."
 (defalias 'ebnf-despool 'ps-despool)
 
 
+;;;###autoload
+(defun ebnf-syntax-directory (&optional directory)
+  "Does a syntactic analysis of the files in DIRECTORY.
+
+If DIRECTORY is nil, it's used `default-directory'.
+
+The files in DIRECTORY that matches `ebnf-file-suffix-regexp' (which see) are
+processed.
+
+See also `ebnf-syntax-buffer'."
+  (interactive
+   (list (read-file-name "Directory containing EBNF files (syntax): "
+                        nil default-directory)))
+  (ebnf-directory 'ebnf-syntax-buffer directory))
+
+
+;;;###autoload
+(defun ebnf-syntax-file (file &optional do-not-kill-buffer-when-done)
+  "Does a syntactic analysis of the FILE.
+
+If optional arg DO-NOT-KILL-BUFFER-WHEN-DONE is non-nil, the buffer isn't
+killed after syntax checking.
+
+See also `ebnf-syntax-buffer'."
+  (interactive "fEBNF file to check syntax: ")
+  (ebnf-file 'ebnf-syntax-buffer file do-not-kill-buffer-when-done))
+
+
 ;;;###autoload
 (defun ebnf-syntax-buffer ()
   "Does a syntactic analysis of the current buffer."
@@ -2355,6 +2522,14 @@ WARNING: It's *NOT* asked any confirmation to override an existing file."
     (yacc
      default
      (ebnf-syntax                      . 'yacc))
+    ;; ebnfx default
+    (ebnfx
+     default
+     (ebnf-syntax                      . 'ebnfx))
+    ;; dtd default
+    (dtd
+     default
+     (ebnf-syntax                      . 'dtd))
     )
   "Style database.
 
@@ -4086,7 +4261,7 @@ end
              ebnf-eps-max-height prod-height))
        )
       (setq ebnf-eps-prod-width prod-width)
-      (insert-buffer eps-buffer))
+      (insert-buffer-substring eps-buffer))
     (setq prod-list (cdr prod-list))))
 
 
@@ -4448,7 +4623,7 @@ killed after process termination."
 (defun ebnf-eps-filename (str)
   (let* ((len  (length str))
         (stri 0)
-        (new  (make-string len ?\ )))
+        (new  (make-string len ?\s)))
     (while (< stri len)
       (aset new stri (aref ebnf-map-name (aref str stri)))
       (setq stri (1+ stri)))
@@ -4499,7 +4674,7 @@ killed after process termination."
       (goto-char the-point)
       (if ebnf-stop-on-error
          (error error-msg)
-       (message error-msg)))
+       (message "%s" error-msg)))
      ;; generated output OK
      (gen-func
       nil)
@@ -4612,7 +4787,9 @@ killed after process termination."
   '((iso-ebnf  ebnf-iso-parser  ebnf-iso-initialize)
     (yacc      ebnf-yac-parser  ebnf-yac-initialize)
     (abnf      ebnf-abn-parser  ebnf-abn-initialize)
-    (ebnf      ebnf-bnf-parser  ebnf-bnf-initialize))
+    (ebnf      ebnf-bnf-parser  ebnf-bnf-initialize)
+    (ebnfx     ebnf-ebx-parser  ebnf-ebx-initialize)
+    (dtd       ebnf-dtd-parser  ebnf-dtd-initialize))
   "Alist associating ebnf syntax with a parser and a initializer.")
 
 
@@ -4710,52 +4887,53 @@ killed after process termination."
 
 
 (defun ebnf-eps-finish-and-write (buffer filename)
-  (save-excursion
-    (set-buffer buffer)
-    (setq ebnf-eps-upper-x (max ebnf-eps-upper-x ebnf-eps-max-width)
-         ebnf-eps-upper-y (if (zerop ebnf-eps-upper-y)
-                              ebnf-eps-max-height
-                            (+ ebnf-eps-upper-y
-                               ebnf-production-vertical-space
-                               ebnf-eps-max-height)))
-    ;; prologue
-    (goto-char (point-min))
-    (insert
-     "%!PS-Adobe-3.0 EPSF-3.0"
-     "\n%%BoundingBox: 0 0 "
-     (format "%d %d" (1+ ebnf-eps-upper-x) (1+ ebnf-eps-upper-y))
-     "\n%%Title: " filename
-     "\n%%CreationDate: " (format-time-string "%T %b %d %Y")
-     "\n%%Creator: " (user-full-name) " (using ebnf2ps v" ebnf-version ")"
-     "\n%%DocumentNeededResources: font "
-     (or ebnf-fonts-required
-        (setq ebnf-fonts-required
-              (mapconcat 'identity
-                         (ps-remove-duplicates
-                          (mapcar 'ebnf-font-name-select
-                                  (list ebnf-production-font
-                                        ebnf-terminal-font
-                                        ebnf-non-terminal-font
-                                        ebnf-special-font
-                                        ebnf-except-font
-                                        ebnf-repeat-font)))
-                         "\n%%+ font ")))
-     "\n%%Pages: 0\n%%EndComments\n\n%%BeginProlog\n"
-     ebnf-eps-prologue)
-    (ebnf-insert-ebnf-prologue)
-    (insert ebnf-eps-begin
-           "\n0 " (ebnf-format-float
-                   (- ebnf-eps-upper-y (* ebnf-font-height-P 0.7)))
-           " #ebnf2ps#begin\n")
-    ;; epilogue
-    (goto-char (point-max))
-    (insert ebnf-eps-end)
-    ;; write file
-    (message "Saving...")
-    (setq filename (expand-file-name filename))
-    (let ((coding-system-for-write 'raw-text-unix))
-      (write-region (point-min) (point-max) filename))
-    (message "Wrote %s" filename)))
+  (when (buffer-modified-p buffer)
+    (save-excursion
+      (set-buffer buffer)
+      (setq ebnf-eps-upper-x (max ebnf-eps-upper-x ebnf-eps-max-width)
+           ebnf-eps-upper-y (if (zerop ebnf-eps-upper-y)
+                                ebnf-eps-max-height
+                              (+ ebnf-eps-upper-y
+                                 ebnf-production-vertical-space
+                                 ebnf-eps-max-height)))
+      ;; prologue
+      (goto-char (point-min))
+      (insert
+       "%!PS-Adobe-3.0 EPSF-3.0"
+       "\n%%BoundingBox: 0 0 "
+       (format "%d %d" (1+ ebnf-eps-upper-x) (1+ ebnf-eps-upper-y))
+       "\n%%Title: " filename
+       "\n%%CreationDate: " (format-time-string "%T %b %d %Y")
+       "\n%%Creator: " (user-full-name) " (using ebnf2ps v" ebnf-version ")"
+       "\n%%DocumentNeededResources: font "
+       (or ebnf-fonts-required
+          (setq ebnf-fonts-required
+                (mapconcat 'identity
+                           (ps-remove-duplicates
+                            (mapcar 'ebnf-font-name-select
+                                    (list ebnf-production-font
+                                          ebnf-terminal-font
+                                          ebnf-non-terminal-font
+                                          ebnf-special-font
+                                          ebnf-except-font
+                                          ebnf-repeat-font)))
+                           "\n%%+ font ")))
+       "\n%%Pages: 0\n%%EndComments\n\n%%BeginProlog\n"
+       ebnf-eps-prologue)
+      (ebnf-insert-ebnf-prologue)
+      (insert ebnf-eps-begin
+             "\n0 " (ebnf-format-float
+                     (- ebnf-eps-upper-y (* ebnf-font-height-P 0.7)))
+             " #ebnf2ps#begin\n")
+      ;; epilogue
+      (goto-char (point-max))
+      (insert ebnf-eps-end)
+      ;; write file
+      (message "Saving...")
+      (setq filename (expand-file-name filename))
+      (let ((coding-system-for-write 'raw-text-unix))
+       (write-region (point-min) (point-max) filename))
+      (message "Wrote %s" filename))))
 
 
 (defun ebnf-insert-ebnf-prologue ()
@@ -5321,7 +5499,7 @@ killed after process termination."
      ;;(skip-chars-forward (concat chars "\240-\377") ebnf-limit)
      (skip-chars-forward (concat chars ebnf-8-bit-chars) ebnf-limit)
      (if (or (eobp) (/= (following-char) eos-char))
-        (error "Illegal %s: missing `%c'" kind eos-char)
+        (error "Invalid %s: missing `%c'" kind eos-char)
        (forward-char)
        (1- (point))))))
 
@@ -5345,7 +5523,7 @@ killed after process termination."
 (defun ebnf-trim-right (str)
   (let* ((len   (1- (length str)))
         (index len))
-    (while (and (> index 0) (= (aref str index) ?\ ))
+    (while (and (> index 0) (= (aref str index) ?\s))
       (setq index (1- index)))
     (if (= index len)
        str
@@ -5608,6 +5786,20 @@ killed after process termination."
                                                   (cons seq body)
                                                 body))))))))
 
+
+(defun ebnf-token-sequence (sequence)
+  (cond
+   ;; null sequence
+   ((null sequence)
+    (ebnf-make-empty))
+   ;; sequence with only one element
+   ((= (length sequence) 1)
+    (car sequence))
+   ;; a real sequence
+   (t
+    (ebnf-make-sequence (nreverse sequence)))
+   ))
+
 \f
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Variables used by parsers
@@ -5618,6 +5810,7 @@ killed after process termination."
     ;; Override special comment character:
     (aset table ?< 'newline)
     (aset table ?> 'keep-line)
+    (aset table ?^ 'form-feed)
     table)
   "Vector used to map characters to a special comment token.")
 
@@ -5650,14 +5843,17 @@ killed after process termination."
 (autoload 'ebnf-yac-initialize        "ebnf-yac"
   "Initializations for Yacc/Bison parser.")
 
-(autoload 'ebnf-eliminate-empty-rules "ebnf-otz"
-  "Eliminate empty rules.")
+(autoload 'ebnf-ebx-parser            "ebnf-ebx"
+  "EBNFX parser.")
 
-(autoload 'ebnf-optimize              "ebnf-otz"
-  "Syntactic chart optimizer.")
+(autoload 'ebnf-ebx-initialize        "ebnf-ebx"
+  "Initializations for EBNFX parser.")
 
-(autoload 'ebnf-otz-initialize        "ebnf-otz"
-  "Initialize optimizer.")
+(autoload 'ebnf-dtd-parser            "ebnf-dtd"
+  "DTD parser.")
+
+(autoload 'ebnf-dtd-initialize        "ebnf-dtd"
+  "Initializations for DTD parser.")
 
 \f
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;