]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/ebnf-yac.el
Adam Hupp <adam at hupp.org>
[gnu-emacs] / lisp / progmodes / ebnf-yac.el
index bbe135e45ece2002daaada9dea1e25a6351270cd..c1b00bdddfc386a6c4502678c3c084a6158f44c0 100644 (file)
@@ -1,29 +1,29 @@
-;;; ebnf-yac --- Parser for Yacc/Bison
+;;; ebnf-yac.el --- parser for Yacc/Bison
 
-;; Copyright (C) 1999 Vinicius Jose Latorre
+;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+;;   Free Software Foundation, Inc.
 
-;; Author:     Vinicius Jose Latorre <vinicius@cpqd.com.br>
-;; Maintainer: Vinicius Jose Latorre <vinicius@cpqd.com.br>
-;; Keywords:   wp, ebnf, PostScript
-;; Time-stamp: <99/11/20 18:02:43 vinicius>
-;; Version:    1.0
+;; Author: Vinicius Jose Latorre <viniciusjl@ig.com.br>
+;; Maintainer: Vinicius Jose Latorre <viniciusjl@ig.com.br>
+;; Keywords: wp, ebnf, PostScript
+;; Version: 1.4
 
-;; This file is *NOT* (yet?) part of GNU Emacs.
+;; This file is part of GNU Emacs.
 
-;; This program is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
+;; the Free Software Foundation; either version 3, or (at your option)
 ;; any later version.
 
-;; This program is distributed in the hope that it will be useful,
+;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ;; GNU General Public License for more details.
 
 ;; 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.
 
 ;;; Commentary:
 
@@ -42,7 +42,9 @@
 ;;
 ;; YACC = { YACC-Definitions }* "%%" { YACC-Rule }* [ "%%" [ YACC-Code ] ].
 ;;
-;; YACC-Definitions = "%token" [ "<" Name ">" ] Name-List
+;; YACC-Definitions = ( "%token" | "%left" | "%right" | "%nonassoc" )
+;;                    [ "<" Name ">" ] Name-List
+;;                  | "%prec" Name
 ;;                  | "any other Yacc definition"
 ;;                  .
 ;;
 ;; Name = "[A-Za-z][A-Za-z0-9_.]*".
 ;;
 ;; Comment = "/*" "any character, but the sequence \"*/\"" "*/"
-;;         | "//" "any character" "\\n".
+;;         | "//" "any character, but the newline \"\\n\"" "\\n".
+;;
+;;
+;; In other words, a valid Name begins with a letter (upper or lower case)
+;; followed by letters, decimal digits, underscore (_) or point (.).  For
+;; example: this_is_a_valid.name, Another_EXAMPLE, mIxEd.CaSe.
+;;
+;;
+;; Acknowledgements
+;; ----------------
+;;
+;; Thanks to Matthew K. Junker <junker@alum.mit.edu> for the suggestion to deal
+;; with %right, %left and %prec pragmas.  His suggestion was extended to deal
+;; with %nonassoc pragma too.
 ;;
 ;;
 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-;;; code:
