Merge from emacs--rel--22
[bpt/emacs.git] / lisp / progmodes / ebnf-otz.el
1 ;;; ebnf-otz.el --- syntactic chart OpTimiZer
2
3 ;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
4 ;; Free Software Foundation, Inc.
5
6 ;; Author: Vinicius Jose Latorre <viniciusjl@ig.com.br>
7 ;; Maintainer: Vinicius Jose Latorre <viniciusjl@ig.com.br>
8 ;; Keywords: wp, ebnf, PostScript
9 ;; Version: 1.0
10
11 ;; This file is part of GNU Emacs.
12
13 ;; GNU Emacs is free software; you can redistribute it and/or modify
14 ;; it under the terms of the GNU General Public License as published by
15 ;; the Free Software Foundation; either version 2, or (at your option)
16 ;; any later version.
17
18 ;; GNU Emacs is distributed in the hope that it will be useful,
19 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 ;; GNU General Public License for more details.
22
23 ;; You should have received a copy of the GNU General Public License
24 ;; along with GNU Emacs; see the file COPYING. If not, write to the
25 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26 ;; Boston, MA 02110-1301, USA.
27
28 ;;; Commentary:
29
30 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
31 ;;
32 ;;
33 ;; This is part of ebnf2ps package.
34 ;;
35 ;; This package defines an optimizer for ebnf2ps.
36 ;;
37 ;; See ebnf2ps.el for documentation.
38 ;;
39 ;;
40 ;; Optimizations
41 ;; -------------
42 ;;
43 ;;
44 ;; *To be implemented*:
45 ;; left recursion:
46 ;; A = B | A C B | A C D. ==> A = B {C (B | D)}*.
47 ;;
48 ;; right recursion:
49 ;; A = B | C A. ==> A = {C}* B.
50 ;; A = B | D | C A | E A. ==> A = { C | E }* ( B | D ).
51 ;;
52 ;; optional:
53 ;; A = B | C B. ==> A = [C] B.
54 ;; A = B | B C. ==> A = B [C].
55 ;; A = D | B D | B C D. ==> A = [B [C]] D.
56 ;;
57 ;;
58 ;; *Already implemented*:
59 ;; left recursion:
60 ;; A = B | A C. ==> A = B {C}*.
61 ;; A = B | A B. ==> A = {B}+.
62 ;; A = | A B. ==> A = {B}*.
63 ;; A = B | A C B. ==> A = {B || C}+.
64 ;; A = B | D | A C | A E. ==> A = ( B | D ) { C | E }*.
65 ;;
66 ;; optional:
67 ;; A = B | . ==> A = [B].
68 ;; A = | B . ==> A = [B].
69 ;;
70 ;; factorization:
71 ;; A = B C | B D. ==> A = B (C | D).
72 ;; A = C B | D B. ==> A = (C | D) B.
73 ;; A = B C E | B D E. ==> A = B (C | D) E.
74 ;;
75 ;; none:
76 ;; A = B | C | . ==> A = B | C | .
77 ;; A = B | C A D. ==> A = B | C A D.
78 ;;
79 ;;
80 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
81
82 ;;; Code:
83
84
85 (require 'ebnf2ps)
86
87 \f
88 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
89
90
91 (defvar ebnf-empty-rule-list nil
92 "List of empty rule name.")
93
94
95 (defun ebnf-add-empty-rule-list (rule)
96 "Add empty RULE in `ebnf-empty-rule-list'."
97 (and ebnf-ignore-empty-rule
98 (eq (ebnf-node-kind (ebnf-node-production rule))
99 'ebnf-generate-empty)
100 (setq ebnf-empty-rule-list (cons (ebnf-node-name rule)
101 ebnf-empty-rule-list))))
102
103
104 (defun ebnf-otz-initialize ()
105 "Initialize optimizer."
106 (setq ebnf-empty-rule-list nil))
107
108 \f
109 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
110 ;; Eliminate empty rules
111
112
113 (defun ebnf-eliminate-empty-rules (syntax-list)
114 "Eliminate empty rules."
115 (while ebnf-empty-rule-list
116 (let ((ebnf-total (length syntax-list))
117 (ebnf-nprod 0)
118 (prod-list syntax-list)
119 new-list before)
120 (while prod-list
121 (ebnf-message-info "Eliminating empty rules")
122 (let ((rule (car prod-list)))
123 ;; if any non-terminal pertains to ebnf-empty-rule-list
124 ;; then eliminate non-terminal from rule
125 (if (ebnf-eliminate-empty rule)
126 (setq before prod-list)
127 ;; eliminate empty rule from syntax-list
128 (setq new-list (cons (ebnf-node-name rule) new-list))
129 (if before
130 (setcdr before (cdr prod-list))
131 (setq syntax-list (cdr syntax-list)))))
132 (setq prod-list (cdr prod-list)))
133 (setq ebnf-empty-rule-list new-list)))
134 syntax-list)
135
136
137 ;; [production width-func entry height width name production action]
138 ;; [sequence width-func entry height width list]
139 ;; [alternative width-func entry height width list]
140 ;; [non-terminal width-func entry height width name default]
141 ;; [empty width-func entry height width]
142 ;; [terminal width-func entry height width name default]
143 ;; [special width-func entry height width name default]
144
145 (defun ebnf-eliminate-empty (rule)
146 (let ((kind (ebnf-node-kind rule)))
147 (cond
148 ;; non-terminal
149 ((eq kind 'ebnf-generate-non-terminal)
150 (if (member (ebnf-node-name rule) ebnf-empty-rule-list)
151 nil
152 rule))
153 ;; sequence
154 ((eq kind 'ebnf-generate-sequence)
155 (let ((seq (ebnf-node-list rule))
156 (header (ebnf-node-list rule))
157 before elt)
158 (while seq
159 (setq elt (car seq))
160 (if (ebnf-eliminate-empty elt)
161 (setq before seq)
162 (if before
163 (setcdr before (cdr seq))
164 (setq header (cdr header))))
165 (setq seq (cdr seq)))
166 (when header
167 (ebnf-node-list rule header)
168 rule)))
169 ;; alternative
170 ((eq kind 'ebnf-generate-alternative)
171 (let ((seq (ebnf-node-list rule))
172 (header (ebnf-node-list rule))
173 before elt)
174 (while seq
175 (setq elt (car seq))
176 (if (ebnf-eliminate-empty elt)
177 (setq before seq)
178 (if before
179 (setcdr before (cdr seq))
180 (setq header (cdr header))))
181 (setq seq (cdr seq)))
182 (when header
183 (if (= (length header) 1)
184 (car header)
185 (ebnf-node-list rule header)
186 rule))))
187 ;; production
188 ((eq kind 'ebnf-generate-production)
189 (let ((prod (ebnf-eliminate-empty (ebnf-node-production rule))))
190 (when prod
191 (ebnf-node-production rule prod)
192 rule)))
193 ;; terminal, special and empty
194 (t
195 rule)
196 )))
197
198 \f
199 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
200 ;; Optimizations
201
202
203 ;; *To be implemented*:
204 ;; left recursion:
205 ;; A = B | A C B | A C D. ==> A = B {C (B | D)}*.
206
207 ;; right recursion:
208 ;; A = B | C A. ==> A = {C}* B.
209 ;; A = B | D | C A | E A. ==> A = { C | E }* ( B | D ).
210
211 ;; optional:
212 ;; A = B | C B. ==> A = [C] B.
213 ;; A = B | B C. ==> A = B [C].
214 ;; A = D | B D | B C D. ==> A = [B [C]] D.
215
216
217 ;; *Already implemented*:
218 ;; left recursion:
219 ;; A = B | A C. ==> A = B {C}*.
220 ;; A = B | A B. ==> A = {B}+.
221 ;; A = | A B. ==> A = {B}*.
222 ;; A = B | A C B. ==> A = {B || C}+.
223 ;; A = B | D | A C | A E. ==> A = ( B | D ) { C | E }*.
224
225 ;; optional:
226 ;; A = B | . ==> A = [B].
227 ;; A = | B . ==> A = [B].
228
229 ;; factorization:
230 ;; A = B C | B D. ==> A = B (C | D).
231 ;; A = C B | D B. ==> A = (C | D) B.
232 ;; A = B C E | B D E. ==> A = B (C | D) E.
233
234 ;; none:
235 ;; A = B | C | . ==> A = B | C | .
236 ;; A = B | C A D. ==> A = B | C A D.
237
238 (defun ebnf-optimize (syntax-list)
239 "Syntactic chart optimizer."
240 (if (not ebnf-optimize)
241 syntax-list
242 (let ((ebnf-total (length syntax-list))
243 (ebnf-nprod 0)
244 new)
245 (while syntax-list
246 (setq new (cons (ebnf-optimize1 (car syntax-list)) new)
247 syntax-list (cdr syntax-list)))
248 (nreverse new))))
249
250
251 ;; left recursion:
252 ;; 1. A = B | A C. ==> A = B {C}*.
253 ;; 2. A = B | A B. ==> A = {B}+.
254 ;; 3. A = | A B. ==> A = {B}*.
255 ;; 4. A = B | A C B. ==> A = {B || C}+.
256 ;; 5. A = B | D | A C | A E. ==> A = ( B | D ) { C | E }*.
257
258 ;; optional:
259 ;; 6. A = B | . ==> A = [B].
260 ;; 7. A = | B . ==> A = [B].
261
262 ;; factorization:
263 ;; 8. A = B C | B D. ==> A = B (C | D).
264 ;; 9. A = C B | D B. ==> A = (C | D) B.
265 ;; 10. A = B C E | B D E. ==> A = B (C | D) E.
266
267 (defun ebnf-optimize1 (prod)
268 (ebnf-message-info "Optimizing syntactic chart")
269 (let ((production (ebnf-node-production prod)))
270 (and (eq (ebnf-node-kind production) 'ebnf-generate-alternative)
271 (let* ((hlist (ebnf-split-header-prefix
272 (ebnf-node-list production)
273 (ebnf-node-name prod)))
274 (nlist (car hlist))
275 (zlist (cdr hlist))
276 (elist (ebnf-split-header-suffix nlist zlist)))
277 (ebnf-node-production
278 prod
279 (cond
280 ;; cases 2., 4.
281 (elist
282 (and (eq elist t)
283 (setq elist nil))
284 (setq elist (or (ebnf-prefix-suffix elist)
285 elist))
286 (let* ((nl (ebnf-extract-empty nlist))
287 (el (or (ebnf-prefix-suffix (cdr nl))
288 (ebnf-create-alternative (cdr nl)))))
289 (if (car nl)
290 (ebnf-make-zero-or-more el elist)
291 (ebnf-make-one-or-more el elist))))
292 ;; cases 1., 3., 5.
293 (zlist
294 (let* ((xlist (cdr (ebnf-extract-empty zlist)))
295 (znode (ebnf-make-zero-or-more
296 (or (ebnf-prefix-suffix xlist)
297 (ebnf-create-alternative xlist))))
298 (nnode (ebnf-map-list-to-optional nlist)))
299 (and nnode
300 (setq nlist (list nnode)))
301 (if (or (null nlist)
302 (and (= (length nlist) 1)
303 (eq (ebnf-node-kind (car nlist))
304 'ebnf-generate-empty)))
305 znode
306 (ebnf-make-sequence
307 (list (or (ebnf-prefix-suffix nlist)
308 (ebnf-create-alternative nlist))
309 znode)))))
310 ;; cases 6., 7.
311 ((ebnf-map-node-to-optional production)
312 )
313 ;; cases 8., 9., 10.
314 ((ebnf-prefix-suffix nlist)
315 )
316 ;; none
317 (t
318 production)
319 ))))
320 prod))
321
322
323 (defun ebnf-split-header-prefix (node-list header)
324 (let* ((hlist (ebnf-split-header-prefix1 node-list header))
325 (nlist (car hlist))
326 zlist empty-p)
327 (while (setq hlist (cdr hlist))
328 (let ((elt (car hlist)))
329 (if (eq (ebnf-node-kind elt) 'ebnf-generate-sequence)
330 (setq zlist (cons
331 (let ((seq (cdr (ebnf-node-list elt))))
332 (if (= (length seq) 1)
333 (car seq)
334 (ebnf-node-list elt seq)
335 elt))
336 zlist))
337 (setq empty-p t))))
338 (and empty-p
339 (setq zlist (cons (ebnf-make-empty)
340 zlist)))
341 (cons nlist (nreverse zlist))))
342
343
344 (defun ebnf-split-header-prefix1 (node-list header)
345 (let (hlist nlist)
346 (while node-list
347 (if (ebnf-node-equal-header (car node-list) header)
348 (setq hlist (cons (car node-list) hlist))
349 (setq nlist (cons (car node-list) nlist)))
350 (setq node-list (cdr node-list)))
351 (cons (nreverse nlist) (nreverse hlist))))
352
353
354 (defun ebnf-node-equal-header (node header)
355 (let ((kind (ebnf-node-kind node)))
356 (cond
357 ((eq kind 'ebnf-generate-sequence)
358 (ebnf-node-equal-header (car (ebnf-node-list node)) header))
359 ((eq kind 'ebnf-generate-non-terminal)
360 (string= (ebnf-node-name node) header))
361 (t
362 nil)
363 )))
364
365
366 (defun ebnf-map-node-to-optional (node)
367 (and (eq (ebnf-node-kind node) 'ebnf-generate-alternative)
368 (ebnf-map-list-to-optional (ebnf-node-list node))))
369
370
371 (defun ebnf-map-list-to-optional (nlist)
372 (and (= (length nlist) 2)
373 (let ((first (nth 0 nlist))
374 (second (nth 1 nlist)))
375 (cond
376 ;; empty second
377 ((eq (ebnf-node-kind first) 'ebnf-generate-empty)
378 (ebnf-make-optional second))
379 ;; first empty
380 ((eq (ebnf-node-kind second) 'ebnf-generate-empty)
381 (ebnf-make-optional first))
382 ;; first second
383 (t
384 nil)
385 ))))
386
387
388 (defun ebnf-extract-empty (elist)
389 (let ((now elist)
390 before empty-p)
391 (while now
392 (if (not (eq (ebnf-node-kind (car now)) 'ebnf-generate-empty))
393 (setq before now)
394 (setq empty-p t)
395 (if before
396 (setcdr before (cdr now))
397 (setq elist (cdr elist))))
398 (setq now (cdr now)))
399 (cons empty-p elist)))
400
401
402 (defun ebnf-split-header-suffix (nlist zlist)
403 (let (new empty-p)
404 (and (cond
405 ((= (length nlist) 1)
406 (let ((ok t)
407 (elt (car nlist)))
408 (while (and ok zlist)
409 (setq ok (ebnf-split-header-suffix1 elt (car zlist))
410 zlist (cdr zlist))
411 (if (eq ok t)
412 (setq empty-p t)
413 (setq new (cons ok new))))
414 ok))
415 ((= (length nlist) (length zlist))
416 (let ((ok t))
417 (while (and ok zlist)
418 (setq ok (ebnf-split-header-suffix1 (car nlist) (car zlist))
419 nlist (cdr nlist)
420 zlist (cdr zlist))
421 (if (eq ok t)
422 (setq empty-p t)
423 (setq new (cons ok new))))
424 ok))
425 (t
426 nil)
427 )
428 (let* ((lis (ebnf-unique-list new))
429 (len (length lis)))
430 (cond
431 ((zerop len)
432 t)
433 ((= len 1)
434 (setq lis (car lis))
435 (if empty-p
436 (ebnf-make-optional lis)
437 lis))
438 (t
439 (and empty-p
440 (setq lis (cons (ebnf-make-empty) lis)))
441 (ebnf-create-alternative (nreverse lis)))
442 )))))
443
444
445 (defun ebnf-split-header-suffix1 (ne ze)
446 (cond
447 ((eq (ebnf-node-kind ne) 'ebnf-generate-sequence)
448 (and (eq (ebnf-node-kind ze) 'ebnf-generate-sequence)
449 (let ((nl (ebnf-node-list ne))
450 (zl (ebnf-node-list ze))
451 len z)
452 (and (>= (length zl) (length nl))
453 (let ((ok t))
454 (setq len (- (length zl) (length nl))
455 z (nthcdr len zl))
456 (while (and ok z)
457 (setq ok (ebnf-node-equal (car z) (car nl))
458 z (cdr z)
459 nl (cdr nl)))
460 ok)
461 (if (zerop len)
462 t
463 (setcdr (nthcdr (1- len) zl) nil)
464 ze)))))
465 ((eq (ebnf-node-kind ze) 'ebnf-generate-sequence)
466 (let* ((zl (ebnf-node-list ze))
467 (len (length zl)))
468 (and (ebnf-node-equal ne (car (nthcdr (1- len) zl)))
469 (cond
470 ((= len 1)
471 t)
472 ((= len 2)
473 (car zl))
474 (t
475 (setcdr (nthcdr (- len 2) zl) nil)
476 ze)
477 ))))
478 (t
479 (ebnf-node-equal ne ze))
480 ))
481
482
483 (defun ebnf-prefix-suffix (lis)
484 (and lis (listp lis)
485 (let* ((prefix (ebnf-split-prefix lis))
486 (suffix (ebnf-split-suffix (cdr prefix)))
487 (middle (cdr suffix)))
488 (setq prefix (car prefix)
489 suffix (car suffix))
490 (and (or prefix suffix)
491 (ebnf-make-sequence
492 (nconc prefix
493 (and middle
494 (list (or (ebnf-map-list-to-optional middle)
495 (ebnf-create-alternative middle))))
496 suffix))))))
497
498
499 (defun ebnf-split-prefix (lis)
500 (let* ((len (length lis))
501 (tail lis)
502 (head (if (eq (ebnf-node-kind (car lis)) 'ebnf-generate-sequence)
503 (ebnf-node-list (car lis))
504 (list (car lis))))
505 (ipre (1+ len)))
506 ;; determine prefix length
507 (while (and (> ipre 0) (setq tail (cdr tail)))
508 (let ((cur head)
509 (this (if (eq (ebnf-node-kind (car tail)) 'ebnf-generate-sequence)
510 (ebnf-node-list (car tail))
511 (list (car tail))))
512 (i 0))
513 (while (and cur this
514 (ebnf-node-equal (car cur) (car this)))
515 (setq cur (cdr cur)
516 this (cdr this)
517 i (1+ i)))
518 (setq ipre (min ipre i))))
519 (if (or (zerop ipre) (> ipre len))
520 ;; no prefix at all
521 (cons nil lis)
522 (let* ((tail (nthcdr ipre head))
523 ;; get prefix
524 (prefix (progn
525 (and tail
526 (setcdr (nthcdr (1- ipre) head) nil))
527 head))
528 empty-p before)
529 ;; adjust first element
530 (if (or (not (eq (ebnf-node-kind (car lis)) 'ebnf-generate-sequence))
531 (null tail))
532 (setq lis (cdr lis)
533 tail lis
534 empty-p t)
535 (if (= (length tail) 1)
536 (setcar lis (car tail))
537 (ebnf-node-list (car lis) tail))
538 (setq tail (cdr lis)))
539 ;; eliminate prefix from lis based on ipre
540 (while tail
541 (let ((elt (car tail))
542 rest)
543 (if (and (eq (ebnf-node-kind elt) 'ebnf-generate-sequence)
544 (setq rest (nthcdr ipre (ebnf-node-list elt))))
545 (progn
546 (if (= (length rest) 1)
547 (setcar tail (car rest))
548 (ebnf-node-list elt rest))
549 (setq before tail))
550 (setq empty-p t)
551 (if before
552 (setcdr before (cdr tail))
553 (setq lis (cdr lis))))
554 (setq tail (cdr tail))))
555 (cons prefix (ebnf-unique-list
556 (if empty-p
557 (nconc lis (list (ebnf-make-empty)))
558 lis)))))))
559
560
561 (defun ebnf-split-suffix (lis)
562 (let* ((len (length lis))
563 (tail lis)
564 (head (nreverse
565 (if (eq (ebnf-node-kind (car lis)) 'ebnf-generate-sequence)
566 (ebnf-node-list (car lis))
567 (list (car lis)))))
568 (isuf (1+ len)))
569 ;; determine suffix length
570 (while (and (> isuf 0) (setq tail (cdr tail)))
571 (let* ((cur head)
572 (tlis (nreverse
573 (if (eq (ebnf-node-kind (car tail)) 'ebnf-generate-sequence)
574 (ebnf-node-list (car tail))
575 (list (car tail)))))
576 (this tlis)
577 (i 0))
578 (while (and cur this
579 (ebnf-node-equal (car cur) (car this)))
580 (setq cur (cdr cur)
581 this (cdr this)
582 i (1+ i)))
583 (nreverse tlis)
584 (setq isuf (min isuf i))))
585 (setq head (nreverse head))
586 (if (or (zerop isuf) (> isuf len))
587 ;; no suffix at all
588 (cons nil lis)
589 (let* ((n (- (length head) isuf))
590 ;; get suffix
591 (suffix (nthcdr n head))
592 (tail (and (> n 0)
593 (progn
594 (setcdr (nthcdr (1- n) head) nil)
595 head)))
596 before empty-p)
597 ;; adjust first element
598 (if (or (not (eq (ebnf-node-kind (car lis)) 'ebnf-generate-sequence))
599 (null tail))
600 (setq lis (cdr lis)
601 tail lis
602 empty-p t)
603 (if (= (length tail) 1)
604 (setcar lis (car tail))
605 (ebnf-node-list (car lis) tail))
606 (setq tail (cdr lis)))
607 ;; eliminate suffix from lis based on isuf
608 (while tail
609 (let ((elt (car tail))
610 rest)
611 (if (and (eq (ebnf-node-kind elt) 'ebnf-generate-sequence)
612 (setq rest (ebnf-node-list elt)
613 n (- (length rest) isuf))
614 (> n 0))
615 (progn
616 (if (= n 1)
617 (setcar tail (car rest))
618 (setcdr (nthcdr (1- n) rest) nil)
619 (ebnf-node-list elt rest))
620 (setq before tail))
621 (setq empty-p t)
622 (if before
623 (setcdr before (cdr tail))
624 (setq lis (cdr lis))))
625 (setq tail (cdr tail))))
626 (cons suffix (ebnf-unique-list
627 (if empty-p
628 (nconc lis (list (ebnf-make-empty)))
629 lis)))))))
630
631
632 (defun ebnf-unique-list (nlist)
633 (let ((current nlist)
634 before)
635 (while current
636 (let ((tail (cdr current))
637 (head (car current))
638 remove-p)
639 (while tail
640 (if (not (ebnf-node-equal head (car tail)))
641 (setq tail (cdr tail))
642 (setq remove-p t
643 tail nil)
644 (if before
645 (setcdr before (cdr current))
646 (setq nlist (cdr nlist)))))
647 (or remove-p
648 (setq before current))
649 (setq current (cdr current))))
650 nlist))
651
652
653 (defun ebnf-node-equal (A B)
654 (let ((kindA (ebnf-node-kind A))
655 (kindB (ebnf-node-kind B)))
656 (and (eq kindA kindB)
657 (cond
658 ;; empty
659 ((eq kindA 'ebnf-generate-empty)
660 t)
661 ;; non-terminal, terminal, special
662 ((memq kindA '(ebnf-generate-non-terminal
663 ebnf-generate-terminal
664 ebnf-generate-special))
665 (string= (ebnf-node-name A) (ebnf-node-name B)))
666 ;; alternative, sequence
667 ((memq kindA '(ebnf-generate-alternative ; any order
668 ebnf-generate-sequence)) ; order is important
669 (let ((listA (ebnf-node-list A))
670 (listB (ebnf-node-list B)))
671 (and (= (length listA) (length listB))
672 (let ((ok t))
673 (while (and ok listA)
674 (setq ok (ebnf-node-equal (car listA) (car listB))
675 listA (cdr listA)
676 listB (cdr listB)))
677 ok))))
678 ;; production
679 ((eq kindA 'ebnf-generate-production)
680 (and (string= (ebnf-node-name A) (ebnf-node-name B))
681 (ebnf-node-equal (ebnf-node-production A)
682 (ebnf-node-production B))))
683 ;; otherwise
684 (t
685 nil)
686 ))))
687
688
689 (defun ebnf-create-alternative (alt)
690 (if (> (length alt) 1)
691 (ebnf-make-alternative alt)
692 (car alt)))
693
694 \f
695 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
696
697
698 (provide 'ebnf-otz)
699
700
701 ;;; arch-tag: 7ef2249d-9e8b-4bc1-999f-95d784690636
702 ;;; ebnf-otz.el ends here