mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-11-24 07:20:37 +00:00
*** empty log message ***
This commit is contained in:
parent
f95d599c51
commit
984ae00171
@ -1,3 +1,9 @@
|
||||
2000-01-27 Gerd Moellmann <gerd@gnu.org>
|
||||
|
||||
* progmodes/ebnf2ps.el, progmodes/ebnf-bnf.el,
|
||||
progmodes/ebnf-iso.el, progmodes/ebnf-otz.el,
|
||||
progmodes/ebnf-yac.el: New files.
|
||||
|
||||
2000-01-26 Dave Love <fx@gnu.org>
|
||||
|
||||
* emacs-lisp/checkdoc.el (checkdoc-interactive-loop): Don't lose
|
||||
|
583
lisp/progmodes/ebnf-bnf.el
Normal file
583
lisp/progmodes/ebnf-bnf.el
Normal file
@ -0,0 +1,583 @@
|
||||
;;; ebnf-bnf --- Parser for EBNF
|
||||
|
||||
;; Copyright (C) 1999 Vinicius Jose Latorre
|
||||
|
||||
;; 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:05:05 vinicius>
|
||||
;; Version: 1.4
|
||||
|
||||
;; This file is *NOT* (yet?) part of GNU Emacs.
|
||||
|
||||
;; This program 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)
|
||||
;; any later version.
|
||||
|
||||
;; This program 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.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;;
|
||||
;; This is part of ebnf2ps package.
|
||||
;;
|
||||
;; This package defines a parser for EBNF.
|
||||
;;
|
||||
;; See ebnf2ps.el for documentation.
|
||||
;;
|
||||
;;
|
||||
;; EBNF Syntax
|
||||
;; -----------
|
||||
;;
|
||||
;; The current EBNF that ebnf2ps accepts has the following constructions:
|
||||
;;
|
||||
;; ; comment (until end of line)
|
||||
;; A non-terminal
|
||||
;; "C" terminal
|
||||
;; ?C? special
|
||||
;; $A default non-terminal
|
||||
;; $"C" default terminal
|
||||
;; $?C? default special
|
||||
;; A = B. production (A is the header and B the body)
|
||||
;; 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)
|
||||
;; (C) group (expression C is grouped together)
|
||||
;; [C] optional (C may or not occurs)
|
||||
;; C+ one or more occurrences of C
|
||||
;; {C}+ one or more occurrences of C
|
||||
;; {C}* zero or more occurrences of C
|
||||
;; {C} zero or more occurrences of C
|
||||
;; C / D equivalent to: C {D C}*
|
||||
;; {C || D}+ equivalent to: C {D C}*
|
||||
;; {C || D}* equivalent to: [C {D C}*]
|
||||
;; {C || D} equivalent to: [C {D C}*]
|
||||
;;
|
||||
;; The EBNF syntax written using the notation above is:
|
||||
;;
|
||||
;; EBNF = {production}+.
|
||||
;;
|
||||
;; production = non_terminal "=" body ".". ;; production
|
||||
;;
|
||||
;; body = {sequence || "|"}*. ;; alternative
|
||||
;;
|
||||
;; sequence = {exception}*. ;; sequence
|
||||
;;
|
||||
;; exception = repeat [ "-" repeat]. ;; exception
|
||||
;;
|
||||
;; repeat = [ integer "*" ] term. ;; repetition
|
||||
;;
|
||||
;; term = factor
|
||||
;; | [factor] "+" ;; one-or-more
|
||||
;; | [factor] "/" [factor] ;; one-or-more
|
||||
;; .
|
||||
;;
|
||||
;; factor = [ "$" ] "\"" terminal "\"" ;; terminal
|
||||
;; | [ "$" ] non_terminal ;; non-terminal
|
||||
;; | [ "$" ] "?" special "?" ;; special
|
||||
;; | "(" body ")" ;; group
|
||||
;; | "[" body "]" ;; zero-or-one
|
||||
;; | "{" body [ "||" body ] "}+" ;; one-or-more
|
||||
;; | "{" body [ "||" body ] "}*" ;; zero-or-more
|
||||
;; | "{" body [ "||" body ] "}" ;; zero-or-more
|
||||
;; .
|
||||
;;
|
||||
;; non_terminal = "[A-Za-z\\240-\\377][!#%&'*-,0-:<>@-Z\\^-z~\\240-\\377]*".
|
||||
;;
|
||||
;; terminal = "\\([^\"\\]\\|\\\\[ -~\\240-\\377]\\)+".
|
||||
;;
|
||||
;; special = "[^?\\n\\000-\\010\\016-\\037\\177-\\237]*".
|
||||
;;
|
||||
;; integer = "[0-9]+".
|
||||
;;
|
||||
;; comment = ";" "[^\\n\\000-\\010\\016-\\037\\177-\\237]*" "\\n".
|
||||
;;
|
||||
;;
|
||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;;; code:
|
||||
|
||||
|
||||
(require 'ebnf-otz)
|
||||
|
||||
|
||||
(defvar ebnf-bnf-lex nil
|
||||
"Value returned by `ebnf-bnf-lex' function.")
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Syntatic analyzer
|
||||
|
||||
|
||||
;;; EBNF = {production}+.
|
||||
|
||||
(defun ebnf-bnf-parser (start)
|
||||
"EBNF parser."
|
||||
(let ((total (+ (- ebnf-limit start) 1))
|
||||
(bias (1- start))
|
||||
(origin (point))
|
||||
prod-list token rule)
|
||||
(goto-char start)
|
||||
(setq token (ebnf-bnf-lex))
|
||||
(and (eq token 'end-of-input)
|
||||
(error "Invalid EBNF file format."))
|
||||
(while (not (eq token 'end-of-input))
|
||||
(ebnf-message-float
|
||||
"Parsing...%s%%"
|
||||
(/ (* (- (point) bias) 100.0) total))
|
||||
(setq token (ebnf-production token)
|
||||
rule (cdr token)
|
||||
token (car token))
|
||||
(or (ebnf-add-empty-rule-list rule)
|
||||
(setq prod-list (cons rule prod-list))))
|
||||
(goto-char origin)
|
||||
prod-list))
|
||||
|
||||
|
||||
;;; production = non-terminal "=" body ".".
|
||||
|
||||
(defun ebnf-production (token)
|
||||
(let ((header ebnf-bnf-lex)
|
||||
(action ebnf-action)
|
||||
body)
|
||||
(setq ebnf-action nil)
|
||||
(or (eq token 'non-terminal)
|
||||
(error "Invalid header production."))
|
||||
(or (eq (ebnf-bnf-lex) 'equal)
|
||||
(error "Invalid production: missing `='."))
|
||||
(setq body (ebnf-body))
|
||||
(or (eq (car body) 'period)
|
||||
(error "Invalid production: missing `.'."))
|
||||
(setq body (cdr body))
|
||||
(ebnf-eps-add-production header)
|
||||
(cons (ebnf-bnf-lex)
|
||||
(ebnf-make-production header body action))))
|
||||
|
||||
|
||||
;;; body = {sequence || "|"}*.
|
||||
|
||||
(defun ebnf-body ()
|
||||
(let (body sequence)
|
||||
(while (eq (car (setq sequence (ebnf-sequence))) 'alternative)
|
||||
(setq sequence (cdr sequence)
|
||||
body (cons sequence body)))
|
||||
(ebnf-token-alternative body sequence)))
|
||||
|
||||
|
||||
;;; sequence = {exception}*.
|
||||
|
||||
(defun ebnf-sequence ()
|
||||
(let ((token (ebnf-bnf-lex))
|
||||
seq term)
|
||||
(while (setq term (ebnf-exception token)
|
||||
token (car term)
|
||||
term (cdr term))
|
||||
(setq seq (cons term seq)))
|
||||
(cons token
|
||||
(cond
|
||||
;; 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)))
|
||||
))))
|
||||
|
||||
|
||||
;;; exception = repeat [ "-" repeat].
|
||||
|
||||
(defun ebnf-exception (token)
|
||||
(let ((term (ebnf-repeat token)))
|
||||
(if (not (eq (car term) 'except))
|
||||
;; repeat
|
||||
term
|
||||
;; repeat - repeat
|
||||
(let ((exception (ebnf-repeat (ebnf-bnf-lex))))
|
||||
(ebnf-no-non-terminal (cdr exception))
|
||||
(ebnf-token-except (cdr term) exception)))))
|
||||
|
||||
|
||||
(defun ebnf-no-non-terminal (node)
|
||||
(and (vectorp node)
|
||||
(let ((kind (ebnf-node-kind node)))
|
||||
(cond
|
||||
((eq kind 'ebnf-generate-non-terminal)
|
||||
(error "Exception sequence should not contain a non-terminal."))
|
||||
((eq kind 'ebnf-generate-repeat)
|
||||
(ebnf-no-non-terminal (ebnf-node-separator node)))
|
||||
((memq kind '(ebnf-generate-optional ebnf-generate-except))
|
||||
(ebnf-no-non-terminal (ebnf-node-list node)))
|
||||
((memq kind '(ebnf-generate-one-or-more ebnf-generate-zero-or-more))
|
||||
(ebnf-no-non-terminal (ebnf-node-list node))
|
||||
(ebnf-no-non-terminal (ebnf-node-separator node)))
|
||||
((memq kind '(ebnf-generate-alternative ebnf-generate-sequence))
|
||||
(let ((seq (ebnf-node-list node)))
|
||||
(while seq
|
||||
(ebnf-no-non-terminal (car seq))
|
||||
(setq seq (cdr seq)))))
|
||||
))))
|
||||
|
||||
|
||||
;;; repeat = [ integer "*" ] term.
|
||||
|
||||
(defun ebnf-repeat (token)
|
||||
(if (not (eq token 'integer))
|
||||
(ebnf-term token)
|
||||
(let ((times ebnf-bnf-lex))
|
||||
(or (eq (ebnf-bnf-lex) 'repeat)
|
||||
(error "Missing `*'."))
|
||||
(ebnf-token-repeat times (ebnf-term (ebnf-bnf-lex))))))
|
||||
|
||||
|
||||
;;; term = factor
|
||||
;;; | [factor] "+" ;; one-or-more
|
||||
;;; | [factor] "/" [factor] ;; one-or-more
|
||||
;;; .
|
||||
|
||||
(defun ebnf-term (token)
|
||||
(let ((factor (ebnf-factor token)))
|
||||
(and factor
|
||||
(setq token (ebnf-bnf-lex)))
|
||||
(cond
|
||||
;; [factor] +
|
||||
((eq token 'one-or-more)
|
||||
(cons (ebnf-bnf-lex)
|
||||
(and factor
|
||||
(let ((kind (ebnf-node-kind factor)))
|
||||
(cond
|
||||
;; { A }+ + ==> { A }+
|
||||
;; { A }* + ==> { A }*
|
||||
((memq kind '(ebnf-generate-zero-or-more
|
||||
ebnf-generate-one-or-more))
|
||||
factor)
|
||||
;; [ A ] + ==> { A }*
|
||||
((eq kind 'ebnf-generate-optional)
|
||||
(ebnf-make-zero-or-more (list factor)))
|
||||
;; A +
|
||||
(t
|
||||
(ebnf-make-one-or-more (list factor)))
|
||||
)))))
|
||||
;; [factor] / [factor]
|
||||
((eq token 'list)
|
||||
(setq token (ebnf-bnf-lex))
|
||||
(let ((sep (ebnf-factor token)))
|
||||
(and sep
|
||||
(setq factor (or factor (ebnf-make-empty))))
|
||||
(cons (if sep
|
||||
(ebnf-bnf-lex)
|
||||
token)
|
||||
(and factor
|
||||
(ebnf-make-one-or-more factor sep)))))
|
||||
;; factor
|
||||
(t
|
||||
(cons token factor))
|
||||
)))
|
||||
|
||||
|
||||
;;; factor = [ "$" ] "\"" terminal "\"" ;; terminal
|
||||
;;; | [ "$" ] non_terminal ;; non-terminal
|
||||
;;; | [ "$" ] "?" special "?" ;; special
|
||||
;;; | "(" body ")" ;; group
|
||||
;;; | "[" body "]" ;; zero-or-one
|
||||
;;; | "{" body [ "||" body ] "}+" ;; one-or-more
|
||||
;;; | "{" body [ "||" body ] "}*" ;; zero-or-more
|
||||
;;; | "{" body [ "||" body ] "}" ;; zero-or-more
|
||||
;;; .
|
||||
|
||||
(defun ebnf-factor (token)
|
||||
(cond
|
||||
;; terminal
|
||||
((eq token 'terminal)
|
||||
(ebnf-make-terminal ebnf-bnf-lex))
|
||||
;; non-terminal
|
||||
((eq token 'non-terminal)
|
||||
(ebnf-make-non-terminal ebnf-bnf-lex))
|
||||
;; special
|
||||
((eq token 'special)
|
||||
(ebnf-make-special ebnf-bnf-lex))
|
||||
;; group
|
||||
((eq token 'begin-group)
|
||||
(let ((body (ebnf-body)))
|
||||
(or (eq (car body) 'end-group)
|
||||
(error "Missing `)'."))
|
||||
(cdr body)))
|
||||
;; optional
|
||||
((eq token 'begin-optional)
|
||||
(let ((body (ebnf-body)))
|
||||
(or (eq (car body) 'end-optional)
|
||||
(error "Missing `]'."))
|
||||
(ebnf-token-optional (cdr body))))
|
||||
;; list
|
||||
((eq token 'begin-list)
|
||||
(let* ((body (ebnf-body))
|
||||
(token (car body))
|
||||
(list-part (cdr body))
|
||||
sep-part)
|
||||
(and (eq token 'list-separator)
|
||||
;; { A || B }
|
||||
(setq body (ebnf-body) ; get separator
|
||||
token (car body)
|
||||
sep-part (cdr body)))
|
||||
(cond
|
||||
;; { A }+
|
||||
((eq token 'end-one-or-more)
|
||||
(ebnf-make-one-or-more list-part sep-part))
|
||||
;; { A }*
|
||||
((eq token 'end-zero-or-more)
|
||||
(ebnf-make-zero-or-more list-part sep-part))
|
||||
(t
|
||||
(error "Missing `}+', `}*' or `}'."))
|
||||
)))
|
||||
;; no term
|
||||
(t
|
||||
nil)
|
||||
))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Lexical analyzer
|
||||
|
||||
|
||||
(defconst ebnf-bnf-token-table (make-vector 256 'error)
|
||||
"Vector used to map characters to a lexical token.")
|
||||
|
||||
|
||||
(defun ebnf-bnf-initialize ()
|
||||
"Initialize EBNF token table."
|
||||
;; control character & control 8-bit character are set to `error'
|
||||
(let ((char ?\040))
|
||||
;; printable character:
|
||||
(while (< char ?\060)
|
||||
(aset ebnf-bnf-token-table char 'non-terminal)
|
||||
(setq char (1+ char)))
|
||||
;; digits:
|
||||
(while (< char ?\072)
|
||||
(aset ebnf-bnf-token-table char 'integer)
|
||||
(setq char (1+ char)))
|
||||
;; printable character:
|
||||
(while (< char ?\177)
|
||||
(aset ebnf-bnf-token-table char 'non-terminal)
|
||||
(setq char (1+ char)))
|
||||
;; European 8-bit accentuated characters:
|
||||
(setq char ?\240)
|
||||
(while (< char ?\400)
|
||||
(aset ebnf-bnf-token-table char 'non-terminal)
|
||||
(setq char (1+ char)))
|
||||
;; Override space characters:
|
||||
(aset ebnf-bnf-token-table ?\013 'space) ; [VT] vertical tab
|
||||
(aset ebnf-bnf-token-table ?\n 'space) ; [NL] linefeed
|
||||
(aset ebnf-bnf-token-table ?\r 'space) ; [CR] carriage return
|
||||
(aset ebnf-bnf-token-table ?\t 'space) ; [HT] horizontal tab
|
||||
(aset ebnf-bnf-token-table ?\ 'space) ; [SP] space
|
||||
;; Override form feed character:
|
||||
(aset ebnf-bnf-token-table ?\f 'form-feed) ; [FF] form feed
|
||||
;; Override other lexical characters:
|
||||
(aset ebnf-bnf-token-table ?\" 'terminal)
|
||||
(aset ebnf-bnf-token-table ?\? 'special)
|
||||
(aset ebnf-bnf-token-table ?\( 'begin-group)
|
||||
(aset ebnf-bnf-token-table ?\) 'end-group)
|
||||
(aset ebnf-bnf-token-table ?* 'repeat)
|
||||
(aset ebnf-bnf-token-table ?- 'except)
|
||||
(aset ebnf-bnf-token-table ?= 'equal)
|
||||
(aset ebnf-bnf-token-table ?\[ 'begin-optional)
|
||||
(aset ebnf-bnf-token-table ?\] 'end-optional)
|
||||
(aset ebnf-bnf-token-table ?\{ 'begin-list)
|
||||
(aset ebnf-bnf-token-table ?| 'alternative)
|
||||
(aset ebnf-bnf-token-table ?\} 'end-list)
|
||||
(aset ebnf-bnf-token-table ?/ 'list)
|
||||
(aset ebnf-bnf-token-table ?+ 'one-or-more)
|
||||
(aset ebnf-bnf-token-table ?$ 'default)
|
||||
;; Override comment character:
|
||||
(aset ebnf-bnf-token-table ebnf-lex-comment-char 'comment)
|
||||
;; Override end of production character:
|
||||
(aset ebnf-bnf-token-table ebnf-lex-eop-char 'period)))
|
||||
|
||||
|
||||
(defun ebnf-bnf-lex ()
|
||||
"Lexical analyser for EBNF.
|
||||
|
||||
Return a lexical token.
|
||||
|
||||
See documentation for variable `ebnf-bnf-lex'."
|
||||
(if (>= (point) ebnf-limit)
|
||||
'end-of-input
|
||||
(let (token)
|
||||
;; skip spaces and comments
|
||||
(while (if (> (following-char) 255)
|
||||
(progn
|
||||
(setq token 'error)
|
||||
nil)
|
||||
(setq token (aref ebnf-bnf-token-table (following-char)))
|
||||
(cond
|
||||
((eq token 'space)
|
||||
(skip-chars-forward " \013\n\r\t" ebnf-limit)
|
||||
(< (point) ebnf-limit))
|
||||
((eq token 'comment)
|
||||
(ebnf-bnf-skip-comment))
|
||||
((eq token 'form-feed)
|
||||
(forward-char)
|
||||
(setq ebnf-action 'form-feed))
|
||||
(t nil)
|
||||
)))
|
||||
(setq ebnf-default-p nil)
|
||||
(cond
|
||||
;; end of input
|
||||
((>= (point) ebnf-limit)
|
||||
'end-of-input)
|
||||
;; error
|
||||
((eq token 'error)
|
||||
(error "Illegal character."))
|
||||
;; default
|
||||
((eq token 'default)
|
||||
(forward-char)
|
||||
(if (memq (aref ebnf-bnf-token-table (following-char))
|
||||
'(terminal non-terminal special))
|
||||
(prog1
|
||||
(ebnf-bnf-lex)
|
||||
(setq ebnf-default-p t))
|
||||
(error "Illegal `default' element.")))
|
||||
;; integer
|
||||
((eq token 'integer)
|
||||
(setq ebnf-bnf-lex (ebnf-buffer-substring "0-9"))
|
||||
'integer)
|
||||
;; special: ?special?
|
||||
((eq token 'special)
|
||||
(setq ebnf-bnf-lex (concat "?"
|
||||
(ebnf-string " ->@-~" ?\? "special")
|
||||
"?"))
|
||||
'special)
|
||||
;; terminal: "string"
|
||||
((eq token 'terminal)
|
||||
(setq ebnf-bnf-lex (ebnf-unescape-string (ebnf-get-string)))
|
||||
'terminal)
|
||||
;; non-terminal or terminal
|
||||
((eq token 'non-terminal)
|
||||
(setq ebnf-bnf-lex (ebnf-buffer-substring
|
||||
"!#%&'*-,0-:<>@-Z\\^-z~\240-\377"))
|
||||
(let ((case-fold-search ebnf-case-fold-search)
|
||||
match)
|
||||
(if (and ebnf-terminal-regexp
|
||||
(setq match (string-match ebnf-terminal-regexp
|
||||
ebnf-bnf-lex))
|
||||
(zerop match)
|
||||
(= (match-end 0) (length ebnf-bnf-lex)))
|
||||
'terminal
|
||||
'non-terminal)))
|
||||
;; end of list: }+, }*, }
|
||||
((eq token 'end-list)
|
||||
(forward-char)
|
||||
(cond
|
||||
((= (following-char) ?+)
|
||||
(forward-char)
|
||||
'end-one-or-more)
|
||||
((= (following-char) ?*)
|
||||
(forward-char)
|
||||
'end-zero-or-more)
|
||||
(t
|
||||
'end-zero-or-more)
|
||||
))
|
||||
;; alternative: |, ||
|
||||
((eq token 'alternative)
|
||||
(forward-char)
|
||||
(if (/= (following-char) ?|)
|
||||
'alternative
|
||||
(forward-char)
|
||||
'list-separator))
|
||||
;; miscellaneous: {, (, ), [, ], ., =, /, +, -, *
|
||||
(t
|
||||
(forward-char)
|
||||
token)
|
||||
))))
|
||||
|
||||
|
||||
(defconst ebnf-bnf-comment-chars "^\n\000-\010\016-\037\177-\237")
|
||||
|
||||
|
||||
(defun ebnf-bnf-skip-comment ()
|
||||
(forward-char)
|
||||
(cond
|
||||
;; open EPS file
|
||||
((and ebnf-eps-executing (= (following-char) ?\[))
|
||||
(ebnf-eps-add-context (ebnf-bnf-eps-filename)))
|
||||
;; close EPS file
|
||||
((and ebnf-eps-executing (= (following-char) ?\]))
|
||||
(ebnf-eps-remove-context (ebnf-bnf-eps-filename)))
|
||||
;; any other action in comment
|
||||
(t
|
||||
(setq ebnf-action (aref ebnf-comment-table (following-char)))
|
||||
(skip-chars-forward ebnf-bnf-comment-chars ebnf-limit))
|
||||
)
|
||||
;; check for a valid end of comment
|
||||
(cond ((>= (point) ebnf-limit)
|
||||
nil)
|
||||
((= (following-char) ?\n)
|
||||
(forward-char)
|
||||
t)
|
||||
(t
|
||||
(error "Illegal character."))
|
||||
))
|
||||
|
||||
|
||||
(defun ebnf-bnf-eps-filename ()
|
||||
(forward-char)
|
||||
(ebnf-buffer-substring ebnf-bnf-comment-chars))
|
||||
|
||||
|
||||
(defun ebnf-unescape-string (str)
|
||||
(let* ((len (length str))
|
||||
(size (1- len))
|
||||
(istr 0)
|
||||
(n-esc 0))
|
||||
;; count number of escapes
|
||||
(while (< istr size)
|
||||
(setq istr (+ istr
|
||||
(if (= (aref str istr) ?\\)
|
||||
(progn
|
||||
(setq n-esc (1+ n-esc))
|
||||
2)
|
||||
1))))
|
||||
(if (zerop n-esc)
|
||||
;; no escapes
|
||||
str
|
||||
;; at least one escape
|
||||
(let ((new (make-string (- len n-esc) ?\ ))
|
||||
(inew 0))
|
||||
;; eliminate all escapes
|
||||
(setq istr 0)
|
||||
(while (> n-esc 0)
|
||||
(and (= (aref str istr) ?\\)
|
||||
(setq istr (1+ istr)
|
||||
n-esc (1- n-esc)))
|
||||
(aset new inew (aref str istr))
|
||||
(setq inew (1+ inew)
|
||||
istr (1+ istr)))
|
||||
;; remaining string has no escape
|
||||
(while (< istr len)
|
||||
(aset new inew (aref str istr))
|
||||
(setq inew (1+ inew)
|
||||
istr (1+ istr)))
|
||||
new))))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
(provide 'ebnf-bnf)
|
||||
|
||||
|
||||
;;; ebnf-bnf.el ends here
|
607
lisp/progmodes/ebnf-iso.el
Normal file
607
lisp/progmodes/ebnf-iso.el
Normal file
@ -0,0 +1,607 @@
|
||||
;;; ebnf-iso --- Parser for ISO EBNF
|
||||
|
||||
;; Copyright (C) 1999 Vinicius Jose Latorre
|
||||
|
||||
;; 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:04:11 vinicius>
|
||||
;; Version: 1.4
|
||||
|
||||
;; This file is *NOT* (yet?) part of GNU Emacs.
|
||||
|
||||
;; This program 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)
|
||||
;; any later version.
|
||||
|
||||
;; This program 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.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;;
|
||||
;; This is part of ebnf2ps package.
|
||||
;;
|
||||
;; This package defines a parser for ISO EBNF.
|
||||
;;
|
||||
;; See ebnf2ps.el for documentation.
|
||||
;;
|
||||
;;
|
||||
;; ISO EBNF Syntax
|
||||
;; ---------------
|
||||
;;
|
||||
;; See the URL:
|
||||
;; `http://www.cl.cam.ac.uk/~mgk25/iso-ebnf.html'
|
||||
;; ("International Standard of the ISO EBNF Notation").
|
||||
;;
|
||||
;;
|
||||
;; ISO EBNF = syntax rule, {syntax rule};
|
||||
;;
|
||||
;; syntax rule = meta identifier, '=', definition list, ';';
|
||||
;;
|
||||
;; definition list = single definition, {'|', single definition};
|
||||
;;
|
||||
;; single definition = term, {',', term};
|
||||
;;
|
||||
;; term = factor, ['-', exception];
|
||||
;;
|
||||
;; exception = factor (* without <meta identifier> *);
|
||||
;;
|
||||
;; factor = [integer, '*'], primary;
|
||||
;;
|
||||
;; primary = optional sequence | repeated sequence | special sequence
|
||||
;; | grouped sequence | meta identifier | terminal string
|
||||
;; | empty;
|
||||
;;
|
||||
;; empty = ;
|
||||
;;
|
||||
;; optional sequence = '[', definition list, ']';
|
||||
;;
|
||||
;; repeated sequence = '{', definition list, '}';
|
||||
;;
|
||||
;; grouped sequence = '(', definition list, ')';
|
||||
;;
|
||||
;; terminal string = "'", character - "'", {character - "'"}, "'"
|
||||
;; | '"', character - '"', {character - '"'}, '"';
|
||||
;;
|
||||
;; special sequence = '?', {character - '?'}, '?';
|
||||
;;
|
||||
;; meta identifier = letter, { letter | decimal digit | ' ' };
|
||||
;;
|
||||
;; integer = decimal digit, {decimal digit};
|
||||
;;
|
||||
;; comment = '(*', {comment symbol}, '*)';
|
||||
;;
|
||||
;; comment symbol = comment (* <== NESTED COMMENT *)
|
||||
;; | terminal string | special sequence | character;
|
||||
;;
|
||||
;; letter = ? A-Z a-z ?;
|
||||
;;
|
||||
;; decimal digit = ? 0-9 ?;
|
||||
;;
|
||||
;; character = letter | decimal digit
|
||||
;; | ',' | '=' | '|' | '/' | '!' | '*' | '(' | ')' | '[' | ']' | '{'
|
||||
;; | '}' | "'" | '"' | '?' | '-' | ';' | '.' | ' ' | ':' | '+' | '_'
|
||||
;; | '%' | '@' | '&' | '#' | '$' | '<' | '>' | '\' | '^' | '`' | '~';
|
||||
;;
|
||||
;;
|
||||
;; There is also the following alternative representation:
|
||||
;;
|
||||
;; STANDARD ALTERNATIVE
|
||||
;; | ==> / or !
|
||||
;; [ ==> (/
|
||||
;; ] ==> /)
|
||||
;; { ==> (:
|
||||
;; } ==> :)
|
||||
;; ; ==> .
|
||||
;;
|
||||
;;
|
||||
;; Differences Between ISO EBNF And ebnf2ps ISO EBNF
|
||||
;; -------------------------------------------------
|
||||
;;
|
||||
;; ISO EBNF accepts the characters given by <character> production above,
|
||||
;; HORIZONTAL TAB (^I), VERTICAL TAB (^K), NEWLINE (^J or ^M) and FORM FEED
|
||||
;; (^L), any other characters are illegal. But ebnf2ps accepts also the
|
||||
;; european 8-bit accentuated characters (from \240 to \377).
|
||||
;;
|
||||
;;
|
||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;;; code:
|
||||
|
||||
|
||||
(require 'ebnf-otz)
|
||||
|
||||
|
||||
(defvar ebnf-iso-lex nil
|
||||
"Value returned by `ebnf-iso-lex' function.")
|
||||
|
||||
|
||||
(defconst ebnf-no-meta-identifier nil)
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Syntatic analyzer
|
||||
|
||||
|
||||
;;; ISO EBNF = syntax rule, {syntax rule};
|
||||
|
||||
(defun ebnf-iso-parser (start)
|
||||
"ISO EBNF parser."
|
||||
(let ((total (+ (- ebnf-limit start) 1))
|
||||
(bias (1- start))
|
||||
(origin (point))
|
||||
syntax-list token rule)
|
||||
(goto-char start)
|
||||
(setq token (ebnf-iso-lex))
|
||||
(and (eq token 'end-of-input)
|
||||
(error "Invalid ISO EBNF file format."))
|
||||
(while (not (eq token 'end-of-input))
|
||||
(ebnf-message-float
|
||||
"Parsing...%s%%"
|
||||
(/ (* (- (point) bias) 100.0) total))
|
||||
(setq token (ebnf-iso-syntax-rule token)
|
||||
rule (cdr token)
|
||||
token (car token))
|
||||
(or (ebnf-add-empty-rule-list rule)
|
||||
(setq syntax-list (cons rule syntax-list))))
|
||||
(goto-char origin)
|
||||
syntax-list))
|
||||
|
||||
|
||||
;;; syntax rule = meta identifier, '=', definition list, ';';
|
||||
|
||||
(defun ebnf-iso-syntax-rule (token)
|
||||
(let ((header ebnf-iso-lex)
|
||||
(action ebnf-action)
|
||||
body)
|
||||
(setq ebnf-action nil)
|
||||
(or (eq token 'non-terminal)
|
||||
(error "Invalid meta identifier syntax rule."))
|
||||
(or (eq (ebnf-iso-lex) 'equal)
|
||||
(error "Invalid syntax rule: missing `='."))
|
||||
(setq body (ebnf-iso-definition-list))
|
||||
(or (eq (car body) 'period)
|
||||
(error "Invalid syntax rule: missing `;' or `.'."))
|
||||
(setq body (cdr body))
|
||||
(ebnf-eps-add-production header)
|
||||
(cons (ebnf-iso-lex)
|
||||
(ebnf-make-production header body action))))
|
||||
|
||||
|
||||
;;; definition list = single definition, {'|', single definition};
|
||||
|
||||
(defun ebnf-iso-definition-list ()
|
||||
(let (body sequence)
|
||||
(while (eq (car (setq sequence (ebnf-iso-single-definition)))
|
||||
'alternative)
|
||||
(setq sequence (cdr sequence)
|
||||
body (cons sequence body)))
|
||||
(ebnf-token-alternative body sequence)))
|
||||
|
||||
|
||||
;;; single definition = term, {',', term};
|
||||
|
||||
(defun ebnf-iso-single-definition ()
|
||||
(let (token seq term)
|
||||
(while (and (setq term (ebnf-iso-term (ebnf-iso-lex))
|
||||
token (car term)
|
||||
term (cdr term))
|
||||
(eq token 'catenate))
|
||||
(setq seq (cons term seq)))
|
||||
(cons token
|
||||
(cond
|
||||
;; null sequence
|
||||
((null seq)
|
||||
term)
|
||||
;; sequence with only one element
|
||||
((and (null term) (= (length seq) 1))
|
||||
(car seq))
|
||||
;; a real sequence
|
||||
(t
|
||||
(ebnf-make-sequence (nreverse (cons term seq))))
|
||||
))))
|
||||
|
||||
|
||||
;;; term = factor, ['-', exception];
|
||||
;;;
|
||||
;;; exception = factor (* without <meta identifier> *);
|
||||
|
||||
(defun ebnf-iso-term (token)
|
||||
(let ((factor (ebnf-iso-factor token)))
|
||||
(if (not (eq (car factor) 'except))
|
||||
;; factor
|
||||
factor
|
||||
;; factor - exception
|
||||
(let ((ebnf-no-meta-identifier t))
|
||||
(ebnf-token-except (cdr factor) (ebnf-iso-factor (ebnf-iso-lex)))))))
|
||||
|
||||
|
||||
;;; factor = [integer, '*'], primary;
|
||||
|
||||
(defun ebnf-iso-factor (token)
|
||||
(if (eq token 'integer)
|
||||
(let ((times ebnf-iso-lex))
|
||||
(or (eq (ebnf-iso-lex) 'repeat)
|
||||
(error "Missing `*'."))
|
||||
(ebnf-token-repeat times (ebnf-iso-primary (ebnf-iso-lex))))
|
||||
(ebnf-iso-primary token)))
|
||||
|
||||
|
||||
;;; primary = optional sequence | repeated sequence | special sequence
|
||||
;;; | grouped sequence | meta identifier | terminal string
|
||||
;;; | empty;
|
||||
;;;
|
||||
;;; empty = ;
|
||||
;;;
|
||||
;;; optional sequence = '[', definition list, ']';
|
||||
;;;
|
||||
;;; repeated sequence = '{', definition list, '}';
|
||||
;;;
|
||||
;;; grouped sequence = '(', definition list, ')';
|
||||
;;;
|
||||
;;; terminal string = "'", character - "'", {character - "'"}, "'"
|
||||
;;; | '"', character - '"', {character - '"'}, '"';
|
||||
;;;
|
||||
;;; special sequence = '?', {character - '?'}, '?';
|
||||
;;;
|
||||
;;; meta identifier = letter, {letter | decimal digit};
|
||||
|
||||
(defun ebnf-iso-primary (token)
|
||||
(let ((primary
|
||||
(cond
|
||||
;; terminal string
|
||||
((eq token 'terminal)
|
||||
(ebnf-make-terminal ebnf-iso-lex))
|
||||
;; meta identifier
|
||||
((eq token 'non-terminal)
|
||||
(ebnf-make-non-terminal ebnf-iso-lex))
|
||||
;; special sequence
|
||||
((eq token 'special)
|
||||
(ebnf-make-special ebnf-iso-lex))
|
||||
;; grouped sequence
|
||||
((eq token 'begin-group)
|
||||
(let ((body (ebnf-iso-definition-list)))
|
||||
(or (eq (car body) 'end-group)
|
||||
(error "Missing `)'."))
|
||||
(cdr body)))
|
||||
;; optional sequence
|
||||
((eq token 'begin-optional)
|
||||
(let ((body (ebnf-iso-definition-list)))
|
||||
(or (eq (car body) 'end-optional)
|
||||
(error "Missing `]' or `/)'."))
|
||||
(ebnf-token-optional (cdr body))))
|
||||
;; repeated sequence
|
||||
((eq token 'begin-zero-or-more)
|
||||
(let* ((body (ebnf-iso-definition-list))
|
||||
(repeat (cdr body)))
|
||||
(or (eq (car body) 'end-zero-or-more)
|
||||
(error "Missing `}' or `:)'."))
|
||||
(ebnf-make-zero-or-more repeat)))
|
||||
;; empty
|
||||
(t
|
||||
nil)
|
||||
)))
|
||||
(cons (if primary
|
||||
(ebnf-iso-lex)
|
||||
token)
|
||||
primary)))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Lexical analyzer
|
||||
|
||||
|
||||
(defconst ebnf-iso-token-table
|
||||
;; control character & 8-bit character are set to `error'
|
||||
(let ((table (make-vector 256 'error))
|
||||
(char ?\040))
|
||||
;; printable character
|
||||
(while (< char ?\060)
|
||||
(aset table char 'character)
|
||||
(setq char (1+ char)))
|
||||
;; digits:
|
||||
(while (< char ?\072)
|
||||
(aset table char 'integer)
|
||||
(setq char (1+ char)))
|
||||
(while (< char ?\101)
|
||||
(aset table char 'character)
|
||||
(setq char (1+ char)))
|
||||
;; upper case letters:
|
||||
(while (< char ?\133)
|
||||
(aset table char 'non-terminal)
|
||||
(setq char (1+ char)))
|
||||
(while (< char ?\141)
|
||||
(aset table char 'character)
|
||||
(setq char (1+ char)))
|
||||
;; lower case letters:
|
||||
(while (< char ?\173)
|
||||
(aset table char 'non-terminal)
|
||||
(setq char (1+ char)))
|
||||
(while (< char ?\177)
|
||||
(aset table char 'character)
|
||||
(setq char (1+ char)))
|
||||
;; European 8-bit accentuated characters:
|
||||
(setq char ?\240)
|
||||
(while (< char ?\400)
|
||||
(aset table char 'non-terminal)
|
||||
(setq char (1+ char)))
|
||||
;; Override space characters:
|
||||
(aset table ?\013 'space) ; [VT] vertical tab
|
||||
(aset table ?\n 'space) ; [NL] linefeed
|
||||
(aset table ?\r 'space) ; [CR] carriage return
|
||||
(aset table ?\t 'space) ; [HT] horizontal tab
|
||||
(aset table ?\ 'space) ; [SP] space
|
||||
;; Override form feed character:
|
||||
(aset table ?\f 'form-feed) ; [FF] form feed
|
||||
;; Override other lexical characters:
|
||||
(aset table ?\" 'double-terminal)
|
||||
(aset table ?\' 'single-terminal)
|
||||
(aset table ?\? 'special)
|
||||
(aset table ?* 'repeat)
|
||||
(aset table ?, 'catenate)
|
||||
(aset table ?- 'except)
|
||||
(aset table ?= 'equal)
|
||||
(aset table ?\) 'end-group)
|
||||
table)
|
||||
"Vector used to map characters to a lexical token.")
|
||||
|
||||
|
||||
(defun ebnf-iso-initialize ()
|
||||
"Initialize ISO EBNF token table."
|
||||
(if ebnf-iso-alternative-p
|
||||
;; Override alternative lexical characters:
|
||||
(progn
|
||||
(aset ebnf-iso-token-table ?\( 'left-parenthesis)
|
||||
(aset ebnf-iso-token-table ?\[ 'character)
|
||||
(aset ebnf-iso-token-table ?\] 'character)
|
||||
(aset ebnf-iso-token-table ?\{ 'character)
|
||||
(aset ebnf-iso-token-table ?\} 'character)
|
||||
(aset ebnf-iso-token-table ?| 'character)
|
||||
(aset ebnf-iso-token-table ?\; 'character)
|
||||
(aset ebnf-iso-token-table ?/ 'slash)
|
||||
(aset ebnf-iso-token-table ?! 'alternative)
|
||||
(aset ebnf-iso-token-table ?: 'colon)
|
||||
(aset ebnf-iso-token-table ?. 'period))
|
||||
;; Override standard lexical characters:
|
||||
(aset ebnf-iso-token-table ?\( 'begin-parenthesis)
|
||||
(aset ebnf-iso-token-table ?\[ 'begin-optional)
|
||||
(aset ebnf-iso-token-table ?\] 'end-optional)
|
||||
(aset ebnf-iso-token-table ?\{ 'begin-zero-or-more)
|
||||
(aset ebnf-iso-token-table ?\} 'end-zero-or-more)
|
||||
(aset ebnf-iso-token-table ?| 'alternative)
|
||||
(aset ebnf-iso-token-table ?\; 'period)
|
||||
(aset ebnf-iso-token-table ?/ 'character)
|
||||
(aset ebnf-iso-token-table ?! 'character)
|
||||
(aset ebnf-iso-token-table ?: 'character)
|
||||
(aset ebnf-iso-token-table ?. 'character)))
|
||||
|
||||
|
||||
(defun ebnf-iso-lex ()
|
||||
"Lexical analyser for ISO EBNF.
|
||||
|
||||
Return a lexical token.
|
||||
|
||||
See documentation for variable `ebnf-iso-lex'."
|
||||
(if (>= (point) ebnf-limit)
|
||||
'end-of-input
|
||||
(let (token)
|
||||
;; skip spaces and comments
|
||||
(while (if (> (following-char) 255)
|
||||
(progn
|
||||
(setq token 'error)
|
||||
nil)
|
||||
(setq token (aref ebnf-iso-token-table (following-char)))
|
||||
(cond
|
||||
((eq token 'space)
|
||||
(skip-chars-forward " \013\n\r\t" ebnf-limit)
|
||||
(< (point) ebnf-limit))
|
||||
((or (eq token 'begin-parenthesis)
|
||||
(eq token 'left-parenthesis))
|
||||
(forward-char)
|
||||
(if (/= (following-char) ?*)
|
||||
;; no comment
|
||||
nil
|
||||
;; comment
|
||||
(ebnf-iso-skip-comment)
|
||||
t))
|
||||
((eq token 'form-feed)
|
||||
(forward-char)
|
||||
(setq ebnf-action 'form-feed))
|
||||
(t nil)
|
||||
)))
|
||||
(cond
|
||||
;; end of input
|
||||
((>= (point) ebnf-limit)
|
||||
'end-of-input)
|
||||
;; error
|
||||
((eq token 'error)
|
||||
(error "Illegal character."))
|
||||
;; integer
|
||||
((eq token 'integer)
|
||||
(setq ebnf-iso-lex (ebnf-buffer-substring "0-9"))
|
||||
'integer)
|
||||
;; special: ?special?
|
||||
((eq token 'special)
|
||||
(setq ebnf-iso-lex (concat "?"
|
||||
(ebnf-string " ->@-~" ?\? "special")
|
||||
"?"))
|
||||
'special)
|
||||
;; terminal: "string"
|
||||
((eq token 'double-terminal)
|
||||
(setq ebnf-iso-lex (ebnf-string " !#-~" ?\" "terminal"))
|
||||
'terminal)
|
||||
;; terminal: 'string'
|
||||
((eq token 'single-terminal)
|
||||
(setq ebnf-iso-lex (ebnf-string " -&(-~" ?\' "terminal"))
|
||||
'terminal)
|
||||
;; non-terminal
|
||||
((eq token 'non-terminal)
|
||||
(setq ebnf-iso-lex (ebnf-iso-normalize
|
||||
(ebnf-trim-right
|
||||
(ebnf-buffer-substring " 0-9A-Za-z\240-\377"))))
|
||||
(and ebnf-no-meta-identifier
|
||||
(error "Exception sequence should not contain a meta identifier."))
|
||||
'non-terminal)
|
||||
;; begin optional, begin list or begin group
|
||||
((eq token 'left-parenthesis)
|
||||
(forward-char)
|
||||
(cond ((= (following-char) ?/)
|
||||
(forward-char)
|
||||
'begin-optional)
|
||||
((= (following-char) ?:)
|
||||
(forward-char)
|
||||
'begin-zero-or-more)
|
||||
(t
|
||||
'begin-group)
|
||||
))
|
||||
;; end optional or alternative
|
||||
((eq token 'slash)
|
||||
(forward-char)
|
||||
(if (/= (following-char) ?\))
|
||||
'alternative
|
||||
(forward-char)
|
||||
'end-optional))
|
||||
;; end list
|
||||
((eq token 'colon)
|
||||
(forward-char)
|
||||
(if (/= (following-char) ?\))
|
||||
'character
|
||||
(forward-char)
|
||||
'end-zero-or-more))
|
||||
;; begin group
|
||||
((eq token 'begin-parenthesis)
|
||||
'begin-group)
|
||||
;; miscellaneous
|
||||
(t
|
||||
(forward-char)
|
||||
token)
|
||||
))))
|
||||
|
||||
|
||||
(defconst ebnf-iso-comment-chars "^*(\000-\010\016-\037\177-\237")
|
||||
|
||||
|
||||
(defun ebnf-iso-skip-comment ()
|
||||
(forward-char)
|
||||
(cond
|
||||
;; open EPS file
|
||||
((and ebnf-eps-executing (= (following-char) ?\[))
|
||||
(ebnf-eps-add-context (ebnf-iso-eps-filename)))
|
||||
;; close EPS file
|
||||
((and ebnf-eps-executing (= (following-char) ?\]))
|
||||
(ebnf-eps-remove-context (ebnf-iso-eps-filename)))
|
||||
;; any other action in comment
|
||||
(t
|
||||
(setq ebnf-action (aref ebnf-comment-table (following-char))))
|
||||
)
|
||||
(let ((pair 1))
|
||||
(while (> pair 0)
|
||||
(skip-chars-forward ebnf-iso-comment-chars ebnf-limit)
|
||||
(cond ((>= (point) ebnf-limit)
|
||||
(error "Missing end of comment: `*)'."))
|
||||
((= (following-char) ?*)
|
||||
(skip-chars-forward "*" ebnf-limit)
|
||||
(when (= (following-char) ?\))
|
||||
;; end of comment
|
||||
(forward-char)
|
||||
(setq pair (1- pair))))
|
||||
((= (following-char) ?\()
|
||||
(skip-chars-forward "(" ebnf-limit)
|
||||
(when (= (following-char) ?*)
|
||||
;; beginning of comment
|
||||
(forward-char)
|
||||
(setq pair (1+ pair))))
|
||||
(t
|
||||
(error "Illegal character."))
|
||||
))))
|
||||
|
||||
|
||||
(defun ebnf-iso-eps-filename ()
|
||||
(forward-char)
|
||||
(buffer-substring-no-properties
|
||||
(point)
|
||||
(let ((chars (concat ebnf-iso-comment-chars "\n"))
|
||||
found)
|
||||
(while (not found)
|
||||
(skip-chars-forward chars ebnf-limit)
|
||||
(setq found
|
||||
(cond ((>= (point) ebnf-limit)
|
||||
(point))
|
||||
((= (following-char) ?*)
|
||||
(skip-chars-forward "*" ebnf-limit)
|
||||
(if (/= (following-char) ?\))
|
||||
nil
|
||||
(backward-char)
|
||||
(point)))
|
||||
((= (following-char) ?\()
|
||||
(forward-char)
|
||||
(if (/= (following-char) ?*)
|
||||
nil
|
||||
(backward-char)
|
||||
(point)))
|
||||
(t
|
||||
(point))
|
||||
)))
|
||||
found)))
|
||||
|
||||
|
||||
(defun ebnf-iso-normalize (str)
|
||||
(if (not ebnf-iso-normalize-p)
|
||||
str
|
||||
(let ((len (length str))
|
||||
(stri 0)
|
||||
(spaces 0))
|
||||
;; count exceeding spaces
|
||||
(while (< stri len)
|
||||
(if (/= (aref str stri) ?\ )
|
||||
(setq stri (1+ stri))
|
||||
(setq stri (1+ stri))
|
||||
(while (and (< stri len) (= (aref str stri) ?\ ))
|
||||
(setq stri (1+ stri)
|
||||
spaces (1+ spaces)))))
|
||||
(if (zerop spaces)
|
||||
;; no exceeding space
|
||||
str
|
||||
;; at least one exceeding space
|
||||
(let ((new (make-string (- len spaces) ?\ ))
|
||||
(newi 0))
|
||||
;; eliminate exceeding spaces
|
||||
(setq stri 0)
|
||||
(while (> spaces 0)
|
||||
(if (/= (aref str stri) ?\ )
|
||||
(progn
|
||||
(aset new newi (aref str stri))
|
||||
(setq stri (1+ stri)
|
||||
newi (1+ newi)))
|
||||
(aset new newi (aref str stri))
|
||||
(setq stri (1+ stri)
|
||||
newi (1+ newi))
|
||||
(while (and (> spaces 0) (= (aref str stri) ?\ ))
|
||||
(setq stri (1+ stri)
|
||||
spaces (1- spaces)))))
|
||||
;; remaining is normalized
|
||||
(while (< stri len)
|
||||
(aset new newi (aref str stri))
|
||||
(setq stri (1+ stri)
|
||||
newi (1+ newi)))
|
||||
new)))))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
(provide 'ebnf-iso)
|
||||
|
||||
|
||||
;;; ebnf-iso.el ends here
|
661
lisp/progmodes/ebnf-otz.el
Normal file
661
lisp/progmodes/ebnf-otz.el
Normal file
@ -0,0 +1,661 @@
|
||||
;;; ebnf-otz --- Syntatic chart OpTimiZer
|
||||
|
||||
;; Copyright (C) 1999 Vinicius Jose Latorre
|
||||
|
||||
;; 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:03:10 vinicius>
|
||||
;; Version: 1.0
|
||||
|
||||
;; This file is *NOT* (yet?) part of GNU Emacs.
|
||||
|
||||
;; This program 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)
|
||||
;; any later version.
|
||||
|
||||
;; This program 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.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;;
|
||||
;; This is part of ebnf2ps package.
|
||||
;;
|
||||
;; This package defines an optimizer for ebnf2ps.
|
||||
;;
|
||||
;; See ebnf2ps.el for documentation.
|
||||
;;
|
||||
;;
|
||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;;; code:
|
||||
|
||||
|
||||
(require 'ebnf2ps)
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
(defvar ebnf-empty-rule-list nil
|
||||
"List of empty rule name.")
|
||||
|
||||
|
||||
(defun ebnf-add-empty-rule-list (rule)
|
||||
"Add empty RULE in `ebnf-empty-rule-list'."
|
||||
(and ebnf-ignore-empty-rule
|
||||
(eq (ebnf-node-kind (ebnf-node-production rule))
|
||||
'ebnf-generate-empty)
|
||||
(setq ebnf-empty-rule-list (cons (ebnf-node-name rule)
|
||||
ebnf-empty-rule-list))))
|
||||
|
||||
|
||||
(defun ebnf-otz-initialize ()
|
||||
"Initialize optimizer."
|
||||
(setq ebnf-empty-rule-list nil))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Eliminate empty rules
|
||||
|
||||
|
||||
(defun ebnf-eliminate-empty-rules (syntax-list)
|
||||
"Eliminate empty rules."
|
||||
(while ebnf-empty-rule-list
|
||||
(let ((ebnf-total (length syntax-list))
|
||||
(ebnf-nprod 0)
|
||||
(prod-list syntax-list)
|
||||
new-list before)
|
||||
(while prod-list
|
||||
(ebnf-message-info "Eliminating empty rules")
|
||||
(let ((rule (car prod-list)))
|
||||
;; if any non-terminal pertains to ebnf-empty-rule-list
|
||||
;; then eliminate non-terminal from rule
|
||||
(if (ebnf-eliminate-empty rule)
|
||||
(setq before prod-list)
|
||||
;; eliminate empty rule from syntax-list
|
||||
(setq new-list (cons (ebnf-node-name rule) new-list))
|
||||
(if before
|
||||
(setcdr before (cdr prod-list))
|
||||
(setq syntax-list (cdr syntax-list)))))
|
||||
(setq prod-list (cdr prod-list)))
|
||||
(setq ebnf-empty-rule-list new-list)))
|
||||
syntax-list)
|
||||
|
||||
|
||||
;; [production width-func entry height width name production action]
|
||||
;; [sequence width-func entry height width list]
|
||||
;; [alternative width-func entry height width list]
|
||||
;; [non-terminal width-func entry height width name default]
|
||||
;; [empty width-func entry height width]
|
||||
;; [terminal width-func entry height width name default]
|
||||
;; [special width-func entry height width name default]
|
||||
|
||||
(defun ebnf-eliminate-empty (rule)
|
||||
(let ((kind (ebnf-node-kind rule)))
|
||||
(cond
|
||||
;; non-terminal
|
||||
((eq kind 'ebnf-generate-non-terminal)
|
||||
(if (member (ebnf-node-name rule) ebnf-empty-rule-list)
|
||||
nil
|
||||
rule))
|
||||
;; sequence
|
||||
((eq kind 'ebnf-generate-sequence)
|
||||
(let ((seq (ebnf-node-list rule))
|
||||
(header (ebnf-node-list rule))
|
||||
before elt)
|
||||
(while seq
|
||||
(setq elt (car seq))
|
||||
(if (ebnf-eliminate-empty elt)
|
||||
(setq before seq)
|
||||
(if before
|
||||
(setcdr before (cdr seq))
|
||||
(setq header (cdr header))))
|
||||
(setq seq (cdr seq)))
|
||||
(when header
|
||||
(ebnf-node-list rule header)
|
||||
rule)))
|
||||
;; alternative
|
||||
((eq kind 'ebnf-generate-alternative)
|
||||
(let ((seq (ebnf-node-list rule))
|
||||
(header (ebnf-node-list rule))
|
||||
before elt)
|
||||
(while seq
|
||||
(setq elt (car seq))
|
||||
(if (ebnf-eliminate-empty elt)
|
||||
(setq before seq)
|
||||
(if before
|
||||
(setcdr before (cdr seq))
|
||||
(setq header (cdr header))))
|
||||
(setq seq (cdr seq)))
|
||||
(when header
|
||||
(if (= (length header) 1)
|
||||
(car header)
|
||||
(ebnf-node-list rule header)
|
||||
rule))))
|
||||
;; production
|
||||
((eq kind 'ebnf-generate-production)
|
||||
(let ((prod (ebnf-eliminate-empty (ebnf-node-production rule))))
|
||||
(when prod
|
||||
(ebnf-node-production rule prod)
|
||||
rule)))
|
||||
;; terminal, special and empty
|
||||
(t
|
||||
rule)
|
||||
)))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Optimizations
|
||||
|
||||
|
||||
;; *To be implemented*:
|
||||
;; left recursion:
|
||||
;; A = B | A C B | A C D. ==> A = B {C (B | D)}*.
|
||||
|
||||
;; right recursion:
|
||||
;; A = B | C A. ==> A = {C}* B.
|
||||
;; A = B | D | C A | E A. ==> A = { C | E }* ( B | D ).
|
||||
|
||||
;; optional:
|
||||
;; A = B | C B. ==> A = [C] B.
|
||||
;; A = B | B C. ==> A = B [C].
|
||||
;; A = D | B D | B C D. ==> A = [B [C]] D.
|
||||
|
||||
|
||||
;; *Already implemented*:
|
||||
;; left recursion:
|
||||
;; A = B | A C. ==> A = B {C}*.
|
||||
;; A = B | A B. ==> A = {B}+.
|
||||
;; A = | A B. ==> A = {B}*.
|
||||
;; A = B | A C B. ==> A = {B || C}+.
|
||||
;; A = B | D | A C | A E. ==> A = ( B | D ) { C | E }*.
|
||||
|
||||
;; optional:
|
||||
;; A = B | . ==> A = [B].
|
||||
;; A = | B . ==> A = [B].
|
||||
|
||||
;; factoration:
|
||||
;; A = B C | B D. ==> A = B (C | D).
|
||||
;; A = C B | D B. ==> A = (C | D) B.
|
||||
;; A = B C E | B D E. ==> A = B (C | D) E.
|
||||
|
||||
;; none:
|
||||
;; A = B | C | . ==> A = B | C | .
|
||||
;; A = B | C A D. ==> A = B | C A D.
|
||||
|
||||
(defun ebnf-optimize (syntax-list)
|
||||
"Syntatic chart optimizer."
|
||||
(if (not ebnf-optimize)
|
||||
syntax-list
|
||||
(let ((ebnf-total (length syntax-list))
|
||||
(ebnf-nprod 0)
|
||||
new)
|
||||
(while syntax-list
|
||||
(setq new (cons (ebnf-optimize1 (car syntax-list)) new)
|
||||
syntax-list (cdr syntax-list)))
|
||||
(nreverse new))))
|
||||
|
||||
|
||||
;; left recursion:
|
||||
;; 1. A = B | A C. ==> A = B {C}*.
|
||||
;; 2. A = B | A B. ==> A = {B}+.
|
||||
;; 3. A = | A B. ==> A = {B}*.
|
||||
;; 4. A = B | A C B. ==> A = {B || C}+.
|
||||
;; 5. A = B | D | A C | A E. ==> A = ( B | D ) { C | E }*.
|
||||
|
||||
;; optional:
|
||||
;; 6. A = B | . ==> A = [B].
|
||||
;; 7. A = | B . ==> A = [B].
|
||||
|
||||
;; factoration:
|
||||
;; 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.
|
||||
|
||||
(defun ebnf-optimize1 (prod)
|
||||
(ebnf-message-info "Optimizing syntatic chart")
|
||||
(let ((production (ebnf-node-production prod)))
|
||||
(and (eq (ebnf-node-kind production) 'ebnf-generate-alternative)
|
||||
(let* ((hlist (ebnf-split-header-prefix
|
||||
(ebnf-node-list production)
|
||||
(ebnf-node-name prod)))
|
||||
(nlist (car hlist))
|
||||
(zlist (cdr hlist))
|
||||
(elist (ebnf-split-header-suffix nlist zlist)))
|
||||
(ebnf-node-production
|
||||
prod
|
||||
(cond
|
||||
;; cases 2., 4.
|
||||
(elist
|
||||
(and (eq elist t)
|
||||
(setq elist nil))
|
||||
(setq elist (or (ebnf-prefix-suffix elist)
|
||||
elist))
|
||||
(let* ((nl (ebnf-extract-empty nlist))
|
||||
(el (or (ebnf-prefix-suffix (cdr nl))
|
||||
(ebnf-create-alternative (cdr nl)))))
|
||||
(if (car nl)
|
||||
(ebnf-make-zero-or-more el elist)
|
||||
(ebnf-make-one-or-more el elist))))
|
||||
;; cases 1., 3., 5.
|
||||
(zlist
|
||||
(let* ((xlist (cdr (ebnf-extract-empty zlist)))
|
||||
(znode (ebnf-make-zero-or-more
|
||||
(or (ebnf-prefix-suffix xlist)
|
||||
(ebnf-create-alternative xlist))))
|
||||
(nnode (ebnf-map-list-to-optional nlist)))
|
||||
(and nnode
|
||||
(setq nlist (list nnode)))
|
||||
(if (or (null nlist)
|
||||
(and (= (length nlist) 1)
|
||||
(eq (ebnf-node-kind (car nlist))
|
||||
'ebnf-generate-empty)))
|
||||
znode
|
||||
(ebnf-make-sequence
|
||||
(list (or (ebnf-prefix-suffix nlist)
|
||||
(ebnf-create-alternative nlist))
|
||||
znode)))))
|
||||
;; cases 6., 7.
|
||||
((ebnf-map-node-to-optional production)
|
||||
)
|
||||
;; cases 8., 9., 10.
|
||||
((ebnf-prefix-suffix nlist)
|
||||
)
|
||||
;; none
|
||||
(t
|
||||
production)
|
||||
))))
|
||||
prod))
|
||||
|
||||
|
||||
(defun ebnf-split-header-prefix (node-list header)
|
||||
(let* ((hlist (ebnf-split-header-prefix1 node-list header))
|
||||
(nlist (car hlist))
|
||||
zlist empty-p)
|
||||
(while (setq hlist (cdr hlist))
|
||||
(let ((elt (car hlist)))
|
||||
(if (eq (ebnf-node-kind elt) 'ebnf-generate-sequence)
|
||||
(setq zlist (cons
|
||||
(let ((seq (cdr (ebnf-node-list elt))))
|
||||
(if (= (length seq) 1)
|
||||
(car seq)
|
||||
(ebnf-node-list elt seq)
|
||||
elt))
|
||||
zlist))
|
||||
(setq empty-p t))))
|
||||
(and empty-p
|
||||
(setq zlist (cons (ebnf-make-empty)
|
||||
zlist)))
|
||||
(cons nlist (nreverse zlist))))
|
||||
|
||||
|
||||
(defun ebnf-split-header-prefix1 (node-list header)
|
||||
(let (hlist nlist)
|
||||
(while node-list
|
||||
(if (ebnf-node-equal-header (car node-list) header)
|
||||
(setq hlist (cons (car node-list) hlist))
|
||||
(setq nlist (cons (car node-list) nlist)))
|
||||
(setq node-list (cdr node-list)))
|
||||
(cons (nreverse nlist) (nreverse hlist))))
|
||||
|
||||
|
||||
(defun ebnf-node-equal-header (node header)
|
||||
(let ((kind (ebnf-node-kind node)))
|
||||
(cond
|
||||
((eq kind 'ebnf-generate-sequence)
|
||||
(ebnf-node-equal-header (car (ebnf-node-list node)) header))
|
||||
((eq kind 'ebnf-generate-non-terminal)
|
||||
(string= (ebnf-node-name node) header))
|
||||
(t
|
||||
nil)
|
||||
)))
|
||||
|
||||
|
||||
(defun ebnf-map-node-to-optional (node)
|
||||
(and (eq (ebnf-node-kind node) 'ebnf-generate-alternative)
|
||||
(ebnf-map-list-to-optional (ebnf-node-list node))))
|
||||
|
||||
|
||||
(defun ebnf-map-list-to-optional (nlist)
|
||||
(and (= (length nlist) 2)
|
||||
(let ((first (nth 0 nlist))
|
||||
(second (nth 1 nlist)))
|
||||
(cond
|
||||
;; empty second
|
||||
((eq (ebnf-node-kind first) 'ebnf-generate-empty)
|
||||
(ebnf-make-optional second))
|
||||
;; first empty
|
||||
((eq (ebnf-node-kind second) 'ebnf-generate-empty)
|
||||
(ebnf-make-optional first))
|
||||
;; first second
|
||||
(t
|
||||
nil)
|
||||
))))
|
||||
|
||||
|
||||
(defun ebnf-extract-empty (elist)
|
||||
(let ((now elist)
|
||||
before empty-p)
|
||||
(while now
|
||||
(if (not (eq (ebnf-node-kind (car now)) 'ebnf-generate-empty))
|
||||
(setq before now)
|
||||
(setq empty-p t)
|
||||
(if before
|
||||
(setcdr before (cdr now))
|
||||
(setq elist (cdr elist))))
|
||||
(setq now (cdr now)))
|
||||
(cons empty-p elist)))
|
||||
|
||||
|
||||
(defun ebnf-split-header-suffix (nlist zlist)
|
||||
(let (new empty-p)
|
||||
(and (cond
|
||||
((= (length nlist) 1)
|
||||
(let ((ok t)
|
||||
(elt (car nlist)))
|
||||
(while (and ok zlist)
|
||||
(setq ok (ebnf-split-header-suffix1 elt (car zlist))
|
||||
zlist (cdr zlist))
|
||||
(if (eq ok t)
|
||||
(setq empty-p t)
|
||||
(setq new (cons ok new))))
|
||||
ok))
|
||||
((= (length nlist) (length zlist))
|
||||
(let ((ok t))
|
||||
(while (and ok zlist)
|
||||
(setq ok (ebnf-split-header-suffix1 (car nlist) (car zlist))
|
||||
nlist (cdr nlist)
|
||||
zlist (cdr zlist))
|
||||
(if (eq ok t)
|
||||
(setq empty-p t)
|
||||
(setq new (cons ok new))))
|
||||
ok))
|
||||
(t
|
||||
nil)
|
||||
)
|
||||
(let* ((lis (ebnf-unique-list new))
|
||||
(len (length lis)))
|
||||
(cond
|
||||
((zerop len)
|
||||
t)
|
||||
((= len 1)
|
||||
(setq lis (car lis))
|
||||
(if empty-p
|
||||
(ebnf-make-optional lis)
|
||||
lis))
|
||||
(t
|
||||
(and empty-p
|
||||
(setq lis (cons (ebnf-make-empty) lis)))
|
||||
(ebnf-create-alternative (nreverse lis)))
|
||||
)))))
|
||||
|
||||
|
||||
(defun ebnf-split-header-suffix1 (ne ze)
|
||||
(cond
|
||||
((eq (ebnf-node-kind ne) 'ebnf-generate-sequence)
|
||||
(and (eq (ebnf-node-kind ze) 'ebnf-generate-sequence)
|
||||
(let ((nl (ebnf-node-list ne))
|
||||
(zl (ebnf-node-list ze))
|
||||
len z)
|
||||
(and (>= (length zl) (length nl))
|
||||
(let ((ok t))
|
||||
(setq len (- (length zl) (length nl))
|
||||
z (nthcdr len zl))
|
||||
(while (and ok z)
|
||||
(setq ok (ebnf-node-equal (car z) (car nl))
|
||||
z (cdr z)
|
||||
nl (cdr nl)))
|
||||
ok)
|
||||
(if (zerop len)
|
||||
t
|
||||
(setcdr (nthcdr (1- len) zl) nil)
|
||||
ze)))))
|
||||
((eq (ebnf-node-kind ze) 'ebnf-generate-sequence)
|
||||
(let* ((zl (ebnf-node-list ze))
|
||||
(len (length zl)))
|
||||
(and (ebnf-node-equal ne (car (nthcdr (1- len) zl)))
|
||||
(cond
|
||||
((= len 1)
|
||||
t)
|
||||
((= len 2)
|
||||
(car zl))
|
||||
(t
|
||||
(setcdr (nthcdr (- len 2) zl) nil)
|
||||
ze)
|
||||
))))
|
||||
(t
|
||||
(ebnf-node-equal ne ze))
|
||||
))
|
||||
|
||||
|
||||
(defun ebnf-prefix-suffix (lis)
|
||||
(and lis (listp lis)
|
||||
(let* ((prefix (ebnf-split-prefix lis))
|
||||
(suffix (ebnf-split-suffix (cdr prefix)))
|
||||
(middle (cdr suffix)))
|
||||
(setq prefix (car prefix)
|
||||
suffix (car suffix))
|
||||
(and (or prefix suffix)
|
||||
(ebnf-make-sequence
|
||||
(nconc prefix
|
||||
(and middle
|
||||
(list (or (ebnf-map-list-to-optional middle)
|
||||
(ebnf-create-alternative middle))))
|
||||
suffix))))))
|
||||
|
||||
|
||||
(defun ebnf-split-prefix (lis)
|
||||
(let* ((len (length lis))
|
||||
(tail lis)
|
||||
(head (if (eq (ebnf-node-kind (car lis)) 'ebnf-generate-sequence)
|
||||
(ebnf-node-list (car lis))
|
||||
(list (car lis))))
|
||||
(ipre (1+ len)))
|
||||
;; determine prefix length
|
||||
(while (and (> ipre 0) (setq tail (cdr tail)))
|
||||
(let ((cur head)
|
||||
(this (if (eq (ebnf-node-kind (car tail)) 'ebnf-generate-sequence)
|
||||
(ebnf-node-list (car tail))
|
||||
(list (car tail))))
|
||||
(i 0))
|
||||
(while (and cur this
|
||||
(ebnf-node-equal (car cur) (car this)))
|
||||
(setq cur (cdr cur)
|
||||
this (cdr this)
|
||||
i (1+ i)))
|
||||
(setq ipre (min ipre i))))
|
||||
(if (or (zerop ipre) (> ipre len))
|
||||
;; no prefix at all
|
||||
(cons nil lis)
|
||||
(let* ((tail (nthcdr ipre head))
|
||||
;; get prefix
|
||||
(prefix (progn
|
||||
(and tail
|
||||
(setcdr (nthcdr (1- ipre) head) nil))
|
||||
head))
|
||||
empty-p before)
|
||||
;; adjust first element
|
||||
(if (or (not (eq (ebnf-node-kind (car lis)) 'ebnf-generate-sequence))
|
||||
(null tail))
|
||||
(setq lis (cdr lis)
|
||||
tail lis
|
||||
empty-p t)
|
||||
(if (= (length tail) 1)
|
||||
(setcar lis (car tail))
|
||||
(ebnf-node-list (car lis) tail))
|
||||
(setq tail (cdr lis)))
|
||||
;; eliminate prefix from lis based on ipre
|
||||
(while tail
|
||||
(let ((elt (car tail))
|
||||
rest)
|
||||
(if (and (eq (ebnf-node-kind elt) 'ebnf-generate-sequence)
|
||||
(setq rest (nthcdr ipre (ebnf-node-list elt))))
|
||||
(progn
|
||||
(if (= (length rest) 1)
|
||||
(setcar tail (car rest))
|
||||
(ebnf-node-list elt rest))
|
||||
(setq before tail))
|
||||
(setq empty-p t)
|
||||
(if before
|
||||
(setcdr before (cdr tail))
|
||||
(setq lis (cdr lis))))
|
||||
(setq tail (cdr tail))))
|
||||
(cons prefix (ebnf-unique-list
|
||||
(if empty-p
|
||||
(nconc lis (list (ebnf-make-empty)))
|
||||
lis)))))))
|
||||
|
||||
|
||||
(defun ebnf-split-suffix (lis)
|
||||
(let* ((len (length lis))
|
||||
(tail lis)
|
||||
(head (nreverse
|
||||
(if (eq (ebnf-node-kind (car lis)) 'ebnf-generate-sequence)
|
||||
(ebnf-node-list (car lis))
|
||||
(list (car lis)))))
|
||||
(isuf (1+ len)))
|
||||
;; determine suffix length
|
||||
(while (and (> isuf 0) (setq tail (cdr tail)))
|
||||
(let* ((cur head)
|
||||
(tlis (nreverse
|
||||
(if (eq (ebnf-node-kind (car tail)) 'ebnf-generate-sequence)
|
||||
(ebnf-node-list (car tail))
|
||||
(list (car tail)))))
|
||||
(this tlis)
|
||||
(i 0))
|
||||
(while (and cur this
|
||||
(ebnf-node-equal (car cur) (car this)))
|
||||
(setq cur (cdr cur)
|
||||
this (cdr this)
|
||||
i (1+ i)))
|
||||
(nreverse tlis)
|
||||
(setq isuf (min isuf i))))
|
||||
(setq head (nreverse head))
|
||||
(if (or (zerop isuf) (> isuf len))
|
||||
;; no suffix at all
|
||||
(cons nil lis)
|
||||
(let* ((n (- (length head) isuf))
|
||||
;; get suffix
|
||||
(suffix (nthcdr n head))
|
||||
(tail (and (> n 0)
|
||||
(progn
|
||||
(setcdr (nthcdr (1- n) head) nil)
|
||||
head)))
|
||||
before empty-p)
|
||||
;; adjust first element
|
||||
(if (or (not (eq (ebnf-node-kind (car lis)) 'ebnf-generate-sequence))
|
||||
(null tail))
|
||||
(setq lis (cdr lis)
|
||||
tail lis
|
||||
empty-p t)
|
||||
(if (= (length tail) 1)
|
||||
(setcar lis (car tail))
|
||||
(ebnf-node-list (car lis) tail))
|
||||
(setq tail (cdr lis)))
|
||||
;; eliminate suffix from lis based on isuf
|
||||
(while tail
|
||||
(let ((elt (car tail))
|
||||
rest)
|
||||
(if (and (eq (ebnf-node-kind elt) 'ebnf-generate-sequence)
|
||||
(setq rest (ebnf-node-list elt)
|
||||
n (- (length rest) isuf))
|
||||
(> n 0))
|
||||
(progn
|
||||
(if (= n 1)
|
||||
(setcar tail (car rest))
|
||||
(setcdr (nthcdr (1- n) rest) nil)
|
||||
(ebnf-node-list elt rest))
|
||||
(setq before tail))
|
||||
(setq empty-p t)
|
||||
(if before
|
||||
(setcdr before (cdr tail))
|
||||
(setq lis (cdr lis))))
|
||||
(setq tail (cdr tail))))
|
||||
(cons suffix (ebnf-unique-list
|
||||
(if empty-p
|
||||
(nconc lis (list (ebnf-make-empty)))
|
||||
lis)))))))
|
||||
|
||||
|
||||
(defun ebnf-unique-list (nlist)
|
||||
(let ((current nlist)
|
||||
before)
|
||||
(while current
|
||||
(let ((tail (cdr current))
|
||||
(head (car current))
|
||||
remove-p)
|
||||
(while tail
|
||||
(if (not (ebnf-node-equal head (car tail)))
|
||||
(setq tail (cdr tail))
|
||||
(setq remove-p t
|
||||
tail nil)
|
||||
(if before
|
||||
(setcdr before (cdr current))
|
||||
(setq nlist (cdr nlist)))))
|
||||
(or remove-p
|
||||
(setq before current))
|
||||
(setq current (cdr current))))
|
||||
nlist))
|
||||
|
||||
|
||||
(defun ebnf-node-equal (A B)
|
||||
(let ((kindA (ebnf-node-kind A))
|
||||
(kindB (ebnf-node-kind B)))
|
||||
(and (eq kindA kindB)
|
||||
(cond
|
||||
;; empty
|
||||
((eq kindA 'ebnf-generate-empty)
|
||||
t)
|
||||
;; non-terminal, terminal, special
|
||||
((memq kindA '(ebnf-generate-non-terminal
|
||||
ebnf-generate-terminal
|
||||
ebnf-generate-special))
|
||||
(string= (ebnf-node-name A) (ebnf-node-name B)))
|
||||
;; alternative, sequence
|
||||
((memq kindA '(ebnf-generate-alternative ; any order
|
||||
ebnf-generate-sequence)) ; order is important
|
||||
(let ((listA (ebnf-node-list A))
|
||||
(listB (ebnf-node-list B)))
|
||||
(and (= (length listA) (length listB))
|
||||
(let ((ok t))
|
||||
(while (and ok listA)
|
||||
(setq ok (ebnf-node-equal (car listA) (car listB))
|
||||
listA (cdr listA)
|
||||
listB (cdr listB)))
|
||||
ok))))
|
||||
;; production
|
||||
((eq kindA 'ebnf-generate-production)
|
||||
(and (string= (ebnf-node-name A) (ebnf-node-name B))
|
||||
(ebnf-node-equal (ebnf-node-production A)
|
||||
(ebnf-node-production B))))
|
||||
;; otherwise
|
||||
(t
|
||||
nil)
|
||||
))))
|
||||
|
||||
|
||||
(defun ebnf-create-alternative (alt)
|
||||
(if (> (length alt) 1)
|
||||
(ebnf-make-alternative alt)
|
||||
(car alt)))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
(provide 'ebnf-otz)
|
||||
|
||||
|
||||
;;; ebnf-otz.el ends here
|
487
lisp/progmodes/ebnf-yac.el
Normal file
487
lisp/progmodes/ebnf-yac.el
Normal file
@ -0,0 +1,487 @@
|
||||
;;; ebnf-yac --- Parser for Yacc/Bison
|
||||
|
||||
;; Copyright (C) 1999 Vinicius Jose Latorre
|
||||
|
||||
;; 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
|
||||
|
||||
;; This file is *NOT* (yet?) part of GNU Emacs.
|
||||
|
||||
;; This program 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)
|
||||
;; any later version.
|
||||
|
||||
;; This program 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.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;;
|
||||
;; This is part of ebnf2ps package.
|
||||
;;
|
||||
;; This package defines a parser for Yacc/Bison.
|
||||
;;
|
||||
;; See ebnf2ps.el for documentation.
|
||||
;;
|
||||
;;
|
||||
;; Yacc/Bison Syntax
|
||||
;; -----------------
|
||||
;;
|
||||
;; YACC = { YACC-Definitions }* "%%" { YACC-Rule }* [ "%%" [ YACC-Code ] ].
|
||||
;;
|
||||
;; YACC-Definitions = "%token" [ "<" Name ">" ] Name-List
|
||||
;; | "any other Yacc definition"
|
||||
;; .
|
||||
;;
|
||||
;; YACC-Code = "any C definition".
|
||||
;;
|
||||
;; YACC-Rule = Name ":" Alternative ";".
|
||||
;;
|
||||
;; Alternative = { Sequence || "|" }*.
|
||||
;;
|
||||
;; Sequence = { Factor }*.
|
||||
;;
|
||||
;; Factor = Name
|
||||
;; | "'" "character" "'"
|
||||
;; | "error"
|
||||
;; | "{" "C like commands" "}"
|
||||
;; .
|
||||
;;
|
||||
;; Name-List = { Name || "," }*.
|
||||
;;
|
||||
;; Name = "[A-Za-z][A-Za-z0-9_.]*".
|
||||
;;
|
||||
;; Comment = "/*" "any character, but the sequence \"*/\"" "*/"
|
||||
;; | "//" "any character" "\\n".
|
||||
;;
|
||||
;;
|
||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;;; code:
|
||||
|
||||
|
||||
(require 'ebnf-otz)
|
||||
|
||||
|
||||
(defvar ebnf-yac-lex nil
|
||||
"Value returned by `ebnf-yac-lex' function.")
|
||||
|
||||
|
||||
(defvar ebnf-yac-token-list nil
|
||||
"List of `%TOKEN' names.")
|
||||
|
||||
|
||||
(defvar ebnf-yac-skip-char nil
|
||||
"Non-nil means skip printable characters with no grammatical meaning.")
|
||||
|
||||
|
||||
(defvar ebnf-yac-error nil
|
||||
"Non-nil means \"error\" occured.")
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Syntatic analyzer
|
||||
|
||||
|
||||
;;; YACC = { YACC-Definitions }* "%%" { YACC-Rule }* [ "%%" [ YACC-Code ] ].
|
||||
;;;
|
||||
;;; YACC-Code = "any C definition".
|
||||
|
||||
(defun ebnf-yac-parser (start)
|
||||
"yacc/Bison parser."
|
||||
(let ((total (+ (- ebnf-limit start) 1))
|
||||
(bias (1- start))
|
||||
(origin (point))
|
||||
syntax-list token rule)
|
||||
(goto-char start)
|
||||
(setq token (ebnf-yac-lex))
|
||||
(and (eq token 'end-of-input)
|
||||
(error "Invalid Yacc/Bison file format."))
|
||||
(or (eq (ebnf-yac-definitions token) 'yac-separator)
|
||||
(error "Missing `%%%%'."))
|
||||
(setq token (ebnf-yac-lex))
|
||||
(while (not (memq token '(end-of-input yac-separator)))
|
||||
(ebnf-message-float
|
||||
"Parsing...%s%%"
|
||||
(/ (* (- (point) bias) 100.0) total))
|
||||
(setq token (ebnf-yac-rule token)
|
||||
rule (cdr token)
|
||||
token (car token))
|
||||
(or (ebnf-add-empty-rule-list rule)
|
||||
(setq syntax-list (cons rule syntax-list))))
|
||||
(goto-char origin)
|
||||
syntax-list))
|
||||
|
||||
|
||||
;;; YACC-Definitions = "%token" [ "<" Name ">" ] Name-List
|
||||
;;; | "any other Yacc definition"
|
||||
;;; .
|
||||
|
||||
(defun ebnf-yac-definitions (token)
|
||||
(let ((ebnf-yac-skip-char t))
|
||||
(while (not (memq token '(yac-separator end-of-input)))
|
||||
(setq token
|
||||
(cond
|
||||
;; "%token" [ "<" 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."))
|
||||
(or (eq (ebnf-yac-lex) 'close-angle)
|
||||
(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"
|
||||
(t
|
||||
(ebnf-yac-lex))
|
||||
)))
|
||||
token))
|
||||
|
||||
|
||||
;;; YACC-Rule = Name ":" Alternative ";".
|
||||
|
||||
(defun ebnf-yac-rule (token)
|
||||
(let ((header ebnf-yac-lex)
|
||||
(action ebnf-action)
|
||||
body)
|
||||
(setq ebnf-action nil)
|
||||
(or (eq token 'non-terminal)
|
||||
(error "Invalid rule name."))
|
||||
(or (eq (ebnf-yac-lex) 'colon)
|
||||
(error "Invalid rule: missing `:'."))
|
||||
(setq body (ebnf-yac-alternative))
|
||||
(or (eq (car body) 'period)
|
||||
(error "Invalid rule: missing `;'."))
|
||||
(setq body (cdr body))
|
||||
(ebnf-eps-add-production header)
|
||||
(cons (ebnf-yac-lex)
|
||||
(ebnf-make-production header body action))))
|
||||
|
||||
|
||||
;;; Alternative = { Sequence || "|" }*.
|
||||
|
||||
(defun ebnf-yac-alternative ()
|
||||
(let (body sequence)
|
||||
(while (eq (car (setq sequence (ebnf-yac-sequence)))
|
||||
'alternative)
|
||||
(and (setq sequence (cdr sequence))
|
||||
(setq body (cons sequence body))))
|
||||
(ebnf-token-alternative body sequence)))
|
||||
|
||||
|
||||
;;; Sequence = { Factor }*.
|
||||
|
||||
(defun ebnf-yac-sequence ()
|
||||
(let (ebnf-yac-error token seq factor)
|
||||
(while (setq token (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)))
|
||||
))))
|
||||
|
||||
|
||||
;;; Factor = Name
|
||||
;;; | "'" "character" "'"
|
||||
;;; | "error"
|
||||
;;; | "{" "C like commands" "}"
|
||||
;;; .
|
||||
|
||||
(defun ebnf-yac-factor (token)
|
||||
(cond
|
||||
;; 'character'
|
||||
((eq token 'terminal)
|
||||
(ebnf-make-terminal ebnf-yac-lex))
|
||||
;; Name
|
||||
((eq token 'non-terminal)
|
||||
(ebnf-make-non-terminal ebnf-yac-lex))
|
||||
;; "error"
|
||||
((eq token 'yac-error)
|
||||
(ebnf-make-special ebnf-yac-lex))
|
||||
;; not a factor
|
||||
(t
|
||||
nil)
|
||||
))
|
||||
|
||||
|
||||
;;; Name-List = { Name || "," }*.
|
||||
|
||||
(defun ebnf-yac-name-list (token)
|
||||
(let (names)
|
||||
(when (eq token 'non-terminal)
|
||||
(while (progn
|
||||
(setq names (cons ebnf-yac-lex names)
|
||||
token (ebnf-yac-lex))
|
||||
(eq token 'comma))
|
||||
(or (eq (ebnf-yac-lex) 'non-terminal)
|
||||
(error "Missing token name."))))
|
||||
(cons token names)))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Lexical analyzer
|
||||
|
||||
|
||||
;;; Name = "[A-Za-z][A-Za-z0-9_.]*".
|
||||
;;;
|
||||
;;; Comment = "/*" "any character, but the sequence \"*/\"" "*/"
|
||||
;;; | "//" "any character" "\\n".
|
||||
|
||||
(defconst ebnf-yac-token-table
|
||||
;; control character & 8-bit character are set to `error'
|
||||
(let ((table (make-vector 256 'error)))
|
||||
;; upper & lower case letters:
|
||||
(mapcar
|
||||
#'(lambda (char)
|
||||
(aset table char 'non-terminal))
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
|
||||
;; printable characters:
|
||||
(mapcar
|
||||
#'(lambda (char)
|
||||
(aset table char 'character))
|
||||
"!#$&()*+-.0123456789=?@[\\]^_`~")
|
||||
;; Override space characters:
|
||||
(aset table ?\n 'space) ; [NL] linefeed
|
||||
(aset table ?\r 'space) ; [CR] carriage return
|
||||
(aset table ?\t 'space) ; [HT] horizontal tab
|
||||
(aset table ?\ 'space) ; [SP] space
|
||||
;; Override form feed character:
|
||||
(aset table ?\f 'form-feed) ; [FF] form feed
|
||||
;; Override other lexical characters:
|
||||
(aset table ?< 'open-angle)
|
||||
(aset table ?> 'close-angle)
|
||||
(aset table ?, 'comma)
|
||||
(aset table ?% 'yac-pragma)
|
||||
(aset table ?/ 'slash)
|
||||
(aset table ?\{ 'yac-code)
|
||||
(aset table ?\" 'string)
|
||||
(aset table ?\' 'terminal)
|
||||
(aset table ?: 'colon)
|
||||
(aset table ?| 'alternative)
|
||||
(aset table ?\; 'period)
|
||||
table)
|
||||
"Vector used to map characters to a lexical token.")
|
||||
|
||||
|
||||
(defun ebnf-yac-initialize ()
|
||||
"Initializations for Yacc/Bison parser."
|
||||
(setq ebnf-yac-token-list nil))
|
||||
|
||||
|
||||
(defun ebnf-yac-lex ()
|
||||
"Lexical analyser for Yacc/Bison.
|
||||
|
||||
Return a lexical token.
|
||||
|
||||
See documentation for variable `ebnf-yac-lex'."
|
||||
(if (>= (point) ebnf-limit)
|
||||
'end-of-input
|
||||
(let (token)
|
||||
;; skip spaces, code blocks and comments
|
||||
(while (if (> (following-char) 255)
|
||||
(progn
|
||||
(setq token 'error)
|
||||
nil)
|
||||
(setq token (aref ebnf-yac-token-table (following-char)))
|
||||
(cond
|
||||
((or (eq token 'space)
|
||||
(and ebnf-yac-skip-char
|
||||
(eq token 'character)))
|
||||
(ebnf-yac-skip-spaces))
|
||||
((eq token 'yac-code)
|
||||
(ebnf-yac-skip-code))
|
||||
((eq token 'slash)
|
||||
(ebnf-yac-handle-comment))
|
||||
((eq token 'form-feed)
|
||||
(forward-char)
|
||||
(setq ebnf-action 'form-feed))
|
||||
(t nil)
|
||||
)))
|
||||
(cond
|
||||
;; end of input
|
||||
((>= (point) ebnf-limit)
|
||||
'end-of-input)
|
||||
;; error
|
||||
((eq token 'error)
|
||||
(error "Illegal character."))
|
||||
;; "string"
|
||||
((eq token 'string)
|
||||
(setq ebnf-yac-lex (ebnf-get-string))
|
||||
'string)
|
||||
;; terminal: 'char'
|
||||
((eq token 'terminal)
|
||||
(setq ebnf-yac-lex (ebnf-string " -&(-~" ?\' "terminal"))
|
||||
'terminal)
|
||||
;; non-terminal, terminal or "error"
|
||||
((eq token 'non-terminal)
|
||||
(setq ebnf-yac-lex (ebnf-buffer-substring "0-9A-Za-z_."))
|
||||
(cond ((member ebnf-yac-lex ebnf-yac-token-list)
|
||||
'terminal)
|
||||
((string= ebnf-yac-lex "error")
|
||||
(setq ebnf-yac-error t)
|
||||
'yac-error)
|
||||
(t
|
||||
'non-terminal)
|
||||
))
|
||||
;; %% and Yacc pragmas (%TOKEN, %START, etc).
|
||||
((eq token 'yac-pragma)
|
||||
(forward-char)
|
||||
(cond
|
||||
;; Yacc separator
|
||||
((eq (following-char) ?%)
|
||||
(forward-char)
|
||||
'yac-separator)
|
||||
;; %TOKEN
|
||||
((string= (upcase (ebnf-buffer-substring "0-9A-Za-z_")) "TOKEN")
|
||||
'yac-token)
|
||||
;; other Yacc pragmas
|
||||
(t
|
||||
'yac-pragma)
|
||||
))
|
||||
;; miscellaneous
|
||||
(t
|
||||
(forward-char)
|
||||
token)
|
||||
))))
|
||||
|
||||
|
||||
(defun ebnf-yac-skip-spaces ()
|
||||
(skip-chars-forward
|
||||
(if ebnf-yac-skip-char
|
||||
"\n\r\t !#$&()*+-.0123456789=?@[\\\\]^_`~"
|
||||
"\n\r\t ")
|
||||
ebnf-limit)
|
||||
(< (point) ebnf-limit))
|
||||
|
||||
|
||||
(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)
|
||||
(cond
|
||||
((= (following-char) ?{)
|
||||
(forward-char)
|
||||
(setq pair (1+ pair)))
|
||||
((= (following-char) ?})
|
||||
(forward-char)
|
||||
(setq pair (1- pair)))
|
||||
((= (following-char) ?/)
|
||||
(ebnf-yac-handle-comment))
|
||||
((= (following-char) ?\")
|
||||
(ebnf-get-string))
|
||||
((= (following-char) ?\')
|
||||
(ebnf-string " -&(-~" ?\' "character"))
|
||||
(t
|
||||
(error "Illegal character."))
|
||||
)))
|
||||
(ebnf-yac-skip-spaces))
|
||||
|
||||
|
||||
(defun ebnf-yac-handle-comment ()
|
||||
(forward-char)
|
||||
(cond
|
||||
;; begin comment
|
||||
((= (following-char) ?*)
|
||||
(ebnf-yac-skip-comment)
|
||||
(ebnf-yac-skip-spaces))
|
||||
;; line comment
|
||||
((= (following-char) ?/)
|
||||
(end-of-line)
|
||||
(ebnf-yac-skip-spaces))
|
||||
;; no comment
|
||||
(t nil)
|
||||
))
|
||||
|
||||
|
||||
(defconst ebnf-yac-comment-chars "^*\000-\010\013\016-\037\177-\237")
|
||||
|
||||
|
||||
(defun ebnf-yac-skip-comment ()
|
||||
(forward-char)
|
||||
(cond
|
||||
;; open EPS file
|
||||
((and ebnf-eps-executing (= (following-char) ?\[))
|
||||
(ebnf-eps-add-context (ebnf-yac-eps-filename)))
|
||||
;; close EPS file
|
||||
((and ebnf-eps-executing (= (following-char) ?\]))
|
||||
(ebnf-eps-remove-context (ebnf-yac-eps-filename)))
|
||||
;; any other action in comment
|
||||
(t
|
||||
(setq ebnf-action (aref ebnf-comment-table (following-char))))
|
||||
)
|
||||
(let ((not-end t))
|
||||
(while not-end
|
||||
(skip-chars-forward ebnf-yac-comment-chars ebnf-limit)
|
||||
(cond ((>= (point) ebnf-limit)
|
||||
(error "Missing end of comment: `*/'."))
|
||||
((= (following-char) ?*)
|
||||
(skip-chars-forward "*" ebnf-limit)
|
||||
(when (= (following-char) ?/)
|
||||
;; end of comment
|
||||
(forward-char)
|
||||
(setq not-end nil)))
|
||||
(t
|
||||
(error "Illegal character."))
|
||||
))))
|
||||
|
||||
|
||||
(defun ebnf-yac-eps-filename ()
|
||||
(forward-char)
|
||||
(buffer-substring-no-properties
|
||||
(point)
|
||||
(let ((chars (concat ebnf-yac-comment-chars "\n"))
|
||||
found)
|
||||
(while (not found)
|
||||
(skip-chars-forward chars ebnf-limit)
|
||||
(setq found
|
||||
(cond ((>= (point) ebnf-limit)
|
||||
(point))
|
||||
((= (following-char) ?*)
|
||||
(skip-chars-forward "*" ebnf-limit)
|
||||
(if (/= (following-char) ?\/)
|
||||
nil
|
||||
(backward-char)
|
||||
(point)))
|
||||
(t
|
||||
(point))
|
||||
)))
|
||||
found)))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
(provide 'ebnf-yac)
|
||||
|
||||
|
||||
;;; ebnf-yac.el ends here
|
5339
lisp/progmodes/ebnf2ps.el
Normal file
5339
lisp/progmodes/ebnf2ps.el
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user