+;;; Code:
 
 
 (require 'ebnf-otz)
 
 
 (defvar ebnf-yac-error nil
-  "Non-nil means \"error\" occured.")
+  "Non-nil means \"error\" occurred.")
 
 \f
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Syntatic analyzer
+;; Syntactic analyzer
 
 
 ;;; YACC = { YACC-Definitions }* "%%" { YACC-Rule }* [ "%%" [ YACC-Code ] ].
     (goto-char start)
     (setq token (ebnf-yac-lex))
     (and (eq token 'end-of-input)
-        (error "Invalid Yacc/Bison file format."))
+        (error "Invalid Yacc/Bison file format"))
     (or (eq (ebnf-yac-definitions token) 'yac-separator)
-       (error "Missing `%%%%'."))
+       (error "Missing `%%%%'"))
     (setq token (ebnf-yac-lex))
     (while (not (memq token '(end-of-input yac-separator)))
       (ebnf-message-float
     syntax-list))
 
 
-;;; YACC-Definitions = "%token" [ "<" Name ">" ] Name-List
+;;; YACC-Definitions = ( "%token" | "%left" | "%right" | "%nonassoc" )
+;;;                    [ "<" Name ">" ] Name-List
+;;;                  | "%prec" Name
 ;;;                  | "any other Yacc definition"
 ;;;                  .
 
     (while (not (memq token '(yac-separator end-of-input)))
       (setq token
            (cond
-            ;; "%token" [ "<" Name ">" ] Name-List
+            ;; ( "%token" | "%left" | "%right" | "%nonassoc" )
+            ;; [ "<" Name ">" ] Name-List
             ((eq token 'yac-token)
              (setq token (ebnf-yac-lex))
              (when (eq token 'open-angle)
                (or (eq (ebnf-yac-lex) 'non-terminal)
-                   (error "Missing type name."))
+                   (error "Missing type name"))
                (or (eq (ebnf-yac-lex) 'close-angle)
-                   (error "Missing `>'."))
+                   (error "Missing `>'"))
                (setq token (ebnf-yac-lex)))
              (setq token               (ebnf-yac-name-list token)
                    ebnf-yac-token-list (nconc (cdr token)
                                               ebnf-yac-token-list))
              (car token))
-            ;; "any other Yacc definition"
+            ;;  "%prec" Name
+            ((eq token 'yac-prec)
+             (or (eq (ebnf-yac-lex) 'non-terminal)
+                 (error "Missing prec name"))
+             (ebnf-yac-lex))
+            ;;  "any other Yacc definition"
             (t
              (ebnf-yac-lex))
             )))
        body)
     (setq ebnf-action nil)
     (or (eq token 'non-terminal)
-       (error "Invalid rule name."))
+       (error "Invalid rule name"))
     (or (eq (ebnf-yac-lex) 'colon)
-       (error "Invalid rule: missing `:'."))
+       (error "Invalid rule: missing `:'"))
     (setq body (ebnf-yac-alternative))
     (or (eq (car body) 'period)
-       (error "Invalid rule: missing `;'."))
+       (error "Invalid rule: missing `;'"))
     (setq body (cdr body))
     (ebnf-eps-add-production header)
     (cons (ebnf-yac-lex)
                 factor (ebnf-yac-factor token))
       (setq seq (cons factor seq)))
     (cons token
-         (cond
-          ;; ignore error recovery
-          ((and ebnf-yac-ignore-error-recovery ebnf-yac-error)
-           nil)
-          ;; null sequence
-          ((null seq)
-           (ebnf-make-empty))
-          ;; sequence with only one element
-          ((= (length seq) 1)
-           (car seq))
-          ;; a real sequence
-          (t
-           (ebnf-make-sequence (nreverse seq)))
-          ))))
+         (if (and ebnf-yac-ignore-error-recovery ebnf-yac-error)
+             ;; ignore error recovery
+             nil
+           (ebnf-token-sequence seq)))))
 
 
 ;;; Factor = Name
                     token (ebnf-yac-lex))
               (eq token 'comma))
        (or (eq (ebnf-yac-lex) 'non-terminal)
-           (error "Missing token name."))))
+           (error "Missing token name"))))
     (cons token names)))
 
 \f
 
 
 (defun ebnf-yac-lex ()
-  "Lexical analyser for Yacc/Bison.
+  "Lexical analyzer for Yacc/Bison.
 
 Return a lexical token.
 
@@ -332,7 +345,7 @@ See documentation for variable `ebnf-yac-lex'."
        'end-of-input)
        ;; error
        ((eq token 'error)
-       (error "Illegal character."))
+       (error "Invalid character"))
        ;; "string"
        ((eq token 'string)
        (setq ebnf-yac-lex (ebnf-get-string))
@@ -360,9 +373,13 @@ See documentation for variable `ebnf-yac-lex'."
         ((eq (following-char) ?%)
          (forward-char)
          'yac-separator)
-        ;; %TOKEN
-        ((string= (upcase (ebnf-buffer-substring "0-9A-Za-z_")) "TOKEN")
-         'yac-token)
+        ;; %TOKEN, %RIGHT, %LEFT,  %PREC, %NONASSOC
+        ((cdr (assoc (upcase (ebnf-buffer-substring "0-9A-Za-z_"))
+                     '(("TOKEN"    . yac-token)
+                       ("RIGHT"    . yac-token)
+                       ("LEFT"     . yac-token)
+                       ("NONASSOC" . yac-token)
+                       ("PREC"     . yac-prec)))))
         ;; other Yacc pragmas
         (t
          'yac-pragma)
@@ -383,11 +400,16 @@ See documentation for variable `ebnf-yac-lex'."
   (< (point) ebnf-limit))
 
 
+;; replace the range "\177-\377" (see `ebnf-range-regexp').
+(defconst ebnf-yac-skip-chars
+  (ebnf-range-regexp "^{}/'\"\000-\010\013\016-\037" ?\177 ?\377))
+
+
 (defun ebnf-yac-skip-code ()
   (forward-char)
   (let ((pair 1))
     (while (> pair 0)
-      (skip-chars-forward "^{}/'\"\000-\010\013\016-\037\177-\377" ebnf-limit)
+      (skip-chars-forward ebnf-yac-skip-chars ebnf-limit)
       (cond
        ((= (following-char) ?{)
        (forward-char)
@@ -402,7 +424,7 @@ See documentation for variable `ebnf-yac-lex'."
        ((= (following-char) ?\')
        (ebnf-string " -&(-~" ?\' "character"))
        (t
-       (error "Illegal character."))
+       (error "Invalid character"))
        )))
   (ebnf-yac-skip-spaces))
 
@@ -423,7 +445,9 @@ See documentation for variable `ebnf-yac-lex'."
    ))
 
 
-(defconst ebnf-yac-comment-chars "^*\000-\010\013\016-\037\177-\237")
+;; replace the range "\177-\237" (see `ebnf-range-regexp').
+(defconst ebnf-yac-comment-chars
+  (ebnf-range-regexp "^*\000-\010\013\016-\037" ?\177 ?\237))
 
 
 (defun ebnf-yac-skip-comment ()
@@ -435,6 +459,12 @@ See documentation for variable `ebnf-yac-lex'."
    ;; close EPS file
    ((and ebnf-eps-executing (= (following-char) ?\]))
     (ebnf-eps-remove-context (ebnf-yac-eps-filename)))
+   ;; EPS header
+   ((and ebnf-eps-executing (= (following-char) ?H))
+    (ebnf-eps-header-comment (ebnf-yac-eps-filename)))
+   ;; EPS footer
+   ((and ebnf-eps-executing (= (following-char) ?F))
+    (ebnf-eps-footer-comment (ebnf-yac-eps-filename)))
    ;; any other action in comment
    (t
     (setq ebnf-action (aref ebnf-comment-table (following-char))))
@@ -443,7 +473,7 @@ See documentation for variable `ebnf-yac-lex'."
     (while not-end
       (skip-chars-forward ebnf-yac-comment-chars ebnf-limit)
       (cond ((>= (point) ebnf-limit)
-            (error "Missing end of comment: `*/'."))
+            (error "Missing end of comment: `*/'"))
            ((= (following-char) ?*)
             (skip-chars-forward "*" ebnf-limit)
             (when (= (following-char) ?/)
@@ -451,7 +481,7 @@ See documentation for variable `ebnf-yac-lex'."
               (forward-char)
               (setq not-end nil)))
            (t
-            (error "Illegal character."))
+            (error "Invalid character"))
            ))))
 
 
@@ -484,4 +514,5 @@ See documentation for variable `ebnf-yac-lex'."
 (provide 'ebnf-yac)
 
 
+;;; arch-tag: 8a96989c-0b1d-42ba-a020-b2901f9a2a4d
 ;;; ebnf-yac.el ends here