Initial Commit
[packages] / xemacs-packages / semantic / wisent / wisent-comp.el.upstream
1 ;;; wisent-comp.el --- GNU Bison for Emacs - Grammar compiler
2
3 ;; Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 David Ponce
4 ;; Copyright (C) 1984, 1986, 1989, 1992, 1995, 2000, 2001
5 ;; Free Software Foundation, Inc. (Bison)
6
7 ;; Author: David Ponce <david@dponce.com>
8 ;; Maintainer: David Ponce <david@dponce.com>
9 ;; Created: 30 January 2002
10 ;; Keywords: syntax
11 ;; X-RCS: $Id: wisent-comp.el.upstream,v 1.1 2007-12-02 12:56:43 michaels Exp $
12
13 ;; This file is not part of GNU Emacs.
14
15 ;; This program is free software; you can redistribute it and/or
16 ;; modify it under the terms of the GNU General Public License as
17 ;; published by the Free Software Foundation; either version 2, or (at
18 ;; your option) any later version.
19
20 ;; This program is distributed in the hope that it will be useful, but
21 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
22 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23 ;; General Public License for more details.
24
25 ;; You should have received a copy of the GNU General Public License
26 ;; along with this program; see the file COPYING.  If not, write to
27 ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
28 ;; Boston, MA 02110-1301, USA.
29
30 ;;; Commentary:
31 ;;
32 ;; Grammar compiler that produces Wisent's LALR automatons.
33 ;;
34 ;; Wisent (the European Bison ;-) is an Elisp implementation of the
35 ;; GNU Compiler Compiler Bison.  The Elisp code is a port of the C
36 ;; code of GNU Bison 1.28 & 1.31.
37 ;;
38 ;; For more details on the basic concepts for understanding Wisent,
39 ;; read the Bison manual ;)
40 ;;
41 ;; For more details on Wisent itself read the Wisent manual.
42
43 ;;; History:
44 ;;
45
46 ;;; Code:
47 (require 'wisent)
48 (require 'working)
49 \f
50 ;;;; -------------------
51 ;;;; Misc. useful things
52 ;;;; -------------------
53
54 ;; As much as possible I would like to keep the name of global
55 ;; variables used in Bison without polluting too much the Elisp global
56 ;; name space.  Elisp dynamic binding allows that ;-)
57
58 ;; Here are simple macros to easily define and use set of variables
59 ;; binded locally, without all these "reference to free variable"
60 ;; compiler warnings!
61
62 (defmacro wisent-context-name (name)
63   "Return the context name from NAME."
64   `(if (and ,name (symbolp ,name))
65        (intern (format "wisent-context-%s" ,name))
66      (error "Invalid context name: %S" ,name)))
67
68 (defmacro wisent-context-bindings (name)
69   "Return the variables in context NAME."
70   `(symbol-value (wisent-context-name ,name)))
71
72 (defmacro wisent-defcontext (name &rest vars)
73   "Define a context NAME that will bind variables VARS."
74   (let* ((context (wisent-context-name name))
75          (bindings (mapcar #'(lambda (v) (list 'defvar v)) vars)))
76     `(eval-when-compile
77        ,@bindings
78        (defvar ,context ',vars))))
79 (put 'wisent-defcontext 'lisp-indent-function 1)
80
81 (defmacro wisent-with-context (name &rest body)
82   "Bind variables in context NAME then eval BODY."
83   `(let* ,(wisent-context-bindings name)
84      ,@body))
85 (put 'wisent-with-context 'lisp-indent-function 1)
86
87 ;; A naive implementation of data structures!  But it suffice here ;-)
88
89 (defmacro wisent-struct (name &rest fields)
90   "Define a simple data structure called NAME.
91 Which contains data stored in FIELDS.  FIELDS is a list of symbols
92 which are field names or pairs (FIELD INITIAL-VALUE) where
93 INITIAL-VALUE is a constant used as the initial value of FIELD when
94 the data structure is created.  INITIAL-VALUE defaults to nil.
95
96 This defines a `make-NAME' constructor, get-able `NAME-FIELD' and
97 set-able `set-NAME-FIELD' accessors."
98   (let ((size (length fields))
99         (i    0)
100         accors field sufx fun ivals)
101     (while (< i size)
102       (setq field  (car fields)
103             fields (cdr fields))
104       (if (consp field)
105           (setq ivals (cons (cadr field) ivals)
106                 field (car field))
107         (setq ivals (cons nil ivals)))
108       (setq sufx   (format "%s-%s" name field)
109             fun    (intern (format "%s" sufx))
110             accors (cons `(defmacro ,fun (s)
111                             (list 'aref s ,i))
112                          accors)
113             fun    (intern (format "set-%s" sufx))
114             accors (cons `(defmacro ,fun (s v)
115                             (list 'aset s ,i v))
116                          accors)
117             i      (1+ i)))
118     `(progn
119       (defmacro ,(intern (format "make-%s" name)) ()
120         (cons 'vector ',(nreverse ivals)))
121       ,@accors)))
122 (put 'wisent-struct 'lisp-indent-function 1)
123
124 ;; Other utilities
125
126 (defsubst wisent-pad-string (s n &optional left)
127   "Fill string S with spaces.
128 Return a new string of at least N characters.  Insert spaces on right.
129 If optional LEFT is non-nil insert spaces on left."
130   (let ((i (length s)))
131     (if (< i n)
132         (if left
133             (concat (make-string (- n i) ?\ ) s)
134           (concat s (make-string (- n i) ?\ )))
135       s)))
136 \f
137 ;;;; ------------------------
138 ;;;; Environment dependencies
139 ;;;; ------------------------
140
141 (defconst wisent-BITS-PER-WORD
142   (let ((i 1))
143     (while (not (zerop (lsh 1 i)))
144       (setq i (1+ i)))
145     i))
146
147 (defsubst wisent-WORDSIZE (n)
148   "(N + BITS-PER-WORD - 1) / BITS-PER-WORD."
149   (/ (1- (+ n wisent-BITS-PER-WORD)) wisent-BITS-PER-WORD))
150
151 (defsubst wisent-SETBIT (x i)
152   "X[I/BITS-PER-WORD] |= 1 << (I % BITS-PER-WORD)."
153   (let ((k (/ i wisent-BITS-PER-WORD)))
154     (aset x k (logior (aref x k)
155                       (lsh 1 (% i wisent-BITS-PER-WORD))))))
156
157 (defsubst wisent-RESETBIT (x i)
158   "X[I/BITS-PER-WORD] &= ~(1 << (I % BITS-PER-WORD))."
159   (let ((k (/ i wisent-BITS-PER-WORD)))
160     (aset x k (logand (aref x k)
161                       (lognot (lsh 1 (% i wisent-BITS-PER-WORD)))))))
162
163 (defsubst wisent-BITISSET (x i)
164   "(X[I/BITS-PER-WORD] & (1 << (I % BITS-PER-WORD))) != 0."
165   (not (zerop (logand (aref x (/ i wisent-BITS-PER-WORD))
166                       (lsh 1 (% i wisent-BITS-PER-WORD))))))
167
168 (eval-when-compile
169   (or (fboundp 'noninteractive)
170       ;; Silence the Emacs byte compiler
171       (defun noninteractive nil))
172   )
173
174 (defsubst wisent-noninteractive ()
175   "Return non-nil if running without interactive terminal."
176   (if (featurep 'xemacs)
177       (noninteractive)
178     noninteractive))
179
180 (defvar wisent-debug-flag nil
181   "Non-nil means enable some debug stuff.")
182 \f
183 ;;;; --------------
184 ;;;; Logging/Output
185 ;;;; --------------
186 (defconst wisent-log-buffer-name "*wisent-log*"
187   "Name of the log buffer.")
188
189 (defvar wisent-new-log-flag nil
190   "Non-nil means to start a new report.")
191
192 ;;;###autoload
193 (defvar wisent-verbose-flag nil
194   "*Non-nil means to report verbose information on generated parser.")
195
196 ;;;###autoload
197 (defun wisent-toggle-verbose-flag ()
198   "Toggle whether to report verbose information on generated parser."
199   (interactive)
200   (setq wisent-verbose-flag (not wisent-verbose-flag))
201   (when (interactive-p)
202     (message "Verbose report %sabled"
203              (if wisent-verbose-flag "en" "dis"))))
204
205 (defmacro wisent-log-buffer ()
206   "Return the log buffer.
207 Its name is defined in constant `wisent-log-buffer-name'."
208   `(get-buffer-create wisent-log-buffer-name))
209
210 (defmacro wisent-clear-log ()
211   "Delete the entire contents of the log buffer."
212   `(with-current-buffer (wisent-log-buffer)
213      (erase-buffer)))
214
215 (eval-when-compile (defvar byte-compile-current-file))
216
217 (defun wisent-source ()
218   "Return the current source file name or nil."
219   (let ((source (or (and (boundp 'byte-compile-current-file)
220                          byte-compile-current-file)
221                     load-file-name (buffer-file-name))))
222     (if source
223         (file-relative-name source))))
224
225 (defun wisent-new-log ()
226   "Start a new entry into the log buffer."
227   (setq wisent-new-log-flag nil)
228   (let ((text (format "\n\n*** Wisent %s - %s\n\n"
229                       (or (wisent-source) (buffer-name))
230                       (format-time-string "%Y-%m-%d %R"))))
231     (with-current-buffer (wisent-log-buffer)
232       (goto-char (point-max))
233       (insert text))))
234
235 (defsubst wisent-log (&rest args)
236   "Insert text into the log buffer.
237 `format' is applied to ARGS and the result string is inserted into the
238 log buffer returned by the function `wisent-log-buffer'."
239   (and wisent-new-log-flag (wisent-new-log))
240   (with-current-buffer (wisent-log-buffer)
241     (insert (apply 'format args))))
242
243 (defconst wisent-log-file "wisent.output"
244   "The log file.
245 Used when running without interactive terminal.")
246
247 (defun wisent-append-to-log-file ()
248   "Append contents of logging buffer to `wisent-log-file'."
249   (if (get-buffer wisent-log-buffer-name)
250       (condition-case err
251           (with-current-buffer (wisent-log-buffer)
252             (widen)
253             (if (> (point-max) (point-min))
254                 (write-region (point-min) (point-max)
255                               wisent-log-file t)))
256         (error
257          (message "*** %s" (error-message-string err))))))
258 \f
259 ;;;; -----------------------------------
260 ;;;; Representation of the grammar rules
261 ;;;; -----------------------------------
262
263 ;; ntokens is the number of tokens, and nvars is the number of
264 ;; variables (nonterminals).  nsyms is the total number, ntokens +
265 ;; nvars.
266
267 ;; Each symbol (either token or variable) receives a symbol number.
268 ;; Numbers 0 to ntokens-1 are for tokens, and ntokens to nsyms-1 are
269 ;; for variables.  Symbol number zero is the end-of-input token.  This
270 ;; token is counted in ntokens.
271
272 ;; The rules receive rule numbers 1 to nrules in the order they are
273 ;; written.  Actions and guards are accessed via the rule number.
274
275 ;; The rules themselves are described by three arrays: rrhs, rlhs and
276 ;; ritem.  rlhs[R] is the symbol number of the left hand side of rule
277 ;; R.  The right hand side is stored as symbol numbers in a portion of
278 ;; ritem.  rrhs[R] contains the index in ritem of the beginning of the
279 ;; portion for rule R.
280
281 ;; The length of the portion is one greater than the number of symbols
282 ;; in the rule's right hand side.  The last element in the portion
283 ;; contains minus R, which identifies it as the end of a portion and
284 ;; says which rule it is for.
285
286 ;; The portions of ritem come in order of increasing rule number and
287 ;; are followed by an element which is nil to mark the end.  nitems is
288 ;; the total length of ritem, not counting the final nil.  Each
289 ;; element of ritem is called an "item" and its index in ritem is an
290 ;; item number.
291
292 ;; Item numbers are used in the finite state machine to represent
293 ;; places that parsing can get to.
294
295 ;; The vector rprec contains for each rule, the item number of the
296 ;; symbol giving its precedence level to this rule.  The precedence
297 ;; level and associativity of each symbol is recorded in respectively
298 ;; the properties 'wisent--prec and 'wisent--assoc.
299
300 ;; Precedence levels are assigned in increasing order starting with 1
301 ;; so that numerically higher precedence values mean tighter binding
302 ;; as they ought to.  nil as a symbol or rule's precedence means none
303 ;; is assigned.
304
305 (defcustom wisent-state-table-size 1009
306   "The size of the state table."
307   :type 'integer
308   :group 'wisent)
309
310 ;; These variables only exist locally in the function
311 ;; `wisent-compile-grammar' and are shared by all other nested
312 ;; callees.
313 (wisent-defcontext compile-grammar
314   F LA LAruleno accessing-symbol conflicts consistent default-prec
315   derives err-table fderives final-state first-reduction first-shift
316   first-state firsts from-state goto-map includes itemset nitemset
317   kernel-base kernel-end kernel-items last-reduction last-shift
318   last-state lookaheads lookaheadset lookback maxrhs ngotos nitems
319   nrules nshifts nstates nsyms ntokens nullable nvars rassoc redset
320   reduction-table ritem rlhs rprec rrc-count rrc-total rrhs ruseful
321   rcode ruleset rulesetsize shift-symbol shift-table shiftset
322   src-count src-total start-table state-table tags this-state to-state
323   tokensetsize ;; nb of words req. to hold a bit for each rule
324   varsetsize ;; nb of words req. to hold a bit for each variable
325   error-token-number start-symbol token-list var-list
326   N P V V1 nuseless-nonterminals nuseless-productions
327   ptable ;; symbols & characters properties
328   )
329
330 (defmacro wisent-ISTOKEN (s)
331   "Return non-nil if item number S defines a token (terminal).
332 That is if S < `ntokens'."
333   `(< ,s ntokens))
334
335 (defmacro wisent-ISVAR(s)
336   "Return non-nil if item number S defines a nonterminal.
337 That is if S >= `ntokens'."
338   `(>= ,s ntokens))
339
340 (defsubst wisent-tag (s)
341   "Return printable form of item number S."
342   (wisent-item-to-string (aref tags s)))
343
344 ;; Symbol and character properties
345
346 (defsubst wisent-put (object propname value)
347   "Store OBJECT's PROPNAME property with value VALUE.
348 Use `eq' to locate OBJECT."
349   (let ((entry (assq object ptable)))
350     (or entry (setq entry (list object) ptable (cons entry ptable)))
351     (setcdr entry (plist-put (cdr entry) propname value))))
352
353 (defsubst wisent-get (object propname)
354   "Return the value of OBJECT's PROPNAME property.
355 Use `eq' to locate OBJECT."
356   (plist-get (cdr (assq object ptable)) propname))
357
358 (defsubst wisent-item-number (x)
359   "Return the item number of symbol X."
360   (wisent-get x 'wisent--item-no))
361
362 (defsubst wisent-set-item-number (x n)
363   "Set the item number of symbol X to N."
364   (wisent-put x 'wisent--item-no n))
365
366 (defsubst wisent-assoc (x)
367   "Return the associativity of symbol X."
368   (wisent-get x 'wisent--assoc))
369
370 (defsubst wisent-set-assoc (x a)
371   "Set the associativity of symbol X to A."
372   (wisent-put x 'wisent--assoc a))
373
374 (defsubst wisent-prec (x)
375   "Return the precedence level of symbol X."
376   (wisent-get x 'wisent--prec))
377
378 (defsubst wisent-set-prec (x p)
379   "Set the precedence level of symbol X to P."
380   (wisent-put x 'wisent--prec p))
381 \f
382 ;;;; ----------------------------------------------------------
383 ;;;; Type definitions for nondeterministic finite state machine
384 ;;;; ----------------------------------------------------------
385
386 ;; These type definitions are used to represent a nondeterministic
387 ;; finite state machine that parses the specified grammar.  This
388 ;; information is generated by the function `wisent-generate-states'.
389
390 ;; Each state of the machine is described by a set of items --
391 ;; particular positions in particular rules -- that are the possible
392 ;; places where parsing could continue when the machine is in this
393 ;; state.  These symbols at these items are the allowable inputs that
394 ;; can follow now.
395
396 ;; A core represents one state.  States are numbered in the number
397 ;; field.  When `wisent-generate-states' is finished, the starting
398 ;; state is state 0 and `nstates' is the number of states.  (A
399 ;; transition to a state whose state number is `nstates' indicates
400 ;; termination.)  All the cores are chained together and `first-state'
401 ;; points to the first one (state 0).
402
403 ;; For each state there is a particular symbol which must have been
404 ;; the last thing accepted to reach that state.  It is the
405 ;; accessing-symbol of the core.
406
407 ;; Each core contains a vector of `nitems' items which are the indices
408 ;; in the `ritems' vector of the items that are selected in this
409 ;; state.
410
411 ;; The link field is used for chaining buckets that hash states by
412 ;; their itemsets.  This is for recognizing equivalent states and
413 ;; combining them when the states are generated.
414
415 ;; The two types of transitions are shifts (push the lookahead token
416 ;; and read another) and reductions (combine the last n things on the
417 ;; stack via a rule, replace them with the symbol that the rule
418 ;; derives, and leave the lookahead token alone).  When the states are
419 ;; generated, these transitions are represented in two other lists.
420
421 ;; Each shifts structure describes the possible shift transitions out
422 ;; of one state, the state whose number is in the number field.  The
423 ;; shifts structures are linked through next and first-shift points to
424 ;; them.  Each contains a vector of numbers of the states that shift
425 ;; transitions can go to.  The accessing-symbol fields of those
426 ;; states' cores say what kind of input leads to them.
427
428 ;; A shift to state zero should be ignored.  Conflict resolution
429 ;; deletes shifts by changing them to zero.
430
431 ;; Each reductions structure describes the possible reductions at the
432 ;; state whose number is in the number field.  The data is a list of
433 ;; nreds rules, represented by their rule numbers.  `first-reduction'
434 ;; points to the list of these structures.
435
436 ;; Conflict resolution can decide that certain tokens in certain
437 ;; states should explicitly be errors (for implementing %nonassoc).
438 ;; For each state, the tokens that are errors for this reason are
439 ;; recorded in an errs structure, which has the state number in its
440 ;; number field.  The rest of the errs structure is full of token
441 ;; numbers.
442
443 ;; There is at least one shift transition present in state zero.  It
444 ;; leads to a next-to-final state whose accessing-symbol is the
445 ;; grammar's start symbol.  The next-to-final state has one shift to
446 ;; the final state, whose accessing-symbol is zero (end of input).
447 ;; The final state has one shift, which goes to the termination state
448 ;; (whose number is `nstates'-1).
449 ;; The reason for the extra state at the end is to placate the
450 ;; parser's strategy of making all decisions one token ahead of its
451 ;; actions.
452
453 (wisent-struct core
454   next                                  ; -> core
455   link                                  ; -> core
456   (number 0)
457   (accessing-symbol 0)
458   (nitems 0)
459   (items [0]))
460
461 (wisent-struct shifts
462   next                                  ; -> shifts
463   (number 0)
464   (nshifts 0)
465   (shifts [0]))
466
467 (wisent-struct reductions
468   next                                  ; -> reductions
469   (number 0)
470   (nreds 0)
471   (rules [0]))
472
473 (wisent-struct errs
474   (nerrs 0)
475   (errs [0]))
476 \f
477 ;;;; --------------------------------------------------------
478 ;;;; Find unreachable terminals, nonterminals and productions
479 ;;;; --------------------------------------------------------
480
481 (defun wisent-bits-equal (L R n)
482   "Visit L and R and return non-nil if their first N elements are `='.
483 L and R must be vectors of integers."
484   (let* ((i    (1- n))
485          (iseq t))
486     (while (and iseq (natnump i))
487       (setq iseq (= (aref L i) (aref R i))
488             i (1- i)))
489     iseq))
490
491 (defun wisent-nbits (i)
492   "Return number of bits set in integer I."
493   (let ((count 0))
494     (while (not (zerop i))
495       ;; i ^= (i & ((unsigned) (-(int) i)))
496       (setq i (logxor i (logand i (- i)))
497             count (1+ count)))
498     count))
499
500 (defun wisent-bits-size (S n)
501   "In vector S count the total of bits set in first N elements.
502 S must be a vector of integers."
503   (let* ((i (1- n))
504          (count 0))
505     (while (natnump i)
506       (setq count (+ count (wisent-nbits (aref S i)))
507             i (1- i)))
508     count))
509
510 (defun wisent-useful-production (i N0)
511   "Return non-nil if production I is in useful set N0."
512   (let* ((useful t)
513          (r (aref rrhs i))
514          n)
515     (while (and useful (> (setq n (aref ritem r)) 0))
516       (if (wisent-ISVAR n)
517           (setq useful (wisent-BITISSET N0 (- n ntokens))))
518       (setq r (1+ r)))
519     useful))
520
521 (defun wisent-useless-nonterminals ()
522   "Find out which nonterminals are used."
523   (let (Np Ns i n break)
524     ;; N is set as built.  Np is set being built this iteration. P is
525     ;; set of all productions which have a RHS all in N.
526     (setq n  (wisent-WORDSIZE nvars)
527           Np (make-vector n 0))
528     
529     ;; The set being computed is a set of nonterminals which can
530     ;; derive the empty string or strings consisting of all
531     ;; terminals. At each iteration a nonterminal is added to the set
532     ;; if there is a production with that nonterminal as its LHS for
533     ;; which all the nonterminals in its RHS are already in the set.
534     ;; Iterate until the set being computed remains unchanged.  Any
535     ;; nonterminals not in the set at that point are useless in that
536     ;; they will never be used in deriving a sentence of the language.
537     
538     ;; This iteration doesn't use any special traversal over the
539     ;; productions.  A set is kept of all productions for which all
540     ;; the nonterminals in the RHS are in useful.  Only productions
541     ;; not in this set are scanned on each iteration.  At the end,
542     ;; this set is saved to be used when finding useful productions:
543     ;; only productions in this set will appear in the final grammar.
544     
545     (while (not break)
546       (setq i (1- n))
547       (while (natnump i)
548         ;; Np[i] = N[i]
549         (aset Np i (aref N i))
550         (setq i (1- i)))
551       
552       (setq i 1)
553       (while (<= i nrules)
554         (if (not (wisent-BITISSET P i))
555             (when (wisent-useful-production i N)
556               (wisent-SETBIT Np (- (aref rlhs i) ntokens))
557               (wisent-SETBIT P i)))
558         (setq i (1+ i)))
559       (if (wisent-bits-equal N Np n)
560           (setq break t)
561         (setq Ns Np
562               Np N
563               N  Ns)))
564     (setq N Np)))
565
566 (defun wisent-inaccessable-symbols ()
567   "Find out which productions are reachable and which symbols are used."
568   ;; Starting with an empty set of productions and a set of symbols
569   ;; which only has the start symbol in it, iterate over all
570   ;; productions until the set of productions remains unchanged for an
571   ;; iteration.  For each production which has a LHS in the set of
572   ;; reachable symbols, add the production to the set of reachable
573   ;; productions, and add all of the nonterminals in the RHS of the
574   ;; production to the set of reachable symbols.
575   
576   ;; Consider only the (partially) reduced grammar which has only
577   ;; nonterminals in N and productions in P.
578   
579   ;; The result is the set P of productions in the reduced grammar,
580   ;; and the set V of symbols in the reduced grammar.
581   
582   ;; Although this algorithm also computes the set of terminals which
583   ;; are reachable, no terminal will be deleted from the grammar. Some
584   ;; terminals might not be in the grammar but might be generated by
585   ;; semantic routines, and so the user might want them available with
586   ;; specified numbers.  (Is this true?)  However, the non reachable
587   ;; terminals are printed (if running in verbose mode) so that the
588   ;; user can know.
589   (let (Vp Vs Pp i tt r n m break)
590     (setq n  (wisent-WORDSIZE nsyms)
591           m  (wisent-WORDSIZE (1+ nrules))
592           Vp (make-vector n 0)
593           Pp (make-vector m 0))
594     
595     ;; If the start symbol isn't useful, then nothing will be useful.
596     (when (wisent-BITISSET N (- start-symbol ntokens))
597       (wisent-SETBIT V start-symbol)
598       (while (not break)
599         (setq i (1- n))
600         (while (natnump i)
601           (aset Vp i (aref V i))
602           (setq i (1- i)))
603         (setq i 1)
604         (while (<= i nrules)
605           (when (and (not (wisent-BITISSET Pp i))
606                      (wisent-BITISSET P i)
607                      (wisent-BITISSET V (aref rlhs i)))
608             (setq r (aref rrhs i))
609             (while (natnump (setq tt (aref ritem r)))
610               (if (or (wisent-ISTOKEN tt)
611                       (wisent-BITISSET N (- tt ntokens)))
612                   (wisent-SETBIT Vp tt))
613               (setq r (1+ r)))
614             (wisent-SETBIT Pp i))
615           (setq i (1+ i)))
616         (if (wisent-bits-equal V Vp n)
617             (setq break t)
618           (setq Vs Vp
619                 Vp V
620                 V  Vs))))
621     (setq V Vp)
622     
623     ;; Tokens 0, 1 are internal to Wisent.  Consider them useful.
624     (wisent-SETBIT V 0) ;; end-of-input token
625     (wisent-SETBIT V 1) ;; error token
626     (setq P Pp)
627     
628     (setq nuseless-productions  (- nrules (wisent-bits-size P m))
629           nuseless-nonterminals nvars
630           i ntokens)
631     (while (< i nsyms)
632       (if (wisent-BITISSET V i)
633           (setq nuseless-nonterminals (1- nuseless-nonterminals)))
634       (setq i (1+ i)))
635     
636     ;; A token that was used in %prec should not be warned about.
637     (setq i 1)
638     (while (<= i nrules)
639       (if (aref rprec i)
640           (wisent-SETBIT V1 (aref rprec i)))
641       (setq i (1+ i)))
642     ))
643
644 (defun wisent-reduce-grammar-tables ()
645   "Disable useless productions."
646   (if (> nuseless-productions 0)
647       (let ((pn 1))
648         (while (<= pn nrules)
649           (aset ruseful pn (wisent-BITISSET P pn))
650           (setq pn (1+ pn))))))
651
652 (defun wisent-nonterminals-reduce ()
653   "Remove useless nonterminals."
654   (let (i n r item nontermmap tags-sorted)
655     ;; Map the nonterminals to their new index: useful first, useless
656     ;; afterwards.  Kept for later report.
657     (setq nontermmap (make-vector nvars 0)
658           n ntokens
659           i ntokens)
660     (while (< i nsyms)
661       (when (wisent-BITISSET V i)
662         (aset nontermmap (- i ntokens) n)
663         (setq n (1+ n)))
664       (setq i (1+ i)))
665     (setq i ntokens)
666     (while (< i nsyms)
667       (unless (wisent-BITISSET V i)
668         (aset nontermmap (- i ntokens) n)
669         (setq n (1+ n)))
670       (setq i (1+ i)))
671     ;; Shuffle elements of tables indexed by symbol number
672     (setq tags-sorted (make-vector nvars nil)
673           i ntokens)
674     (while (< i nsyms)
675       (setq n (aref nontermmap (- i ntokens)))
676       (aset tags-sorted (- n ntokens) (aref tags i))
677       (setq i (1+ i)))
678     (setq i ntokens)
679     (while (< i nsyms)
680       (aset tags i (aref tags-sorted (- i ntokens)))
681       (setq i (1+ i)))
682     ;; Replace all symbol numbers in valid data structures.
683     (setq i 1)
684     (while (<= i nrules)
685       (aset rlhs i (aref nontermmap (- (aref rlhs i) ntokens)))
686       (setq i (1+ i)))
687     (setq r 0)
688     (while (setq item (aref ritem r))
689       (if (wisent-ISVAR item)
690           (aset ritem r (aref nontermmap (- item ntokens))))
691       (setq r (1+ r)))
692     (setq start-symbol (aref nontermmap (- start-symbol ntokens))
693           nsyms (- nsyms nuseless-nonterminals)
694           nvars (- nvars nuseless-nonterminals))
695     ))
696
697 (defun wisent-total-useless ()
698   "Report number of useless nonterminals and productions."
699   (let* ((src (wisent-source))
700          (src (if src (concat " in " src) ""))
701          (msg (format "Grammar%s contains" src)))
702     (if (> nuseless-nonterminals 0)
703         (setq msg (format "%s %d useless nonterminal%s"
704                           msg nuseless-nonterminals
705                           (if (> nuseless-nonterminals 0) "s" ""))))
706     (if (and (> nuseless-nonterminals 0) (> nuseless-productions 0))
707         (setq msg (format "%s and" msg)))
708     (if (> nuseless-productions 0)
709         (setq msg (format "%s %d useless rule%s"
710                           msg nuseless-productions
711                           (if (> nuseless-productions 0) "s" ""))))
712     (message msg)))
713
714 (defun wisent-reduce-grammar ()
715   "Find unreachable terminals, nonterminals and productions."
716   ;; Allocate the global sets used to compute the reduced grammar
717   (setq N  (make-vector (wisent-WORDSIZE nvars) 0)
718         P  (make-vector (wisent-WORDSIZE (1+ nrules)) 0)
719         V  (make-vector (wisent-WORDSIZE nsyms) 0)
720         V1 (make-vector (wisent-WORDSIZE nsyms) 0)
721         nuseless-nonterminals 0
722         nuseless-productions  0)
723   
724   (wisent-useless-nonterminals)
725   (wisent-inaccessable-symbols)
726   
727   (when (> (+ nuseless-nonterminals nuseless-productions) 0)
728     (wisent-total-useless)
729     (or (wisent-BITISSET N (- start-symbol ntokens))
730         (error "Start symbol `%s' does not derive any sentence"
731                (wisent-tag start-symbol)))
732     (wisent-reduce-grammar-tables)
733     (if (> nuseless-nonterminals 0)
734         (wisent-nonterminals-reduce))))
735
736 (defun wisent-print-useless ()
737   "Output the detailed results of the reductions."
738   (let (i b r)
739     (when (> nuseless-nonterminals 0)
740       ;; Useless nonterminals have been moved after useful ones.
741       (wisent-log "\n\nUseless nonterminals:\n\n")
742       (setq i 0)
743       (while (< i nuseless-nonterminals)
744         (wisent-log "   %s\n" (wisent-tag (+ nsyms i)))
745         (setq i (1+ i))))
746     (setq b nil
747           i 0)
748     (while (< i ntokens)
749       (unless (or (wisent-BITISSET V i) (wisent-BITISSET V1 i))
750         (or b
751             (wisent-log "\n\nTerminals which are not used:\n\n"))
752         (setq b t)
753         (wisent-log "   %s\n" (wisent-tag i)))
754       (setq i (1+ i)))
755     (when (> nuseless-productions 0)
756       (wisent-log "\n\nUseless rules:\n\n")
757       (setq i 1)
758       (while (<= i nrules)
759         (unless (aref ruseful i)
760           (wisent-log "#%s  " (wisent-pad-string (format "%d" i) 4))
761           (wisent-log "%s:" (wisent-tag (aref rlhs i)))
762           (setq r (aref rrhs i))
763           (while (natnump (aref ritem r))
764             (wisent-log " %s" (wisent-tag (aref ritem r)))
765             (setq r (1+ r)))
766           (wisent-log ";\n"))
767         (setq i (1+ i))))
768     (if (or b (> nuseless-nonterminals 0) (> nuseless-productions 0))
769         (wisent-log "\n\n"))
770     ))
771 \f
772 ;;;; -----------------------------
773 ;;;; Match rules with nonterminals
774 ;;;; -----------------------------
775
776 (defun wisent-set-derives ()
777   "Find, for each variable (nonterminal), which rules can derive it.
778 It sets up the value of DERIVES so that DERIVES[i - NTOKENS] points to
779 a list of rule numbers, terminated with -1."
780   (let (i lhs p q dset delts)
781     (setq dset (make-vector nvars nil)
782           delts (make-vector (1+ nrules) 0))
783     (setq p 0 ;; p = delts
784           i nrules)
785     (while (> i 0)
786       (when (aref ruseful i)
787         (setq lhs (aref rlhs i))
788         ;; p->next = dset[lhs];
789         ;; p->value = i;
790         (aset delts p (cons i (aref dset (- lhs ntokens)))) ;; (value . next)
791         (aset dset (- lhs ntokens) p) ;; dset[lhs] = p
792         (setq p (1+ p)) ;; p++
793         )
794       (setq i (1- i)))
795     
796     (setq derives (make-vector nvars nil)
797           i       ntokens)
798     
799     (while (< i nsyms)
800       (setq q nil
801             p (aref dset (- i ntokens))) ;; p = dset[i]
802       
803       (while p
804         (setq p (aref delts p)
805               q (cons (car p) q) ;;q++ = p->value
806               p (cdr p))) ;; p = p->next
807       (setq q (nreverse (cons -1 q))) ;; *q++ = -1
808       (aset derives (- i ntokens) q) ;; derives[i] = q
809       (setq i (1+ i)))
810     ))
811 \f
812 ;;;; --------------------------------------------------------
813 ;;;; Find which nonterminals can expand into the null string.
814 ;;;; --------------------------------------------------------
815
816 (defun wisent-print-nullable ()
817   "Print NULLABLE."
818   (let (i)
819     (wisent-log "NULLABLE\n")
820     (setq i ntokens)
821     (while (< i nsyms)
822       (wisent-log "\t%s: %s\n" (wisent-tag i)
823                   (if (aref nullable (- i ntokens))
824                       "yes" : "no"))
825       (setq i (1+ i)))
826     (wisent-log "\n\n")))
827
828 (defun wisent-set-nullable ()
829   "Set up NULLABLE.
830 A vector saying which nonterminals can expand into the null string.
831 NULLABLE[i - NTOKENS] is nil if symbol I can do so."
832   (let (ruleno s1 s2 p r squeue rcount rsets relts item any-tokens)
833     (setq squeue (make-vector nvars 0)
834           rcount (make-vector (1+ nrules) 0)
835           rsets  (make-vector nvars nil) ;; - ntokens
836           relts  (make-vector (+ nitems nvars 1) nil)
837           nullable (make-vector nvars nil)) ;; - ntokens
838     (setq s1 0 s2 0 ;; s1 = s2 = squeue
839           p 0 ;; p = relts
840           ruleno 1)
841     (while (<= ruleno nrules)
842       (when (aref ruseful ruleno)
843         (if (> (aref ritem (aref rrhs ruleno)) 0)
844             (progn
845               ;; This rule has a non empty RHS.
846               (setq any-tokens nil
847                     r (aref rrhs ruleno))
848               (while (> (aref ritem r) 0)
849                 (if (wisent-ISTOKEN (aref ritem r))
850                     (setq any-tokens t))
851                 (setq r (1+ r)))
852               
853               ;; This rule has only nonterminals: schedule it for the
854               ;; second pass.
855               (unless any-tokens
856                 (setq r (aref rrhs ruleno))
857                 (while (> (setq item (aref ritem r)) 0)
858                   (aset rcount ruleno (1+ (aref rcount ruleno)))
859                   ;; p->next = rsets[item];
860                   ;; p->value = ruleno;
861                   (aset relts p (cons ruleno (aref rsets (- item ntokens))))
862                   ;; rsets[item] = p;
863                   (aset rsets (- item ntokens) p)
864                   (setq p (1+ p)
865                         r (1+ r)))))
866           ;; This rule has an empty RHS.
867           ;; assert (ritem[rrhs[ruleno]] == -ruleno)
868           (when (and (aref ruseful ruleno)
869                      (setq item (aref rlhs ruleno))
870                      (not (aref nullable (- item ntokens))))
871             (aset nullable (- item ntokens) t)
872             (aset squeue s2 item)
873             (setq s2 (1+ s2)))
874           )
875         )
876       (setq ruleno (1+ ruleno)))
877     
878     (while (< s1 s2)
879       ;; p = rsets[*s1++]
880       (setq p (aref rsets (- (aref squeue s1) ntokens))
881             s1 (1+ s1))
882       (while p
883         (setq p (aref relts p)
884               ruleno (car p)
885               p (cdr p)) ;; p = p->next
886         ;; if (--rcount[ruleno] == 0)
887         (when (zerop (aset rcount ruleno (1- (aref rcount ruleno))))
888           (setq item (aref rlhs ruleno))
889           (aset nullable (- item ntokens) t)
890           (aset squeue s2 item)
891           (setq s2 (1+ s2)))))
892     
893     (if wisent-debug-flag
894         (wisent-print-nullable))
895     ))
896 \f
897 ;;;; -----------
898 ;;;; Subroutines
899 ;;;; -----------
900
901 (defun wisent-print-fderives ()
902   "Print FDERIVES."
903   (let (i j rp)
904     (wisent-log "\n\n\nFDERIVES\n")
905     (setq i ntokens)
906     (while (< i nsyms)
907       (wisent-log "\n\n%s derives\n\n" (wisent-tag i))
908       (setq rp (aref fderives (- i ntokens))
909             j  0)
910       (while (<= j nrules)
911         (if (wisent-BITISSET rp j)
912             (wisent-log "   %d\n" j))
913         (setq j (1+ j)))
914       (setq i (1+ i)))))
915
916 (defun wisent-set-fderives ()
917   "Set up FDERIVES.
918 An NVARS by NRULES matrix of bits indicating which rules can help
919 derive the beginning of the data for each nonterminal.  For example,
920 if symbol 5 can be derived as the sequence of symbols 8 3 20, and one
921 of the rules for deriving symbol 8 is rule 4, then the
922 \[5 - NTOKENS, 4] bit in FDERIVES is set."
923   (let (i j k)
924     (setq fderives (make-vector nvars nil))
925     (setq i 0)
926     (while (< i nvars)
927       (aset fderives i (make-vector rulesetsize 0))
928       (setq i (1+ i)))
929     
930     (wisent-set-firsts)
931     
932     (setq i ntokens)
933     (while (< i nsyms)
934       (setq j ntokens)
935       (while (< j nsyms)
936         ;; if (BITISSET (FIRSTS (i), j - ntokens))
937         (when (wisent-BITISSET (aref firsts (- i ntokens)) (- j ntokens))
938           (setq k (aref derives (- j ntokens)))
939           (while (> (car k) 0) ;; derives[j][k] > 0
940             ;; SETBIT (FDERIVES (i), derives[j][k]);
941             (wisent-SETBIT (aref fderives (- i ntokens)) (car k))
942             (setq k (cdr k))))
943         (setq j (1+ j)))
944       (setq i (1+ i)))
945     
946     (if wisent-debug-flag
947         (wisent-print-fderives))
948     ))
949
950 (defun wisent-print-firsts ()
951   "Print FIRSTS."
952   (let (i j v)
953     (wisent-log "\n\n\nFIRSTS\n\n")
954     (setq i ntokens)
955     (while (< i nsyms)
956       (wisent-log "\n\n%s firsts\n\n" (wisent-tag i))
957       (setq v (aref firsts (- i ntokens))
958             j 0)
959       (while (< j nvars)
960         (if (wisent-BITISSET v j)
961             (wisent-log "\t\t%d (%s)\n"
962                         (+ j ntokens) (wisent-tag (+ j ntokens))))
963         (setq j (1+ j)))
964       (setq i (1+ i)))))
965
966 (defun wisent-TC (R n)
967   "Transitive closure.
968 Given R an N by N matrix of bits, modify its contents to be the
969 transitive closure of what was given."
970   (let (i j k)
971     ;; R (J, I) && R (I, K) => R (J, K).
972     ;; I *must* be the outer loop.
973     (setq i 0)
974     (while (< i n)
975       (setq j 0)
976       (while (< j n)
977         (when (wisent-BITISSET (aref R j) i)
978           (setq k 0)
979           (while (< k n)
980             (if (wisent-BITISSET (aref R i) k)
981                 (wisent-SETBIT (aref R j) k))
982             (setq k (1+ k))))
983         (setq j (1+ j)))
984       (setq i (1+ i)))))
985
986 (defun wisent-RTC (R n)
987   "Reflexive Transitive Closure.
988 Same as `wisent-TC' and then set all the bits on the diagonal of R, an
989 N by N matrix of bits."
990   (let (i)
991     (wisent-TC R n)
992     (setq i 0)
993     (while (< i n)
994       (wisent-SETBIT (aref R i) i)
995       (setq i (1+ i)))))
996
997 (defun wisent-set-firsts ()
998   "Set up FIRSTS.
999 An NVARS by NVARS bit matrix indicating which items can represent the
1000 beginning of the input corresponding to which other items.  For
1001 example, if some rule expands symbol 5 into the sequence of symbols 8
1002 3 20, the symbol 8 can be the beginning of the data for symbol 5, so
1003 the bit [8 - NTOKENS, 5 - NTOKENS] in FIRSTS is set."
1004   (let (row symbol sp rowsize i)
1005     (setq rowsize (wisent-WORDSIZE nvars)
1006           varsetsize rowsize
1007           firsts (make-vector nvars nil)
1008           i 0)
1009     (while (< i nvars)
1010       (aset firsts i (make-vector rowsize 0))
1011       (setq i (1+ i)))
1012     
1013     (setq row 0 ;; row = firsts
1014           i ntokens)
1015     (while (< i nsyms)
1016       (setq sp (aref derives (- i ntokens)))
1017       (while (>= (car sp) 0)
1018         (setq symbol (aref ritem (aref rrhs (car sp)))
1019               sp (cdr sp))
1020         (when (wisent-ISVAR symbol)
1021           (setq symbol (- symbol ntokens))
1022           (wisent-SETBIT (aref firsts row) symbol)
1023           ))
1024       (setq row (1+ row)
1025             i   (1+ i)))
1026     
1027     (wisent-RTC firsts nvars)
1028     
1029     (if wisent-debug-flag
1030         (wisent-print-firsts))
1031     ))
1032
1033 (defun wisent-initialize-closure (n)
1034   "Allocate the ITEMSET and RULESET vectors.
1035 And precompute useful data so that `wisent-closure' can be called.
1036 N is the number of elements to allocate for ITEMSET."
1037   (setq itemset (make-vector n 0)
1038         rulesetsize (wisent-WORDSIZE (1+ nrules))
1039         ruleset (make-vector rulesetsize 0))
1040   
1041   (wisent-set-fderives))
1042
1043 (defun wisent-print-closure ()
1044   "Print ITEMSET."
1045   (let (i)
1046     (wisent-log "\n\nclosure n = %d\n\n" nitemset)
1047     (setq i 0) ;; isp = itemset
1048     (while (< i nitemset)
1049       (wisent-log "   %d\n" (aref itemset i))
1050       (setq i (1+ i)))))
1051
1052 (defun wisent-closure (core n)
1053   "Set up RULESET and ITEMSET for the transitions out of CORE state.
1054 Given a vector of item numbers items, of length N, set up RULESET and
1055 ITEMSET to indicate what rules could be run and which items could be
1056 accepted when those items are the active ones.
1057
1058 RULESET contains a bit for each rule.  `wisent-closure' sets the bits
1059 for all rules which could potentially describe the next input to be
1060 read.
1061
1062 ITEMSET is a vector of item numbers; NITEMSET is the number of items
1063 in ITEMSET.  `wisent-closure' places there the indices of all items
1064 which represent units of input that could arrive next."
1065   (let (c r v symbol ruleno itemno)
1066     (if (zerop n)
1067         (progn
1068           (setq r 0
1069                 v (aref fderives (- start-symbol ntokens)))
1070           (while (< r rulesetsize)
1071             ;; ruleset[r] = FDERIVES (start-symbol)[r];
1072             (aset ruleset r (aref v r))
1073             (setq r (1+ r)))
1074           )
1075       (fillarray ruleset 0)
1076       (setq c 0)
1077       (while (< c n)
1078         (setq symbol (aref ritem (aref core c)))
1079         (when (wisent-ISVAR symbol)
1080           (setq r 0
1081                 v (aref fderives (- symbol ntokens)))
1082           (while (< r rulesetsize)
1083             ;; ruleset[r] |= FDERIVES (ritem[core[c]])[r];
1084             (aset ruleset r (logior (aref ruleset r) (aref v r)))
1085             (setq r (1+ r))))
1086         (setq c (1+ c)))
1087       )
1088     (setq nitemset 0
1089           c 0
1090           ruleno 0
1091           r (* rulesetsize wisent-BITS-PER-WORD))
1092     (while (< ruleno r)
1093       (when (wisent-BITISSET ruleset ruleno)
1094         (setq itemno (aref rrhs ruleno))
1095         (while (and (< c n) (< (aref core c) itemno))
1096           (aset itemset nitemset (aref core c))
1097           (setq nitemset (1+ nitemset)
1098                 c (1+ c)))
1099         (aset itemset nitemset itemno)
1100         (setq nitemset (1+ nitemset)))
1101       (setq ruleno (1+ ruleno)))
1102     
1103     (while (< c n)
1104       (aset itemset nitemset (aref core c))
1105       (setq nitemset (1+ nitemset)
1106             c (1+ c)))
1107     
1108     (if wisent-debug-flag
1109         (wisent-print-closure))
1110     ))
1111 \f
1112 ;;;; --------------------------------------------------
1113 ;;;; Generate the nondeterministic finite state machine
1114 ;;;; --------------------------------------------------
1115
1116 (defun wisent-allocate-itemsets ()
1117   "Allocate storage for itemsets."
1118   (let (symbol i count symbol-count)
1119     ;; Count the number of occurrences of all the symbols in RITEMS.
1120     ;; Note that useless productions (hence useless nonterminals) are
1121     ;; browsed too, hence we need to allocate room for _all_ the
1122     ;; symbols.
1123     (setq count 0
1124           symbol-count (make-vector (+ nsyms nuseless-nonterminals) 0)
1125           i 0)
1126     (while (setq symbol (aref ritem i))
1127       (when (> symbol 0)
1128         (setq count (1+ count))
1129         (aset symbol-count symbol (1+ (aref symbol-count symbol))))
1130       (setq i (1+ i)))
1131     ;; See comments before `wisent-new-itemsets'.  All the vectors of
1132     ;; items live inside kernel-items.  The number of active items
1133     ;; after some symbol cannot be more than the number of times that
1134     ;; symbol appears as an item, which is symbol-count[symbol].  We
1135     ;; allocate that much space for each symbol.
1136     (setq kernel-base (make-vector nsyms nil)
1137           kernel-items (make-vector count 0)
1138           count 0
1139           i 0)
1140     (while (< i nsyms)
1141       (aset kernel-base i count)
1142       (setq count (+ count (aref symbol-count i))
1143             i (1+ i)))
1144     (setq shift-symbol symbol-count
1145           kernel-end (make-vector nsyms nil))
1146     ))
1147
1148 (defun wisent-allocate-storage ()
1149   "Allocate storage for the state machine."
1150   (wisent-allocate-itemsets)
1151   (setq shiftset (make-vector nsyms 0)
1152         redset (make-vector (1+ nrules) 0)
1153         state-table (make-vector wisent-state-table-size nil)))
1154
1155 (defun wisent-new-itemsets ()
1156   "Find which symbols can be shifted in the current state.
1157 And for each one record which items would be active after that shift.
1158 Uses the contents of ITEMSET.  SHIFT-SYMBOL is set to a vector of the
1159 symbols that can be shifted.  For each symbol in the grammar,
1160 KERNEL-BASE[symbol] points to a vector of item numbers activated if
1161 that symbol is shifted, and KERNEL-END[symbol] points after the end of
1162 that vector."
1163   (let (i shiftcount isp ksp symbol)
1164     (fillarray kernel-end nil)
1165     (setq shiftcount 0
1166           isp 0)
1167     (while (< isp nitemset)
1168       (setq i (aref itemset isp)
1169             isp (1+ isp)
1170             symbol (aref ritem i))
1171       (when (> symbol 0)
1172         (setq ksp (aref kernel-end symbol))
1173         (when (not ksp)
1174           ;; shift-symbol[shiftcount++] = symbol;
1175           (aset shift-symbol shiftcount symbol)
1176           (setq shiftcount (1+ shiftcount)
1177                 ksp (aref kernel-base symbol)))
1178         ;; *ksp++ = i + 1;
1179         (aset kernel-items ksp (1+ i))
1180         (setq ksp (1+ ksp))
1181         (aset kernel-end symbol ksp)))
1182     (setq nshifts shiftcount)))
1183
1184 (defun wisent-new-state (symbol)
1185   "Create a new state for those items, if necessary.
1186 SYMBOL is the core accessing-symbol.
1187 Subroutine of `wisent-get-state'."
1188   (let (n p isp1 isp2 iend items)
1189     (setq isp1  (aref kernel-base symbol)
1190           iend  (aref kernel-end symbol)
1191           n     (- iend isp1)
1192           p     (make-core)
1193           items (make-vector n 0))
1194     (set-core-accessing-symbol p symbol)
1195     (set-core-number p nstates)
1196     (set-core-nitems p n)
1197     (set-core-items  p items)
1198     (setq isp2 0) ;; isp2 = p->items
1199     (while (< isp1 iend)
1200       ;; *isp2++ = *isp1++;
1201       (aset items isp2 (aref kernel-items isp1))
1202       (setq isp1 (1+ isp1)
1203             isp2 (1+ isp2)))
1204     (set-core-next last-state p)
1205     (setq last-state p
1206           nstates (1+ nstates))
1207     p))
1208
1209 (defun wisent-get-state (symbol)
1210   "Find the state we would get to by shifting SYMBOL.
1211 Return the state number for the state we would get to (from the
1212 current state) by shifting SYMBOL.  Create a new state if no
1213 equivalent one exists already.  Used by `wisent-append-states'."
1214   (let (key isp1 isp2 iend sp sp2 found n)
1215     (setq isp1 (aref kernel-base symbol)
1216           iend (aref kernel-end symbol)
1217           n    (- iend isp1)
1218           key  0)
1219     ;; Add up the target state's active item numbers to get a hash key
1220     (while (< isp1 iend)
1221       (setq key (+ key (aref kernel-items isp1))
1222             isp1 (1+ isp1)))
1223     (setq key (% key wisent-state-table-size)
1224           sp (aref state-table key))
1225     (if sp
1226         (progn
1227           (setq found nil)
1228           (while (not found)
1229             (when (= (core-nitems sp) n)
1230               (setq found t
1231                     isp1 (aref kernel-base symbol)
1232                     ;; isp2 = sp->items;
1233                     sp2  (core-items sp)
1234                     isp2 0)
1235               
1236               (while (and found (< isp1 iend))
1237                 ;; if (*isp1++ != *isp2++)
1238                 (if (not (= (aref kernel-items isp1)
1239                             (aref sp2 isp2)))
1240                     (setq found nil))
1241                 (setq isp1 (1+ isp1)
1242                       isp2 (1+ isp2))))
1243             (if (not found)
1244                 (if (core-link sp)
1245                     (setq sp (core-link sp))
1246                   ;; sp = sp->link = new-state(symbol)
1247                   (setq sp (set-core-link sp (wisent-new-state symbol))
1248                         found t)))))
1249       ;; bucket is empty
1250       ;; state-table[key] = sp = new-state(symbol)
1251       (setq sp (wisent-new-state symbol))
1252       (aset state-table key sp))
1253     ;; return (sp->number);
1254     (core-number sp)))
1255
1256 (defun wisent-append-states ()
1257   "Find or create the core structures for states.
1258 Use the information computed by `wisent-new-itemsets' to find the
1259 state numbers reached by each shift transition from the current state.
1260 SHIFTSET is set up as a vector of state numbers of those states."
1261   (let (i j symbol)
1262     ;; First sort shift-symbol into increasing order
1263     (setq i 1)
1264     (while (< i nshifts)
1265       (setq symbol (aref shift-symbol i)
1266             j i)
1267       (while (and (> j 0) (> (aref shift-symbol (1- j)) symbol))
1268         (aset shift-symbol j (aref shift-symbol (1- j)))
1269         (setq j (1- j)))
1270       (aset shift-symbol j symbol)
1271       (setq i (1+ i)))
1272     (setq i 0)
1273     (while (< i nshifts)
1274       (setq symbol (aref shift-symbol i))
1275       (aset shiftset i (wisent-get-state symbol))
1276       (setq i (1+ i)))
1277     ))
1278
1279 (defun wisent-initialize-states ()
1280   "Initialize states."
1281   (let ((p (make-core)))
1282     (setq first-state p
1283           last-state  p
1284           this-state  p
1285           nstates     1)))
1286
1287 (defun wisent-save-shifts ()
1288   "Save the NSHIFTS of SHIFTSET into the current linked list."
1289   (let (p i shifts)
1290     (setq p      (make-shifts)
1291           shifts (make-vector nshifts 0)
1292           i 0)
1293     (set-shifts-number p (core-number this-state))
1294     (set-shifts-nshifts p nshifts)
1295     (set-shifts-shifts  p shifts)
1296     (while (< i nshifts)
1297       ;; (p->shifts)[i] = shiftset[i];
1298       (aset shifts i (aref shiftset i))
1299       (setq i (1+ i)))
1300     
1301     (if last-shift
1302         (set-shifts-next last-shift p)
1303       (setq first-shift p))
1304     (setq last-shift p)))
1305
1306 (defun wisent-insert-start-shift ()
1307   "Create the next-to-final state.
1308 That is the state to which a shift has already been made in the
1309 initial state.  Subroutine of `wisent-augment-automaton'."
1310   (let (statep sp)
1311     (setq statep (make-core))
1312     (set-core-number statep nstates)
1313     (set-core-accessing-symbol statep start-symbol)
1314     (set-core-next last-state statep)
1315     (setq last-state statep)
1316     ;; Make a shift from this state to (what will be) the final state.
1317     (setq sp (make-shifts))
1318     (set-shifts-number sp nstates)
1319     (setq nstates (1+ nstates))
1320     (set-shifts-nshifts sp 1)
1321     (set-shifts-shifts sp (vector nstates))
1322     (set-shifts-next last-shift sp)
1323     (setq last-shift sp)))
1324
1325 (defun wisent-augment-automaton ()
1326   "Set up initial and final states as parser wants them.
1327 Make sure that the initial state has a shift that accepts the
1328 grammar's start symbol and goes to the next-to-final state, which has
1329 a shift going to the final state, which has a shift to the termination
1330 state.  Create such states and shifts if they don't happen to exist
1331 already."
1332   (let (i k statep sp sp2 sp1 shifts)
1333     (setq sp first-shift)
1334     (if sp
1335         (progn
1336           (if (zerop (shifts-number sp))
1337               (progn
1338                 (setq k (shifts-nshifts sp)
1339                       statep (core-next first-state))
1340                 ;; The states reached by shifts from first-state are
1341                 ;; numbered 1...K.  Look for one reached by
1342                 ;; START-SYMBOL.
1343                 (while (and (< (core-accessing-symbol statep) start-symbol)
1344                             (< (core-number statep) k))
1345                   (setq statep (core-next statep)))
1346                 (if (= (core-accessing-symbol statep) start-symbol)
1347                     (progn
1348                       ;; We already have a next-to-final state.  Make
1349                       ;; sure it has a shift to what will be the final
1350                       ;; state.
1351                       (setq k (core-number statep))
1352                       (while (and sp (< (shifts-number sp) k))
1353                         (setq sp1 sp
1354                               sp (shifts-next sp)))
1355                       (if (and sp (= (shifts-number sp) k))
1356                           (progn
1357                             (setq i (shifts-nshifts sp)
1358                                   sp2 (make-shifts)
1359                                   shifts (make-vector (1+ i) 0))
1360                             (set-shifts-number sp2 k)
1361                             (set-shifts-nshifts sp2 (1+ i))
1362                             (set-shifts-shifts sp2 shifts)
1363                             (aset shifts 0 nstates)
1364                             (while (> i 0)
1365                               ;; sp2->shifts[i] = sp->shifts[i - 1];
1366                               (aset shifts i (aref (shifts-shifts sp) (1- i)))
1367                               (setq i (1- i)))
1368                             ;; Patch sp2 into the chain of shifts in
1369                             ;; place of sp, following sp1.
1370                             (set-shifts-next sp2 (shifts-next sp))
1371                             (set-shifts-next sp1 sp2)
1372                             (if (eq sp last-shift)
1373                                 (setq last-shift sp2))
1374                             )
1375                         (setq sp2 (make-shifts))
1376                         (set-shifts-number sp2 k)
1377                         (set-shifts-nshifts sp2 1)
1378                         (set-shifts-shifts sp2 (vector nstates))
1379                         ;; Patch sp2 into the chain of shifts between
1380                         ;; sp1 and sp.
1381                         (set-shifts-next sp2 sp)
1382                         (set-shifts-next sp1 sp2)
1383                         (if (not sp)
1384                             (setq last-shift sp2))
1385                         )
1386                       )
1387                   ;; There is no next-to-final state as yet.
1388                   ;; Add one more shift in FIRST-SHIFT, going to the
1389                   ;; next-to-final state (yet to be made).
1390                   (setq sp first-shift
1391                         sp2 (make-shifts)
1392                         i   (shifts-nshifts sp)
1393                         shifts (make-vector (1+ i) 0))
1394                   (set-shifts-nshifts sp2 (1+ i))
1395                   (set-shifts-shifts sp2 shifts)
1396                   ;; Stick this shift into the vector at the proper place.
1397                   (setq statep (core-next first-state)
1398                         k 0
1399                         i 0)
1400                   (while (< i (shifts-nshifts sp))
1401                     (when (and (> (core-accessing-symbol statep) start-symbol)
1402                                (= i k))
1403                       (aset shifts k nstates)
1404                       (setq k (1+ k)))
1405                     (aset shifts k (aref (shifts-shifts sp) i))
1406                     (setq statep (core-next statep))
1407                     (setq i (1+ i)
1408                           k (1+ k)))
1409                   (when (= i k)
1410                     (aset shifts k nstates)
1411                     (setq k (1+ k)))
1412                   ;; Patch sp2 into the chain of shifts in place of
1413                   ;; sp, at the beginning.
1414                   (set-shifts-next sp2 (shifts-next sp))
1415                   (setq first-shift sp2)
1416                   (if (eq last-shift sp)
1417                       (setq last-shift sp2))
1418                   ;; Create the next-to-final state, with shift to
1419                   ;; what will be the final state.
1420                   (wisent-insert-start-shift)))
1421             ;; The initial state didn't even have any shifts.  Give it
1422             ;; one shift, to the next-to-final state.
1423             (setq sp (make-shifts))
1424             (set-shifts-nshifts sp 1)
1425             (set-shifts-shifts sp (vector nstates))
1426             ;; Patch sp into the chain of shifts at the beginning.
1427             (set-shifts-next sp first-shift)
1428             (setq first-shift sp)
1429             ;; Create the next-to-final state, with shift to what will
1430             ;; be the final state.
1431             (wisent-insert-start-shift)))
1432       ;; There are no shifts for any state.  Make one shift, from the
1433       ;; initial state to the next-to-final state.
1434       (setq sp (make-shifts))
1435       (set-shifts-nshifts sp 1)
1436       (set-shifts-shifts sp (vector nstates))
1437       ;; Initialize the chain of shifts with sp.
1438       (setq first-shift sp
1439             last-shift sp)
1440       ;; Create the next-to-final state, with shift to what will be
1441       ;; the final state.
1442       (wisent-insert-start-shift))
1443     ;; Make the final state--the one that follows a shift from the
1444     ;; next-to-final state.  The symbol for that shift is 0
1445     ;; (end-of-file).
1446     (setq statep (make-core))
1447     (set-core-number statep nstates)
1448     (set-core-next last-state statep)
1449     (setq last-state statep)
1450     ;; Make the shift from the final state to the termination state.
1451     (setq sp (make-shifts))
1452     (set-shifts-number sp nstates)
1453     (setq nstates (1+ nstates))
1454     (set-shifts-nshifts sp 1)
1455     (set-shifts-shifts sp (vector nstates))
1456     (set-shifts-next last-shift sp)
1457     (setq last-shift sp)
1458     ;; Note that the variable FINAL-STATE refers to what we sometimes
1459     ;; call the termination state.
1460     (setq final-state nstates)
1461     ;; Make the termination state.
1462     (setq statep (make-core))
1463     (set-core-number statep nstates)
1464     (setq nstates (1+ nstates))
1465     (set-core-next last-state statep)
1466     (setq last-state statep)))
1467
1468 (defun wisent-save-reductions ()
1469   "Make a reductions structure.
1470 Find which rules can be used for reduction transitions from the
1471 current state and make a reductions structure for the state to record
1472 their rule numbers."
1473   (let (i item count p rules)
1474     ;; Find and count the active items that represent ends of rules.
1475     (setq count 0
1476           i 0)
1477     (while (< i nitemset)
1478       (setq item (aref ritem (aref itemset i)))
1479       (when (< item 0)
1480         (aset redset count (- item))
1481         (setq count (1+ count)))
1482       (setq i (1+ i)))
1483     ;; Make a reductions structure and copy the data into it.
1484     (when (> count 0)
1485       (setq p (make-reductions)
1486             rules (make-vector count 0))
1487       (set-reductions-number p (core-number this-state))
1488       (set-reductions-nreds  p count)
1489       (set-reductions-rules  p rules)
1490       (setq i 0)
1491       (while (< i count)
1492         ;; (p->rules)[i] = redset[i]
1493         (aset rules i (aref redset i))
1494         (setq i (1+ i)))
1495       (if last-reduction
1496           (set-reductions-next last-reduction p)
1497         (setq first-reduction p))
1498       (setq last-reduction p))))
1499
1500 (defun wisent-generate-states ()
1501   "Compute the nondeterministic finite state machine from the grammar."
1502   (working-dynamic-status "(compute nondeterministic finite state machine)")
1503   (wisent-allocate-storage)
1504   (wisent-initialize-closure nitems)
1505   (wisent-initialize-states)
1506   (while this-state
1507     ;; Set up RULESET and ITEMSET for the transitions out of this
1508     ;; state.  RULESET gets a 1 bit for each rule that could reduce
1509     ;; now.  ITEMSET gets a vector of all the items that could be
1510     ;; accepted next.
1511     (wisent-closure (core-items this-state) (core-nitems this-state))
1512     ;; Record the reductions allowed out of this state.
1513     (wisent-save-reductions)
1514     ;; Find the itemsets of the states that shifts can reach.
1515     (wisent-new-itemsets)
1516     ;; Find or create the core structures for those states.
1517     (wisent-append-states)
1518     ;; Create the shifts structures for the shifts to those states,
1519     ;; now that the state numbers transitioning to are known.
1520     (if (> nshifts 0)
1521         (wisent-save-shifts))
1522     ;; States are queued when they are created; process them all.
1523     (setq this-state (core-next this-state)))
1524   ;; Set up initial and final states as parser wants them.
1525   (wisent-augment-automaton))
1526 \f
1527 ;;;; ---------------------------
1528 ;;;; Compute look-ahead criteria
1529 ;;;; ---------------------------
1530
1531 ;; Compute how to make the finite state machine deterministic; find
1532 ;; which rules need lookahead in each state, and which lookahead
1533 ;; tokens they accept.
1534
1535 ;; `wisent-lalr', the entry point, builds these data structures:
1536
1537 ;; GOTO-MAP, FROM-STATE and TO-STATE record each shift transition
1538 ;; which accepts a variable (a nonterminal).  NGOTOS is the number of
1539 ;; such transitions.
1540 ;; FROM-STATE[t] is the state number which a transition leads from and
1541 ;; TO-STATE[t] is the state number it leads to.
1542 ;; All the transitions that accept a particular variable are grouped
1543 ;; together and GOTO-MAP[i - NTOKENS] is the index in FROM-STATE and
1544 ;; TO-STATE of the first of them.
1545
1546 ;; CONSISTENT[s] is non-nil if no lookahead is needed to decide what
1547 ;; to do in state s.
1548
1549 ;; LARULENO is a vector which records the rules that need lookahead in
1550 ;; various states.  The elements of LARULENO that apply to state s are
1551 ;; those from LOOKAHEADS[s] through LOOKAHEADS[s+1]-1.  Each element
1552 ;; of LARULENO is a rule number.
1553
1554 ;; If LR is the length of LARULENO, then a number from 0 to LR-1 can
1555 ;; specify both a rule and a state where the rule might be applied.
1556 ;; LA is a LR by NTOKENS matrix of bits.
1557 ;; LA[l, i] is 1 if the rule LARULENO[l] is applicable in the
1558 ;; appropriate state when the next token is symbol i.
1559 ;; If LA[l, i] and LA[l, j] are both 1 for i != j, it is a conflict.
1560
1561 (wisent-defcontext digraph
1562   INDEX R VERTICES
1563   infinity top)
1564
1565 (defun wisent-traverse (i)
1566   "Traverse I."
1567   (let (j k height Ri Fi break)
1568     (setq top (1+ top)
1569           height top)
1570     (aset VERTICES top i) ;; VERTICES[++top] = i
1571     (aset INDEX i top) ;; INDEX[i] = height = top
1572     
1573     (setq Ri (aref R i))
1574     (when Ri
1575       (setq j 0)
1576       (while (>= (aref Ri j) 0)
1577         (if (zerop (aref INDEX (aref Ri j)))
1578             (wisent-traverse (aref Ri j)))
1579         ;; if (INDEX[i] > INDEX[R[i][j]])
1580         (if (> (aref INDEX i) (aref INDEX (aref Ri j)))
1581             ;; INDEX[i] = INDEX[R[i][j]];
1582             (aset INDEX i (aref INDEX (aref Ri j))))
1583         (setq Fi (aref F i)
1584               k 0)
1585         (while (< k tokensetsize)
1586           ;; F (i)[k] |= F (R[i][j])[k];
1587           (aset Fi k (logior (aref Fi k)
1588                              (aref (aref F (aref Ri j)) k)))
1589            (setq k (1+ k)))
1590         (setq j (1+ j))))
1591     
1592     (when (= (aref INDEX i) height)
1593       (setq break nil)
1594       (while (not break)
1595         (setq j (aref VERTICES top) ;; j = VERTICES[top--]
1596               top (1- top))
1597         (aset INDEX j infinity)
1598         (if (= i j)
1599             (setq break t)
1600           (setq k 0)
1601           (while (< k tokensetsize)
1602             ;; F (j)[k] = F (i)[k];
1603             (aset (aref F j) k (aref (aref F i) k))
1604             (setq k (1+ k))))))
1605     ))
1606
1607 (defun wisent-digraph (relation)
1608   "Digraph RELATION."
1609   (wisent-with-context digraph
1610     (setq infinity (+ ngotos 2)
1611           INDEX    (make-vector (1+ ngotos) 0)
1612           VERTICES (make-vector (1+ ngotos) 0)
1613           top      0
1614           R        relation)
1615     (let ((i 0))
1616       (while (< i ngotos)
1617         (if (and (= (aref INDEX i) 0) (aref R i))
1618             (wisent-traverse i))
1619         (setq i (1+ i))))))
1620
1621 (defun wisent-set-state-table ()
1622   "Build state table."
1623   (let (sp)
1624     (setq state-table (make-vector nstates nil)
1625           sp first-state)
1626     (while sp
1627       (aset state-table (core-number sp) sp)
1628       (setq sp (core-next sp)))))
1629
1630 (defun wisent-set-accessing-symbol ()
1631   "Build accessing symbol table."
1632   (let (sp)
1633     (setq accessing-symbol (make-vector nstates 0)
1634           sp first-state)
1635     (while sp
1636       (aset accessing-symbol (core-number sp) (core-accessing-symbol sp))
1637       (setq sp (core-next sp)))))
1638
1639 (defun wisent-set-shift-table ()
1640   "Build shift table."
1641   (let (sp)
1642     (setq shift-table (make-vector nstates nil)
1643           sp first-shift)
1644     (while sp
1645       (aset shift-table (shifts-number sp) sp)
1646       (setq sp (shifts-next sp)))))
1647
1648 (defun wisent-set-reduction-table ()
1649   "Build reduction table."
1650   (let (rp)
1651     (setq reduction-table (make-vector nstates nil)
1652           rp first-reduction)
1653     (while rp
1654       (aset reduction-table (reductions-number rp) rp)
1655       (setq rp (reductions-next rp)))))
1656
1657 (defun wisent-set-maxrhs ()
1658   "Setup MAXRHS length."
1659   (let (i len max)
1660     (setq len 0
1661           max 0
1662           i   0)
1663     (while (aref ritem i)
1664       (if (> (aref ritem i) 0)
1665           (setq len (1+ len))
1666         (if (> len max)
1667             (setq max len))
1668         (setq len 0))
1669       (setq i (1+ i)))
1670     (setq maxrhs max)))
1671
1672 (defun wisent-initialize-LA ()
1673   "Set up LA."
1674   (let (i j k count rp sp np v)
1675     (setq consistent (make-vector nstates nil)
1676           lookaheads (make-vector (1+ nstates) 0)
1677           count 0
1678           i 0)
1679     (while (< i nstates)
1680       (aset lookaheads i count)
1681       (setq rp (aref reduction-table i)
1682             sp (aref shift-table i))
1683       ;; if (rp &&
1684       ;;     (rp->nreds > 1
1685       ;;      || (sp && ! ISVAR(accessing-symbol[sp->shifts[0]]))))
1686       (if (and rp
1687                (or (> (reductions-nreds rp) 1)
1688                    (and sp
1689                         (not (wisent-ISVAR
1690                               (aref accessing-symbol
1691                                     (aref (shifts-shifts sp) 0)))))))
1692           (setq count (+ count (reductions-nreds rp)))
1693         (aset consistent i t))
1694       
1695       (when sp
1696         (setq k 0
1697               j (shifts-nshifts sp)
1698               v (shifts-shifts sp))
1699         (while (< k j)
1700           (when (= (aref accessing-symbol (aref v k))
1701                    error-token-number)
1702             (aset consistent i nil)
1703             (setq k j)) ;; break
1704           (setq k (1+ k))))
1705       (setq i (1+ i)))
1706     
1707     (aset lookaheads nstates count)
1708     
1709     (if (zerop count)
1710         (progn
1711           (setq LA (make-vector 1 nil)
1712                 LAruleno (make-vector 1 0)
1713                 lookback (make-vector 1 nil)))
1714       (setq LA (make-vector count nil)
1715             LAruleno (make-vector count 0)
1716             lookback (make-vector count nil)))
1717     (setq i 0 j (length LA))
1718     (while (< i j)
1719       (aset LA i (make-vector tokensetsize 0))
1720       (setq i (1+ i)))
1721     
1722     (setq np 0
1723           i  0)
1724     (while (< i nstates)
1725       (when (not (aref consistent i))
1726         (setq rp (aref reduction-table i))
1727         (when rp
1728           (setq j 0
1729                 k (reductions-nreds rp)
1730                 v (reductions-rules rp))
1731           (while (< j k)
1732             (aset LAruleno np (aref v j))
1733             (setq np (1+ np)
1734                   j  (1+ j)))))
1735       (setq i (1+ i)))))
1736
1737 (defun wisent-set-goto-map ()
1738   "Set up GOTO-MAP."
1739   (let (sp i j symbol k temp-map state1 state2 v)
1740     (setq goto-map (make-vector (1+ nvars) 0)
1741           temp-map (make-vector (1+ nvars) 0))
1742     
1743     (setq ngotos 0
1744           sp first-shift)
1745     (while sp
1746       (setq i (1- (shifts-nshifts sp))
1747             v (shifts-shifts sp))
1748       (while (>= i 0)
1749         (setq symbol (aref accessing-symbol (aref v i)))
1750         (if (wisent-ISTOKEN symbol)
1751             (setq i 0) ;; break
1752           (setq ngotos (1+ ngotos))
1753           ;; goto-map[symbol]++;
1754           (aset goto-map (- symbol ntokens)
1755                 (1+ (aref goto-map (- symbol ntokens)))))
1756         (setq i (1- i)))
1757       (setq sp (shifts-next sp)))
1758     
1759     (setq k 0
1760           i ntokens
1761           j 0)
1762     (while (< i nsyms)
1763       (aset temp-map j k)
1764       (setq k (+ k (aref goto-map j))
1765             i (1+ i)
1766             j (1+ j)))
1767     (setq i ntokens
1768           j 0)
1769     (while (< i nsyms)
1770       (aset goto-map j (aref temp-map j))
1771       (setq i (1+ i)
1772             j (1+ j)))
1773     ;; goto-map[nsyms] = ngotos;
1774     ;; temp-map[nsyms] = ngotos;
1775     (aset goto-map j ngotos)
1776     (aset temp-map j ngotos)
1777     
1778     (setq from-state (make-vector ngotos 0)
1779           to-state   (make-vector ngotos 0)
1780           sp first-shift)
1781     (while sp
1782       (setq state1 (shifts-number sp)
1783             v      (shifts-shifts sp)
1784             i      (1- (shifts-nshifts sp)))
1785       (while (>= i 0)
1786         (setq state2 (aref v i)
1787               symbol (aref accessing-symbol state2))
1788         (if (wisent-ISTOKEN symbol)
1789             (setq i 0) ;; break
1790           ;; k = temp-map[symbol]++;
1791           (setq k (aref temp-map (- symbol ntokens)))
1792           (aset temp-map (- symbol ntokens) (1+ k))
1793           (aset from-state k state1)
1794           (aset to-state k state2))
1795         (setq i (1- i)))
1796       (setq sp (shifts-next sp)))
1797   ))
1798
1799 (defun wisent-map-goto (state symbol)
1800   "Map a STATE/SYMBOL pair into its numeric representation."
1801   (let (high low middle s result)
1802     ;; low = goto-map[symbol];
1803     ;; high = goto-map[symbol + 1] - 1;
1804     (setq low (aref goto-map (- symbol ntokens))
1805           high (1- (aref goto-map (- (1+ symbol) ntokens))))
1806     (while (and (not result) (<= low high))
1807       (setq middle (/ (+ low high) 2)
1808             s (aref from-state middle))
1809       (cond
1810        ((= s state)
1811         (setq result middle))
1812        ((< s state)
1813         (setq low (1+ middle)))
1814        (t
1815         (setq high (1- middle)))))
1816     (or result
1817         (error "Internal error in `wisent-map-goto'"))
1818     ))
1819
1820 (defun wisent-initialize-F ()
1821   "Set up F."
1822   (let (i j k sp edge rowp rp reads nedges stateno symbol v break)
1823     (setq F (make-vector ngotos nil)
1824           i 0)
1825     (while (< i ngotos)
1826       (aset F i (make-vector tokensetsize 0))
1827       (setq i (1+ i)))
1828     
1829     (setq reads (make-vector ngotos nil)
1830           edge  (make-vector (1+ ngotos) 0)
1831           nedges 0
1832           rowp 0 ;; rowp = F
1833           i 0)
1834     (while (< i ngotos)
1835       (setq stateno (aref to-state i)
1836             sp (aref shift-table stateno))
1837       (when sp
1838         (setq k (shifts-nshifts sp)
1839               v (shifts-shifts sp)
1840               j 0
1841               break nil)
1842         (while (and (not break) (< j k))
1843           ;; symbol = accessing-symbol[sp->shifts[j]];
1844           (setq symbol (aref accessing-symbol (aref v j)))
1845           (if (wisent-ISVAR symbol)
1846               (setq break t) ;; break
1847             (wisent-SETBIT (aref F rowp) symbol)
1848             (setq j (1+ j))))
1849         
1850         (while (< j k)
1851           ;; symbol = accessing-symbol[sp->shifts[j]];
1852           (setq symbol (aref accessing-symbol (aref v j)))
1853           (when (aref nullable (- symbol ntokens))
1854             (aset edge nedges (wisent-map-goto stateno symbol))
1855             (setq nedges (1+ nedges)))
1856           (setq j (1+ j)))
1857         
1858         (when (> nedges 0)
1859           ;; reads[i] = rp = NEW2(nedges + 1, short);
1860           (setq rp (make-vector (1+ nedges) 0)
1861                 j 0)
1862           (aset reads i rp)
1863           (while (< j nedges)
1864             ;; rp[j] = edge[j];
1865             (aset rp j (aref edge j))
1866             (setq j (1+ j)))
1867           (aset rp nedges -1)
1868           (setq nedges 0)))
1869       (setq rowp (1+ rowp))
1870       (setq i (1+ i)))
1871     (wisent-digraph reads)
1872     ))
1873
1874 (defun wisent-add-lookback-edge (stateno ruleno gotono)
1875   "Add a lookback edge.
1876 STATENO, RULENO, GOTONO are self-explanatory."
1877   (let (i k found)
1878     (setq i (aref lookaheads stateno)
1879           k (aref lookaheads (1+ stateno))
1880           found nil)
1881     (while (and (not found) (< i k))
1882       (if (= (aref LAruleno i) ruleno)
1883           (setq found t)
1884         (setq i (1+ i))))
1885     
1886     (or found
1887         (error "Internal error in `wisent-add-lookback-edge'"))
1888     
1889     ;;                value  . next
1890     ;; lookback[i] = (gotono . lookback[i])
1891     (aset lookback i (cons gotono (aref lookback i)))))
1892
1893 (defun wisent-transpose (R-arg n)
1894   "Return the transpose of R-ARG, of size N.
1895 Destroy R-ARG, as it is replaced with the result.  R-ARG[I] is nil or
1896 a -1 terminated list of numbers.  RESULT[NUM] is nil or the -1
1897 terminated list of the I such as NUM is in R-ARG[I]."
1898   (let (i j new-R end-R nedges v sp)
1899     (setq new-R  (make-vector n nil)
1900           end-R  (make-vector n nil)
1901           nedges (make-vector n 0))
1902     
1903     ;; Count.
1904     (setq i 0)
1905     (while (< i n)
1906       (setq v (aref R-arg i))
1907       (when v
1908         (setq j 0)
1909         (while (>= (aref v j) 0)
1910           (aset nedges (aref v j) (1+ (aref nedges (aref v j))))
1911           (setq j (1+ j))))
1912       (setq i (1+ i)))
1913     
1914     ;; Allocate.
1915     (setq i 0)
1916     (while (< i n)
1917       (when (> (aref nedges i) 0)
1918         (setq sp (make-vector (1+ (aref nedges i)) 0))
1919         (aset sp (aref nedges i) -1)
1920         (aset new-R i sp)
1921         (aset end-R i 0))
1922       (setq i (1+ i)))
1923     
1924     ;; Store.
1925     (setq i 0)
1926     (while (< i n)
1927       (setq v (aref R-arg i))
1928       (when v
1929         (setq j 0)
1930         (while (>= (aref v j) 0)
1931           (aset (aref new-R (aref v j)) (aref end-R (aref v j)) i)
1932           (aset end-R (aref v j) (1+ (aref end-R (aref v j))))
1933           (setq j (1+ j))))
1934       (setq i (1+ i)))
1935     
1936     new-R))
1937
1938 (defun wisent-build-relations ()
1939   "Build relations."
1940   (let (i j k rulep rp sp length nedges done state1 stateno
1941           symbol1 symbol2 edge states new-includes v)
1942     (setq includes (make-vector ngotos nil)
1943           edge (make-vector (1+ ngotos) 0)
1944           states (make-vector (1+ maxrhs) 0)
1945           i 0)
1946     
1947     (while (< i ngotos)
1948       (setq nedges 0
1949             state1 (aref from-state i)
1950             symbol1 (aref accessing-symbol (aref to-state i))
1951             rulep (aref derives (- symbol1 ntokens)))
1952       
1953       (while (> (car rulep) 0)
1954         (aset states 0 state1)
1955         (setq length 1
1956               stateno state1
1957               rp (aref rrhs (car rulep))) ;; rp = ritem + rrhs[*rulep]
1958         (while (> (aref ritem rp) 0) ;; *rp > 0
1959           (setq symbol2 (aref ritem rp)
1960                 sp (aref shift-table stateno)
1961                 k  (shifts-nshifts sp)
1962                 v  (shifts-shifts sp)
1963                 j  0)
1964           (while (< j k)
1965             (setq stateno (aref v j))
1966             (if (= (aref accessing-symbol stateno) symbol2)
1967                 (setq j k) ;; break
1968               (setq j (1+ j))))
1969           ;; states[length++] = stateno;
1970           (aset states length stateno)
1971           (setq length (1+ length))
1972           (setq rp (1+ rp)))
1973         
1974         (if (not (aref consistent stateno))
1975             (wisent-add-lookback-edge stateno (car rulep) i))
1976         
1977         (setq length (1- length)
1978               done nil)
1979         (while (not done)
1980           (setq done t
1981                 rp (1- rp))
1982           (when (and (>= rp 0) (wisent-ISVAR (aref ritem rp)))
1983             ;; stateno = states[--length];
1984             (setq length (1- length)
1985                   stateno (aref states length))
1986             (aset edge nedges (wisent-map-goto stateno (aref ritem rp)))
1987             (setq nedges (1+ nedges))
1988             (if (aref nullable (- (aref ritem rp) ntokens))
1989                 (setq done nil))))
1990         (setq rulep (cdr rulep)))
1991       
1992       (when (> nedges 0)
1993         (setq v (make-vector (1+ nedges) 0)
1994               j 0)
1995         (aset includes i v)
1996         (while (< j nedges)
1997           (aset v j (aref edge j))
1998           (setq j (1+ j)))
1999         (aset v nedges -1))
2000       (setq i (1+ i)))
2001     
2002     (setq includes (wisent-transpose includes ngotos))
2003     ))
2004
2005 (defun wisent-compute-FOLLOWS ()
2006   "Compute follows."
2007   (wisent-digraph includes))
2008
2009 (defun wisent-compute-lookaheads ()
2010   "Compute lookaheads."
2011   (let (i j n v1 v2 sp)
2012     (setq n (aref lookaheads nstates)
2013           i 0)
2014     (while (< i n)
2015       (setq sp (aref lookback i))
2016       (while sp
2017         (setq v1 (aref LA i)
2018               v2 (aref F (car sp))
2019               j  0)
2020         (while (< j tokensetsize)
2021           ;; LA (i)[j] |= F (sp->value)[j]
2022           (aset v1 j (logior (aref v1 j) (aref v2 j)))
2023           (setq j (1+ j)))
2024         (setq sp (cdr sp)))
2025       (setq i (1+ i)))))
2026
2027 (defun wisent-lalr ()
2028   "Make the nondeterministic finite state machine deterministic."
2029   (working-dynamic-status "(make finite state machine deterministic)")
2030   (setq tokensetsize (wisent-WORDSIZE ntokens))
2031   (wisent-set-state-table)
2032   (wisent-set-accessing-symbol)
2033   (wisent-set-shift-table)
2034   (wisent-set-reduction-table)
2035   (wisent-set-maxrhs)
2036   (wisent-initialize-LA)
2037   (wisent-set-goto-map)
2038   (wisent-initialize-F)
2039   (wisent-build-relations)
2040   (wisent-compute-FOLLOWS)
2041   (wisent-compute-lookaheads))
2042 \f
2043 ;;;; -----------------------------------------------
2044 ;;;; Find and resolve or report look-ahead conflicts
2045 ;;;; -----------------------------------------------
2046
2047 (defsubst wisent-log-resolution (state LAno token resolution)
2048   "Log a shift-reduce conflict resolution.
2049 In specified STATE between rule pointed by lookahead number LANO and
2050 TOKEN, resolved as RESOLUTION."
2051   (if (or wisent-verbose-flag wisent-debug-flag)
2052       (wisent-log
2053        "Conflict in state %d between rule %d and token %s resolved as %s.\n"
2054        state (aref LAruleno LAno) (wisent-tag token) resolution)))
2055
2056 (defun wisent-flush-shift (state token)
2057   "Turn off the shift recorded in the specified STATE for TOKEN.
2058 Used when we resolve a shift-reduce conflict in favor of the reduction."
2059   (let (shiftp i k v)
2060     (when (setq shiftp (aref shift-table state))
2061       (setq k (shifts-nshifts shiftp)
2062             v (shifts-shifts shiftp)
2063             i 0)
2064       (while (< i k)
2065         (if (and (not (zerop (aref v i)))
2066                  (= token (aref accessing-symbol (aref v i))))
2067             (aset v i 0))
2068         (setq i (1+ i))))))
2069
2070 (defun wisent-resolve-sr-conflict (state lookaheadnum)
2071   "Attempt to resolve shift-reduce conflict for one rule.
2072 Resolve by means of precedence declarations.  The conflict occurred in
2073 specified STATE for the rule pointed by the lookahead symbol
2074 LOOKAHEADNUM.  It has already been checked that the rule has a
2075 precedence.  A conflict is resolved by modifying the shift or reduce
2076 tables so that there is no longer a conflict."
2077   (let (i redprec errp errs nerrs token sprec sassoc)
2078     ;; Find the rule to reduce by to get precedence of reduction
2079     (setq token (aref tags (aref rprec (aref LAruleno lookaheadnum)))
2080           redprec (wisent-prec token)
2081           errp  (make-errs)
2082           errs  (make-vector ntokens 0)
2083           nerrs 0
2084           i 0)
2085     (set-errs-errs errp errs)
2086     (while (< i ntokens)
2087       (setq token (aref tags i))
2088       (when (and (wisent-BITISSET (aref LA lookaheadnum) i)
2089                  (wisent-BITISSET lookaheadset i)
2090                  (setq sprec (wisent-prec token)))
2091         ;; Shift-reduce conflict occurs for token number I and it has
2092         ;; a precedence.  The precedence of shifting is that of token
2093         ;; I.
2094         (cond
2095          ((< sprec redprec)
2096           (wisent-log-resolution state lookaheadnum i "reduce")
2097           ;;  Flush the shift for this token
2098           (wisent-RESETBIT lookaheadset i)
2099           (wisent-flush-shift state i)
2100           )
2101          ((> sprec redprec)
2102           (wisent-log-resolution state lookaheadnum i "shift")
2103           ;; Flush the reduce for this token
2104           (wisent-RESETBIT (aref LA lookaheadnum) i)
2105           )
2106          (t
2107           ;; Matching precedence levels.
2108           ;; For left association, keep only the reduction.
2109           ;; For right association, keep only the shift.
2110           ;; For nonassociation, keep neither.
2111           (setq sassoc (wisent-assoc token))
2112           (cond
2113            ((eq sassoc 'right)
2114             (wisent-log-resolution state lookaheadnum i "shift"))
2115            ((eq sassoc 'left)
2116             (wisent-log-resolution state lookaheadnum i "reduce"))
2117            ((eq sassoc 'nonassoc)
2118             (wisent-log-resolution state lookaheadnum i "an error"))
2119            )
2120           (when (not (eq sassoc 'right))
2121             ;; Flush the shift for this token
2122             (wisent-RESETBIT lookaheadset i)
2123             (wisent-flush-shift state i))
2124           (when (not (eq sassoc 'left))
2125             ;; Flush the reduce for this token
2126             (wisent-RESETBIT (aref LA lookaheadnum) i))
2127           (when (eq sassoc 'nonassoc)
2128             ;; Record an explicit error for this token
2129             (aset errs nerrs i)
2130             (setq nerrs (1+ nerrs)))
2131           )))
2132       (setq i (1+ i)))
2133     (when (> nerrs 0)
2134       (set-errs-nerrs errp nerrs)
2135       (aset err-table state errp))
2136     ))
2137
2138 (defun wisent-set-conflicts (state)
2139   "Find and attempt to resolve conflicts in specified STATE."
2140   (let (i j k v c shiftp symbol)
2141     (unless (aref consistent state)
2142       (fillarray lookaheadset 0)
2143       
2144       (when (setq shiftp (aref shift-table state))
2145         (setq k (shifts-nshifts shiftp)
2146               v (shifts-shifts shiftp)
2147               i 0)
2148         (while (and (< i k)
2149                     (wisent-ISTOKEN
2150                      (setq symbol (aref accessing-symbol (aref v i)))))
2151           (or (zerop (aref v i))
2152               (wisent-SETBIT lookaheadset symbol))
2153           (setq i (1+ i))))
2154       
2155       ;; Loop over all rules which require lookahead in this state
2156       ;; first check for shift-reduce conflict, and try to resolve
2157       ;; using precedence
2158       (setq i (aref lookaheads state)
2159             k (aref lookaheads (1+ state)))
2160       (while (< i k)
2161         (when (aref rprec (aref LAruleno i))
2162           (setq v (aref LA i)
2163                 j 0)
2164           (while (< j tokensetsize)
2165             (if (zerop (logand (aref v j) (aref lookaheadset j)))
2166                 (setq j (1+ j))
2167               ;; if (LA (i)[j] & lookaheadset[j])
2168               (wisent-resolve-sr-conflict state i)
2169               (setq j tokensetsize)))) ;; break
2170         (setq i (1+ i)))
2171       
2172       ;; Loop over all rules which require lookahead in this state
2173       ;; Check for conflicts not resolved above.
2174       (setq i (aref lookaheads state))
2175       (while (< i k)
2176         (setq v (aref LA i)
2177               j 0)
2178         (while (< j tokensetsize)
2179           ;; if (LA (i)[j] & lookaheadset[j])
2180           (if (not (zerop (logand (aref v j) (aref lookaheadset j))))
2181               (aset conflicts state t))
2182           (setq j (1+ j)))
2183         (setq j 0)
2184         (while (< j tokensetsize)
2185           ;; lookaheadset[j] |= LA (i)[j];
2186           (aset lookaheadset j (logior (aref lookaheadset j)
2187                                        (aref v j)))
2188           (setq j (1+ j)))
2189         (setq i (1+ i)))
2190       )))
2191
2192 (defun wisent-resolve-conflicts ()
2193   "Find and resolve conflicts."
2194   (working-dynamic-status "(resolve conflicts)")
2195   (let (i)
2196     (setq conflicts    (make-vector nstates nil)
2197           shiftset     (make-vector tokensetsize 0)
2198           lookaheadset (make-vector tokensetsize 0)
2199           err-table    (make-vector nstates nil)
2200           i 0)
2201     (while (< i nstates)
2202       (wisent-set-conflicts i)
2203       (setq i (1+ i)))))
2204
2205 (defun wisent-count-sr-conflicts (state)
2206   "Count the number of shift/reduce conflicts in specified STATE."
2207   (let (i j k mask shiftp symbol v)
2208     (setq src-count 0
2209           shiftp (aref shift-table state))
2210     (when shiftp
2211       (fillarray shiftset 0)
2212       (fillarray lookaheadset 0)
2213       (setq k (shifts-nshifts shiftp)
2214             v (shifts-shifts shiftp)
2215             i 0)
2216       (while (< i k)
2217         (when (not (zerop (aref v i)))
2218           (setq symbol (aref accessing-symbol (aref v i)))
2219           (if (wisent-ISVAR symbol)
2220               (setq i k) ;; break
2221             (wisent-SETBIT shiftset symbol)))
2222         (setq i (1+ i)))
2223       
2224       (setq k (aref lookaheads (1+ state))
2225             i (aref lookaheads state))
2226       (while (< i k)
2227         (setq v (aref LA i)
2228               j 0)
2229         (while (< j tokensetsize)
2230           ;; lookaheadset[j] |= LA (i)[j]
2231           (aset lookaheadset j (logior (aref lookaheadset j)
2232                                        (aref v j)))
2233           (setq j (1+ j)))
2234         (setq i (1+ i)))
2235       
2236       (setq k 0)
2237       (while (< k tokensetsize)
2238         ;; lookaheadset[k] &= shiftset[k];
2239         (aset lookaheadset k (logand (aref lookaheadset k)
2240                                      (aref shiftset k)))
2241         (setq k (1+ k)))
2242       
2243       (setq i 0)
2244       (while (< i ntokens)
2245         (if (wisent-BITISSET lookaheadset i)
2246             (setq src-count (1+ src-count)))
2247         (setq i (1+ i))))
2248     src-count))
2249
2250 (defun wisent-count-rr-conflicts (state)
2251   "Count the number of reduce/reduce conflicts in specified STATE."
2252   (let (i j count n m)
2253     (setq rrc-count 0
2254           m (aref lookaheads state)
2255           n (aref lookaheads (1+ state)))
2256     (when (>= (- n m) 2)
2257       (setq i 0)
2258       (while (< i ntokens)
2259         (setq count 0
2260               j m)
2261         (while (< j n)
2262           (if (wisent-BITISSET (aref LA j) i)
2263               (setq count (1+ count)))
2264           (setq j (1+ j)))
2265         
2266         (if (>= count 2)
2267             (setq rrc-count (1+ rrc-count)))
2268         (setq i (1+ i))))
2269     rrc-count))
2270
2271 (defvar wisent-expected-conflicts nil
2272   "*If non-nil suppress the warning about shift/reduce conflicts.
2273 It is a decimal integer N that says there should be no warning if
2274 there are N shift/reduce conflicts and no reduce/reduce conflicts.  A
2275 warning is given if there are either more or fewer conflicts, or if
2276 there are any reduce/reduce conflicts.")
2277
2278 (defun wisent-total-conflicts ()
2279   "Report the total number of conflicts."
2280   (unless (and (zerop rrc-total)
2281                (or (zerop src-total)
2282                    (= src-total (or wisent-expected-conflicts 0))))
2283     (let* ((src (wisent-source))
2284            (src (if src (concat " in " src) ""))
2285            (msg (format "Grammar%s contains" src)))
2286       (if (> src-total 0)
2287           (setq msg (format "%s %d shift/reduce conflict%s"
2288                             msg src-total (if (> src-total 1)
2289                                               "s" ""))))
2290       (if (and (> src-total 0) (> rrc-total 0))
2291           (setq msg (format "%s and" msg)))
2292       (if (> rrc-total 0)
2293         (setq msg (format "%s %d reduce/reduce conflict%s"
2294                           msg rrc-total (if (> rrc-total 1)
2295                                             "s" ""))))
2296       (message msg))))
2297
2298 (defun wisent-print-conflicts ()
2299   "Report conflicts."
2300   (let (i)
2301     (setq  src-total 0
2302            rrc-total 0
2303            i 0)
2304     (while (< i nstates)
2305       (when (aref conflicts i)
2306         (wisent-count-sr-conflicts i)
2307         (wisent-count-rr-conflicts i)
2308         (setq src-total (+ src-total src-count)
2309               rrc-total (+ rrc-total rrc-count))
2310         (when (or wisent-verbose-flag wisent-debug-flag)
2311           (wisent-log "State %d contains" i)
2312           (if (> src-count 0)
2313               (wisent-log " %d shift/reduce conflict%s"
2314                           src-count (if (> src-count 1) "s" "")))
2315           
2316           (if (and (> src-count 0) (> rrc-count 0))
2317               (wisent-log " and"))
2318           
2319           (if (> rrc-count 0)
2320               (wisent-log " %d reduce/reduce conflict%s"
2321                           rrc-count (if (> rrc-count 1) "s" "")))
2322           
2323           (wisent-log ".\n")))
2324       (setq i (1+ i)))
2325     (wisent-total-conflicts)))
2326 \f
2327 ;;;; --------------------------------------
2328 ;;;; Report information on generated parser
2329 ;;;; --------------------------------------
2330 (defun wisent-print-grammar ()
2331   "Print grammar."
2332   (let (i j r break left-count right-count)
2333     
2334     (wisent-log "\n\nGrammar\n\n  Number, Rule\n")
2335     (setq i 1)
2336     (while (<= i nrules)
2337       ;; Don't print rules disabled in `wisent-reduce-grammar-tables'.
2338       (when (aref ruseful i)
2339         (wisent-log "  %s  %s ->"
2340                     (wisent-pad-string (number-to-string i) 6)
2341                     (wisent-tag (aref rlhs i)))
2342         (setq r (aref rrhs i))
2343         (if (> (aref ritem r) 0)
2344             (while (> (aref ritem r) 0)
2345               (wisent-log " %s" (wisent-tag (aref ritem r)))
2346               (setq r (1+ r)))
2347           (wisent-log " /* empty */"))
2348         (wisent-log "\n"))
2349       (setq i (1+ i)))
2350     
2351     (wisent-log "\n\nTerminals, with rules where they appear\n\n")
2352     (wisent-log "%s (-1)\n" (wisent-tag 0))
2353     (setq i 1)
2354     (while (< i ntokens)
2355       (wisent-log "%s (%d)" (wisent-tag i) i)
2356       (setq j 1)
2357       (while (<= j nrules)
2358         (setq r (aref rrhs j)
2359               break nil)
2360         (while (and (not break) (> (aref ritem r) 0))
2361           (if (setq break (= (aref ritem r) i))
2362               (wisent-log " %d" j)
2363             (setq r (1+ r))))
2364         (setq j (1+ j)))
2365       (wisent-log "\n")
2366       (setq i (1+ i)))
2367     
2368     (wisent-log "\n\nNonterminals, with rules where they appear\n\n")
2369     (setq i ntokens)
2370     (while (< i nsyms)
2371       (setq left-count 0
2372             right-count 0
2373             j 1)
2374       (while (<= j nrules)
2375         (if (= (aref rlhs j) i)
2376             (setq left-count (1+ left-count)))
2377         (setq r (aref rrhs j)
2378               break nil)
2379         (while (and (not break) (> (aref ritem r) 0))
2380           (if (= (aref ritem r) i)
2381               (setq right-count (1+ right-count)
2382                     break t)
2383             (setq r (1+ r))))
2384         (setq j (1+ j)))
2385       (wisent-log "%s (%d)\n   " (wisent-tag i) i)
2386       (when (> left-count 0)
2387         (wisent-log " on left:")
2388         (setq j 1)
2389         (while (<= j nrules)
2390           (if (= (aref rlhs j) i)
2391               (wisent-log " %d" j))
2392           (setq j (1+ j))))
2393       (when (> right-count 0)
2394         (if (> left-count 0)
2395             (wisent-log ","))
2396         (wisent-log " on right:")
2397         (setq j 1)
2398         (while (<= j nrules)
2399           (setq r (aref rrhs j)
2400                 break nil)
2401           (while (and (not break) (> (aref ritem r) 0))
2402             (if (setq break (= (aref ritem r) i))
2403                 (wisent-log " %d" j)
2404               (setq r (1+ r))))
2405           (setq j (1+ j))))
2406       (wisent-log "\n")
2407       (setq i (1+ i)))
2408     ))
2409
2410 (defun wisent-print-reductions (state)
2411   "Print reductions on STATE."
2412   (let (i j k v rule symbol mask m n defaulted
2413           default-LA default-rule cmax count shiftp errp nodefault)
2414     (setq nodefault nil
2415           i 0)
2416     (fillarray shiftset 0)
2417     
2418     (setq shiftp (aref shift-table state))
2419     (when shiftp
2420       (setq k (shifts-nshifts shiftp)
2421             v (shifts-shifts  shiftp)
2422             i 0)
2423       (while (< i k)
2424         (when (not (zerop (aref v i)))
2425           (setq symbol (aref accessing-symbol (aref v i)))
2426           (if (wisent-ISVAR symbol)
2427               (setq i k) ;; break
2428             ;; If this state has a shift for the error token, don't
2429             ;; use a default rule.
2430             (if (= symbol error-token-number)
2431                 (setq nodefault t))
2432             (wisent-SETBIT shiftset symbol)))
2433         (setq i (1+ i))))
2434     
2435     (setq errp (aref err-table state))
2436     (when errp
2437       (setq k (errs-nerrs errp)
2438             v (errs-errs errp)
2439             i 0)
2440       (while (< i k)
2441         (if (not (zerop (setq symbol (aref v i))))
2442             (wisent-SETBIT shiftset symbol))
2443         (setq i (1+ i))))
2444     
2445     (setq m (aref lookaheads state)
2446           n (aref lookaheads (1+ state)))
2447     
2448     (cond
2449      ((and (= (- n m) 1) (not nodefault))
2450       (setq default-rule (aref LAruleno m)
2451             v (aref LA m)
2452             k 0)
2453       (while (< k tokensetsize)
2454         (aset lookaheadset k (logand (aref v k)
2455                                      (aref shiftset k)))
2456         (setq k (1+ k)))
2457       
2458       (setq i 0)
2459       (while (< i ntokens)
2460         (if (wisent-BITISSET lookaheadset i)
2461             (wisent-log "    %s\t[reduce using rule %d (%s)]\n"
2462                         (wisent-tag i) default-rule
2463                         (wisent-tag (aref rlhs default-rule))))
2464         (setq i (1+ i)))
2465       (wisent-log "    $default\treduce using rule %d (%s)\n\n"
2466                   default-rule
2467                   (wisent-tag (aref rlhs default-rule)))
2468       )
2469      ((>= (- n m) 1)
2470       (setq cmax 0
2471             default-LA -1
2472             default-rule 0)
2473       (when (not nodefault)
2474         (setq i m)
2475         (while (< i n)
2476           (setq v (aref LA i)
2477                 count 0
2478                 k 0)
2479           (while (< k tokensetsize)
2480             ;; lookaheadset[k] = LA (i)[k] & ~shiftset[k]
2481             (aset lookaheadset k
2482                   (logand (aref v k)
2483                           (lognot (aref shiftset k))))
2484             (setq k (1+ k)))
2485           (setq j 0)
2486           (while (< j ntokens)
2487             (if (wisent-BITISSET lookaheadset j)
2488                 (setq count (1+ count)))
2489             (setq j (1+ j)))
2490           (if (> count cmax)
2491               (setq cmax count
2492                     default-LA i
2493                     default-rule (aref LAruleno i)))
2494           (setq k 0)
2495           (while (< k tokensetsize)
2496             (aset shiftset k (logior (aref shiftset k)
2497                                      (aref lookaheadset k)))
2498             (setq k (1+ k)))
2499           (setq i (1+ i))))
2500       
2501       (fillarray shiftset 0)
2502       
2503       (when shiftp
2504         (setq k (shifts-nshifts shiftp)
2505               v (shifts-shifts  shiftp)
2506               i 0)
2507         (while (< i k)
2508           (when (not (zerop (aref v i)))
2509             (setq symbol (aref accessing-symbol (aref v i)))
2510             (if (wisent-ISVAR symbol)
2511                 (setq i k) ;; break
2512               (wisent-SETBIT shiftset symbol)))
2513           (setq i (1+ i))))
2514       
2515       (setq i 0)
2516       (while (< i ntokens)
2517         (setq defaulted nil
2518               count (if (wisent-BITISSET shiftset i) 1 0)
2519               j m)
2520         (while (< j n)
2521           (when (wisent-BITISSET (aref LA j) i)
2522             (if (zerop count)
2523                 (progn
2524                   (if (not (= j default-LA))
2525                       (wisent-log
2526                        "    %s\treduce using rule %d (%s)\n"
2527                        (wisent-tag i) (aref LAruleno j)
2528                        (wisent-tag (aref rlhs (aref LAruleno j))))
2529                     (setq defaulted t))
2530                   (setq count (1+ count)))
2531               (if defaulted
2532                   (wisent-log
2533                    "    %s\treduce using rule %d (%s)\n"
2534                    (wisent-tag i) (aref LAruleno default-LA)
2535                    (wisent-tag (aref rlhs (aref LAruleno default-LA)))))
2536               (setq defaulted nil)
2537               (wisent-log
2538                "    %s\t[reduce using rule %d (%s)]\n"
2539                (wisent-tag i) (aref LAruleno j)
2540                (wisent-tag (aref rlhs (aref LAruleno j))))))
2541           (setq j (1+ j)))
2542         (setq i (1+ i)))
2543       
2544       (if (>= default-LA 0)
2545           (wisent-log
2546            "    $default\treduce using rule %d (%s)\n"
2547            default-rule
2548            (wisent-tag (aref rlhs default-rule))))
2549       ))))
2550
2551 (defun wisent-print-actions (state)
2552   "Print actions on STATE."
2553   (let (i j k v state1 symbol shiftp errp redp rule nerrs break)
2554     (setq shiftp (aref shift-table state)
2555           redp   (aref reduction-table state)
2556           errp   (aref err-table state))
2557     (if (and (not shiftp) (not redp))
2558         (if (= final-state state)
2559             (wisent-log "    $default\taccept\n")
2560           (wisent-log "    NO ACTIONS\n"))
2561      (if (not shiftp)
2562          (setq i 0
2563                k 0)
2564       (setq k (shifts-nshifts shiftp)
2565             v (shifts-shifts shiftp)
2566             i 0
2567             break nil)
2568       (while (and (not break) (< i k))
2569         (if (zerop (setq state1 (aref v i)))
2570             (setq i (1+ i))
2571           (setq symbol (aref accessing-symbol state1))
2572           ;;  The following line used to be turned off.
2573           (if (wisent-ISVAR symbol)
2574               (setq break t) ;; break
2575             (wisent-log "    %s\tshift, and go to state %d\n"
2576                         (wisent-tag symbol) state1)
2577             (setq i (1+ i)))))
2578       (if (> i 0)
2579           (wisent-log "\n")))
2580      
2581      (when errp
2582        (setq nerrs (errs-nerrs errp)
2583              v (errs-errs errp)
2584              j 0)
2585        (while (< j nerrs)
2586          (if (aref v j)
2587              (wisent-log "    %s\terror (nonassociative)\n"
2588                          (wisent-tag (aref v j))))
2589          (setq j (1+ j)))
2590        (if (> j 0)
2591            (wisent-log "\n")))
2592      
2593      (cond
2594       ((and (aref consistent state) redp)
2595        (setq rule (aref (reductions-rules redp) 0)
2596              symbol (aref rlhs rule))
2597        (wisent-log "    $default\treduce using rule %d (%s)\n\n"
2598                    rule (wisent-tag symbol))
2599        )
2600       (redp
2601        (wisent-print-reductions state)
2602        ))
2603      
2604      (when (< i k)
2605        (setq v (shifts-shifts shiftp))
2606        (while (< i k)
2607          (when (setq state1 (aref v i))
2608            (setq symbol (aref accessing-symbol state1))
2609            (wisent-log "    %s\tgo to state %d\n"
2610                        (wisent-tag symbol) state1))
2611          (setq i (1+ i)))
2612        (wisent-log "\n"))
2613      )))
2614
2615 (defun wisent-print-core (state)
2616   "Print STATE core."
2617   (let (i k rule statep sp sp1)
2618     (setq statep (aref state-table state)
2619           k (core-nitems statep))
2620     (when (> k 0)
2621       (setq i 0)
2622       (while (< i k)
2623         ;; sp1 = sp = ritem + statep->items[i];
2624         (setq sp1 (aref (core-items statep) i)
2625               sp  sp1)
2626         (while (> (aref ritem sp) 0)
2627           (setq sp (1+ sp)))
2628         
2629         (setq rule (- (aref ritem sp)))
2630         (wisent-log "    %s  ->  " (wisent-tag (aref rlhs rule)))
2631         
2632         (setq sp (aref rrhs rule))
2633         (while (< sp sp1)
2634           (wisent-log "%s " (wisent-tag (aref ritem sp)))
2635           (setq sp (1+ sp)))
2636         (wisent-log ".")
2637         (while (> (aref ritem sp) 0)
2638           (wisent-log " %s" (wisent-tag (aref ritem sp)))
2639           (setq sp (1+ sp)))
2640         (wisent-log "   (rule %d)\n" rule)
2641         (setq i (1+ i)))
2642       (wisent-log "\n"))))
2643
2644 (defun wisent-print-state (state)
2645   "Print information on STATE."
2646   (wisent-log "\n\nstate %d\n\n" state)
2647   (wisent-print-core state)
2648   (wisent-print-actions state))
2649
2650 (defun wisent-print-states ()
2651   "Print information on states."
2652   (let ((i 0))
2653     (while (< i nstates)
2654       (wisent-print-state i)
2655       (setq i (1+ i)))))
2656
2657 (defun wisent-print-results ()
2658   "Print information on generated parser.
2659 Report detailed informations if `wisent-verbose-flag' or
2660 `wisent-debug-flag' are non-nil."
2661   (when (or wisent-verbose-flag wisent-debug-flag)
2662     (wisent-print-useless))
2663   (wisent-print-conflicts)
2664   (when (or wisent-verbose-flag wisent-debug-flag)
2665     (wisent-print-grammar)
2666     (wisent-print-states))
2667   ;; Append output to log file when running in batch mode
2668   (when (wisent-noninteractive)
2669     (wisent-append-to-log-file)
2670     (wisent-clear-log)))
2671 \f
2672 ;;;; ---------------------------------
2673 ;;;; Build the generated parser tables
2674 ;;;; ---------------------------------
2675
2676 (defun wisent-action-row (state actrow)
2677   "Figure out the actions for the specified STATE.
2678 Decide what to do for each type of token if seen as the lookahead
2679 token in specified state.  The value returned is used as the default
2680 action for the state.  In addition, ACTROW is filled with what to do
2681 for each kind of token, index by symbol number, with nil meaning do
2682 the default action.  The value 'error, means this situation is an
2683 error.  The parser recognizes this value specially.
2684
2685 This is where conflicts are resolved.  The loop over lookahead rules
2686 considered lower-numbered rules last, and the last rule considered
2687 that likes a token gets to handle it."
2688   (let (i j k m n v default-rule nreds rule max count
2689           shift-state symbol redp shiftp errp nodefault)
2690     
2691     (fillarray actrow nil)
2692     
2693     (setq default-rule 0
2694           nodefault nil ;; nil inhibit having any default reduction
2695           nreds 0
2696           m 0
2697           n 0
2698           redp (aref reduction-table state))
2699     
2700     (when redp
2701       (setq nreds (reductions-nreds redp))
2702       (when (>= nreds 1)
2703         ;; loop over all the rules available here which require
2704         ;; lookahead
2705         (setq m (aref lookaheads state)
2706               n (aref lookaheads (1+ state))
2707               i (1- n))
2708         (while (>= i m)
2709           ;; and find each token which the rule finds acceptable to
2710           ;; come next
2711           (setq j 0)
2712           (while (< j ntokens)
2713             ;; and record this rule as the rule to use if that token
2714             ;; follows.
2715             (if (wisent-BITISSET (aref LA i) j)
2716                 (aset actrow j (- (aref LAruleno i)))
2717               )
2718             (setq j (1+ j)))
2719           (setq i (1- i)))))
2720     
2721     ;; Now see which tokens are allowed for shifts in this state.  For
2722     ;; them, record the shift as the thing to do.  So shift is
2723     ;; preferred to reduce.
2724     (setq shiftp (aref shift-table state))
2725     (when shiftp
2726       (setq k (shifts-nshifts shiftp)
2727             v (shifts-shifts shiftp)
2728             i 0)
2729       (while (< i k)
2730         (setq shift-state (aref v i))
2731         (if (zerop shift-state)
2732             nil ;; continue
2733           (setq symbol (aref accessing-symbol shift-state))
2734           (if (wisent-ISVAR symbol)
2735               (setq i k) ;; break
2736             (aset actrow symbol shift-state)
2737             ;; Do not use any default reduction if there is a shift
2738             ;; for error
2739             (if (= symbol error-token-number)
2740                 (setq nodefault t))))
2741         (setq i (1+ i))))
2742     
2743     ;; See which tokens are an explicit error in this state (due to
2744     ;; %nonassoc).  For them, record error as the action.
2745     (setq errp (aref err-table state))
2746     (when errp
2747       (setq k (errs-nerrs errp)
2748             v (errs-errs errp)
2749             i 0)
2750       (while (< i k)
2751         (aset actrow (aref v i) wisent-error-tag)
2752         (setq i (1+ i))))
2753     
2754     ;; Now find the most common reduction and make it the default
2755     ;; action for this state.
2756     (when (and (>= nreds 1) (not nodefault))
2757       (if (aref consistent state)
2758           (setq default-rule (- (aref (reductions-rules redp) 0)))
2759         (setq max 0
2760               i m)
2761         (while (< i n)
2762           (setq count 0
2763                 rule (- (aref LAruleno i))
2764                 j 0)
2765           (while (< j ntokens)
2766             (if (and (numberp (aref actrow j))
2767                      (= (aref actrow j) rule))
2768                 (setq count (1+ count)))
2769             (setq j (1+ j)))
2770           (if (> count max)
2771               (setq max count
2772                     default-rule rule))
2773           (setq i (1+ i)))
2774         ;; actions which match the default are replaced with zero,
2775         ;; which means "use the default"
2776         (when (> max 0)
2777           (setq j 0)
2778           (while (< j ntokens)
2779             (if (and (numberp (aref actrow j))
2780                      (= (aref actrow j) default-rule))
2781                 (aset actrow j nil))
2782             (setq j (1+ j)))
2783           )))
2784     
2785     ;; If have no default rule, if this is the final state the default
2786     ;; is accept else it is an error.  So replace any action which
2787     ;; says "error" with "use default".
2788     (when (zerop default-rule)
2789       (if (= final-state state)
2790           (setq default-rule wisent-accept-tag)
2791         (setq j 0)
2792         (while (< j ntokens)
2793           (if (eq (aref actrow j) wisent-error-tag)
2794               (aset actrow j nil))
2795           (setq j (1+ j)))
2796         (setq default-rule wisent-error-tag)))
2797     default-rule))
2798
2799 (defconst wisent-default-tag 'default
2800   "Tag used in an action table to indicate a default action.")
2801
2802 ;; These variables only exist locally in the function
2803 ;; `wisent-state-actions' and are shared by all other nested callees.
2804 (wisent-defcontext semantic-actions
2805   ;; Uninterned symbols used in code generation.
2806   stack sp gotos state
2807   ;; Name of the current semantic action
2808   NAME)
2809
2810 (defun wisent-state-actions ()
2811   "Figure out the actions for every state.
2812 Return the action table."
2813   (working-dynamic-status "(build state actions)")
2814   ;; Store the semantic action obarray in (unused) RCODE[0].
2815   (aset rcode 0 (make-vector 13 0))
2816   (let (i j action-table actrow action)
2817     (setq action-table (make-vector nstates nil)
2818           actrow (make-vector ntokens nil)
2819           i 0)
2820     (wisent-with-context semantic-actions
2821       (setq stack (make-symbol "stack")
2822             sp    (make-symbol "sp")
2823             gotos (make-symbol "gotos")
2824             state (make-symbol "state"))
2825       (while (< i nstates)
2826         (setq action (wisent-action-row i actrow))
2827         ;; Translate a reduction into semantic action
2828         (and (integerp action) (< action 0)
2829              (setq action (wisent-semantic-action (- action))))
2830         (aset action-table i (list (cons wisent-default-tag action)))
2831         (setq j 0)
2832         (while (< j ntokens)
2833           (when (setq action (aref actrow j))
2834             ;; Translate a reduction into semantic action
2835             (and (integerp action) (< action 0)
2836                  (setq action (wisent-semantic-action (- action))))
2837             (aset action-table i (cons (cons (aref tags j) action)
2838                                        (aref action-table i)))
2839             )
2840           (setq j (1+ j)))
2841         (aset action-table i (nreverse (aref action-table i)))
2842         (setq i (1+ i)))
2843       action-table)))
2844
2845 (defun wisent-goto-actions ()
2846   "Figure out what to do after reducing with each rule.
2847 Depending on the saved state from before the beginning of parsing the
2848 data that matched this rule.  Return the goto table."
2849   (working-dynamic-status "(build goto actions)")
2850   (let (i j m n symbol state goto-table)
2851     (setq goto-table (make-vector nstates nil)
2852           i ntokens)
2853     (while (< i nsyms)
2854       (setq symbol (- i ntokens)
2855             m (aref goto-map symbol)
2856             n (aref goto-map (1+ symbol))
2857             j m)
2858       (while (< j n)
2859         (setq state (aref from-state j))
2860         (aset goto-table state
2861               (cons (cons (aref tags i) (aref to-state j))
2862                     (aref goto-table state)))
2863         (setq j (1+ j)))
2864       (setq i (1+ i)))
2865     goto-table))
2866
2867 (defsubst wisent-quote-p (sym)
2868   "Return non-nil if SYM is bound to the `quote' function."
2869   (condition-case nil
2870       (eq (indirect-function sym)
2871           (indirect-function 'quote))
2872     (error nil)))
2873
2874 (defsubst wisent-backquote-p (sym)
2875   "Return non-nil if SYM is bound to the `backquote' function."
2876   (condition-case nil
2877       (eq (indirect-function sym)
2878           (indirect-function 'backquote))
2879     (error nil)))
2880
2881 (defun wisent-check-$N (x m)
2882   "Return non-nil if X is a valid $N or $regionN symbol.
2883 That is if X is a $N or $regionN symbol with N >= 1 and N <= M.
2884 Also warn if X is a $N or $regionN symbol with N < 1 or N > M."
2885   (when (symbolp x)
2886     (let* ((n (symbol-name x))
2887            (i (and (string-match "\\`\\$\\(region\\)?\\([0-9]+\\)\\'" n)
2888                    (string-to-number (match-string 2 n)))))
2889       (when i
2890         (if (and (>= i 1) (<= i m))
2891             t
2892           (message
2893            "*** In %s, %s might be a free variable (rule has %s)"
2894            NAME x (format (cond ((< m 1) "no component")
2895                                 ((= m 1) "%d component")
2896                                 ("%d components"))
2897                           m))
2898           nil)))))
2899
2900 (defun wisent-semantic-action-expand-body (body n &optional found)
2901   "Parse BODY of semantic action.
2902 N is the maximum number of $N variables that can be referenced in
2903 BODY.  Warn on references out of permitted range.
2904 Optional argument FOUND is the accumulated list of '$N' references
2905 encountered so far.
2906 Return a cons (FOUND . XBODY), where FOUND is the list of $N
2907 references found in BODY, and XBODY is BODY expression with
2908 `backquote' forms expanded."
2909   (if (not (listp body))
2910       ;; BODY is an atom, no expansion needed
2911       (progn
2912         (if (wisent-check-$N body n)
2913             ;; Accumulate $i symbol
2914             (add-to-list 'found body))
2915         (cons found body))
2916     ;; BODY is a list, expand inside it
2917     (let (xbody sexpr bltn)
2918       ;; If backquote expand it first
2919       (if (wisent-backquote-p (car body))
2920           (setq body (macroexpand body)))
2921       (while body
2922         (setq sexpr (car body)
2923               body  (cdr body))
2924         (cond
2925          ;; Function call excepted quote expression
2926          ((and (consp sexpr)
2927                (not (wisent-quote-p (car sexpr))))
2928           (setq sexpr (wisent-semantic-action-expand-body sexpr n found)
2929                 found (car sexpr)
2930                 sexpr (cdr sexpr)))
2931          ;; $i symbol
2932          ((wisent-check-$N sexpr n)
2933           ;; Accumulate $i symbol
2934           (add-to-list 'found sexpr))
2935          )
2936         ;; Accumulate expanded forms
2937         (setq xbody (nconc xbody (list sexpr))))
2938       (cons found xbody))))
2939
2940 (defun wisent-semantic-action (r)
2941   "Set up the Elisp function for semantic action at rule R.
2942 On entry RCODE[R] contains a vector [BODY N (NTERM I)] where BODY is the
2943 body of the semantic action, N is the maximum number of values
2944 available in the parser's stack, NTERM is the nonterminal the semantic
2945 action belongs to, and I is the index of the semantic action inside
2946 NTERM definition.  Return the semantic action symbol.
2947 The semantic action function accepts three arguments:
2948
2949 - the state/value stack
2950 - the top-of-stack index
2951 - the goto table
2952
2953 And returns the updated top-of-stack index."
2954   (if (not (aref ruseful r))
2955       (aset rcode r nil)
2956     (let* ((actn (aref rcode r))
2957            (n    (aref actn 1))         ; nb of val avail. in stack
2958            (NAME (apply 'format "%s:%d" (aref actn 2)))
2959            (form (wisent-semantic-action-expand-body (aref actn 0) n))
2960            ($l   (car form))            ; list of $vars used in body
2961            (form (cdr form))            ; expanded form of body
2962            (nt   (aref rlhs r))         ; nonterminal item no.
2963            (bl   nil)                   ; `let*' binding list
2964            $v i j)
2965       
2966       ;; Compute $N and $regionN bindings
2967       (setq i n)
2968       (while (> i 0)
2969         (setq j (1+ (* 2 (- n i))))
2970         ;; Only bind $regionI if used in action
2971         (setq $v (intern (format "$region%d" i)))
2972         (if (memq $v $l)
2973             (setq bl (cons `(,$v (cdr (aref ,stack (- ,sp ,j)))) bl)))
2974         ;; Only bind $I if used in action
2975         (setq $v (intern (format "$%d" i)))
2976         (if (memq $v $l)
2977             (setq bl (cons `(,$v (car (aref ,stack (- ,sp ,j)))) bl)))
2978         (setq i (1- i)))
2979       
2980       ;; Compute J, the length of rule's RHS.  It will give the
2981       ;; current parser state at STACK[SP - 2*J], and where to push
2982       ;; the new semantic value and the next state, respectively at:
2983       ;; STACK[SP - 2*J + 1] and STACK[SP - 2*J + 2].  Generally N,
2984       ;; the maximum number of values available in the stack, is equal
2985       ;; to J.  But, for mid-rule actions, N is the number of rule
2986       ;; elements before the action and J is always 0 (empty rule).
2987       (setq i (aref rrhs r)
2988             j 0)
2989       (while (> (aref ritem i) 0)
2990         (setq j (1+ j)
2991               i (1+ i)))
2992       
2993       ;; Create the semantic action symbol.
2994       (setq actn (intern NAME (aref rcode 0)))
2995       
2996       ;; Store source code in function cell of the semantic action
2997       ;; symbol.  It will be byte-compiled at automaton's compilation
2998       ;; time.  Using a byte-compiled automaton can significantly
2999       ;; speed up parsing!
3000       (fset actn
3001             `(lambda (,stack ,sp ,gotos)
3002                (let* (,@bl
3003                       ($region
3004                        ,(cond
3005                          ((= n 1)
3006                           (if (assq '$region1 bl)
3007                               '$region1
3008                             `(cdr (aref ,stack (1- ,sp)))))
3009                          ((> n 1)
3010                           `(wisent-production-bounds
3011                             ,stack (- ,sp ,(1- (* 2 n))) (1- ,sp)))))
3012                       ($action ,NAME)
3013                       ($nterm  ',(aref tags nt))
3014                       ,@(and (> j 0) `((,sp (- ,sp ,(* j 2)))))
3015                       (,state (cdr (assq $nterm
3016                                          (aref ,gotos
3017                                                (aref ,stack ,sp))))))
3018                  (setq ,sp (+ ,sp 2))
3019                  ;; push semantic value
3020                  (aset ,stack (1- ,sp) (cons ,form $region))
3021                  ;; push next state
3022                  (aset ,stack ,sp ,state)
3023                  ;; return new top of stack
3024                  ,sp)))
3025       
3026       ;; Return the semantic action symbol
3027       actn)))
3028 \f
3029 ;;;; ----------------------------
3030 ;;;; Build parser LALR automaton.
3031 ;;;; ----------------------------
3032
3033 (defun wisent-parser-automaton ()
3034   "Compute and return LALR(1) automaton from GRAMMAR.
3035 GRAMMAR is in internal format.  GRAM/ACTS are grammar rules
3036 in internal format.  STARTS defines the start symbols."
3037   ;; Check for useless stuff
3038   (wisent-reduce-grammar)
3039   
3040   (wisent-set-derives)
3041   (wisent-set-nullable)
3042   ;; convert to nondeterministic finite state machine.
3043   (wisent-generate-states)
3044   ;; make it deterministic.
3045   (wisent-lalr)
3046   ;; Find and record any conflicts: places where one token of
3047   ;; lookahead is not enough to disambiguate the parsing.  Also
3048   ;; resolve s/r conflicts based on precedence declarations.
3049   (wisent-resolve-conflicts)
3050   (wisent-print-results)
3051   
3052   (vector (wisent-state-actions)        ; action table
3053           (wisent-goto-actions)         ; goto table
3054           start-table                   ; start symbols
3055           (aref rcode 0)                ; sem. action symbol obarray
3056           )
3057   )
3058 \f
3059 ;;;; -------------------
3060 ;;;; Parse input grammar
3061 ;;;; -------------------
3062
3063 (defconst wisent-reserved-symbols (list wisent-error-term)
3064   "The list of reserved symbols.
3065 Also all symbols starting with a character defined in
3066 `wisent-reserved-capitals' are reserved for internal use.")
3067
3068 (defconst wisent-reserved-capitals '(?\$ ?\@)
3069   "The list of reserved capital letters.
3070 All symbol starting with one of these letters are reserved for
3071 internal use.")
3072
3073 (defconst wisent-starts-nonterm '$STARTS
3074   "Main start symbol.
3075 It gives the rules for start symbols.")
3076
3077 (defvar wisent-single-start-flag nil
3078   "Non-nil means allows only one start symbol like in Bison.
3079 That is don't add extra start rules to the grammar.  This is
3080 useful to compare the Wisent's generated automaton with the Bison's
3081 one.")
3082
3083 (defsubst wisent-ISVALID-VAR (x)
3084   "Return non-nil if X is a character or an allowed symbol."
3085   (and x (symbolp x)
3086        (not (memq (aref (symbol-name x) 0) wisent-reserved-capitals))
3087        (not (memq x wisent-reserved-symbols))))
3088
3089 (defsubst wisent-ISVALID-TOKEN (x)
3090   "Return non-nil if X is a character or an allowed symbol."
3091   (or (wisent-char-p x)
3092       (wisent-ISVALID-VAR x)))
3093
3094 (defun wisent-push-token (symbol &optional nocheck)
3095   "Push a new SYMBOL in the list of tokens.
3096 Bypass checking if NOCHECK is non-nil."
3097   ;; Check
3098   (or nocheck (wisent-ISVALID-TOKEN symbol)
3099       (error "Invalid terminal symbol: %S" symbol))
3100   (if (memq symbol token-list)
3101       (message "*** duplicate terminal `%s' ignored" symbol)
3102     ;; Set up properties
3103     (wisent-set-prec        symbol nil)
3104     (wisent-set-assoc       symbol nil)
3105     (wisent-set-item-number symbol ntokens)
3106     ;; Add
3107     (setq ntokens (1+ ntokens)
3108           token-list (cons symbol token-list))))
3109
3110 (defun wisent-push-var (symbol &optional nocheck)
3111   "Push a new SYMBOL in the list of nonterminals.
3112 Bypass checking if NOCHECK is non-nil."
3113   ;; Check
3114   (unless nocheck
3115     (or (wisent-ISVALID-VAR symbol)
3116         (error "Invalid nonterminal symbol: %S" symbol))
3117     (if (memq symbol var-list)
3118         (error "Nonterminal `%s' already defined" symbol)))
3119   ;; Set up properties
3120   (wisent-set-item-number symbol nvars)
3121   ;; Add
3122   (setq nvars (1+ nvars)
3123         var-list (cons symbol var-list)))
3124
3125 (defun wisent-parse-nonterminals (defs)
3126   "Parse nonterminal definitions in DEFS.
3127 Fill in each element of the global arrays RPREC, RCODE, RUSEFUL with
3128 respectively rule precedence level, semantic action code and
3129 usefulness flag.  Return a list of rules of the form (LHS . RHS) where
3130 LHS and RHS are respectively the Left Hand Side and Right Hand Side of
3131 the rule."
3132   (setq rprec  nil
3133         rcode  nil
3134         nitems 0
3135         nrules 0)
3136   (let (def nonterm rlist rule rules rhs rest item items
3137             rhl plevel semact @n @count iactn)
3138     (setq @count 0)
3139     (while defs
3140       (setq def     (car defs)
3141             defs    (cdr defs)
3142             nonterm (car def)
3143             rlist   (cdr def)
3144             iactn   0)
3145       (or (consp rlist)
3146           (error "Invalid nonterminal definition syntax: %S" def))
3147       (while rlist
3148         (setq rule  (car rlist)
3149               rlist (cdr rlist)
3150               items (car rule)
3151               rest  (cdr rule)
3152               rhl   0
3153               rhs   nil)
3154         
3155         ;; Check & count items
3156         (setq nitems (1+ nitems)) ;; LHS item
3157         (while items
3158           (setq item (car items)
3159                 items (cdr items)
3160                 nitems (1+ nitems)) ;; RHS items
3161           (if (listp item)
3162               ;; Mid-rule action
3163               (progn
3164                 (setq @count (1+ @count)
3165                       @n (intern (format "@%d" @count)))
3166                 (wisent-push-var @n t)
3167                 ;; Push a new empty rule with the mid-rule action
3168                 (setq semact (vector item rhl (list nonterm iactn))
3169                       iactn  (1+ iactn)
3170                       plevel nil
3171                       rcode  (cons semact rcode)
3172                       rprec  (cons plevel rprec)
3173                       item   @n ;; Replace action by @N nonterminal
3174                       rules  (cons (list item) rules)
3175                       nitems (1+ nitems)
3176                       nrules (1+ nrules)))
3177             ;; Check terminal or nonterminal symbol
3178             (cond
3179              ((or (memq item token-list) (memq item var-list)))
3180              ;; Create new literal character token
3181              ((wisent-char-p item) (wisent-push-token item t))
3182              ((error "Symbol `%s' is used, but is not defined as a token and has no rules"
3183                      item))))
3184           (setq rhl (1+ rhl)
3185                 rhs (cons item rhs)))
3186         
3187         ;; Check & collect rule precedence level
3188         (setq plevel (when (vectorp (car rest))
3189                        (setq item (car rest)
3190                              rest (cdr rest))
3191                        (if (and (= (length item) 1)
3192                                 (memq (aref item 0) token-list)
3193                                 (wisent-prec (aref item 0)))
3194                            (wisent-item-number (aref item 0))
3195                          (error "Invalid rule precedence level syntax: %S" item)))
3196               rprec (cons plevel rprec))
3197         
3198         ;; Check & collect semantic action body
3199         (setq semact (vector
3200                       (if rest
3201                           (if (cdr rest)
3202                               (error "Invalid semantic action syntax: %S" rest)
3203                             (car rest))
3204                         ;; Give a default semantic action body: nil
3205                         ;; for an empty rule or $1, the value of the
3206                         ;; first symbol in the rule, otherwise.
3207                         (if (> rhl 0) '$1 '()))
3208                       rhl
3209                       (list nonterm iactn))
3210               iactn  (1+ iactn)
3211               rcode  (cons semact rcode))
3212         (setq rules  (cons (cons nonterm (nreverse rhs)) rules)
3213               nrules (1+ nrules))))
3214     
3215     (setq ruseful (make-vector (1+ nrules) t)
3216           rprec   (vconcat (cons nil (nreverse rprec)))
3217           rcode   (vconcat (cons nil (nreverse rcode))))
3218     (nreverse rules)
3219     ))
3220
3221 (defun wisent-parse-grammar (grammar &optional start-list)
3222   "Parse GRAMMAR and build a suitable internal representation.
3223 Optional argument START-LIST defines the start symbols.
3224 GRAMMAR is a list of form: (TOKENS ASSOCS . NONTERMS)
3225
3226 TOKENS is a list of terminal symbols (tokens).
3227
3228 ASSOCS is nil or an alist of (ASSOC-TYPE . ASSOC-VALUE) elements
3229 describing the associativity of TOKENS.  ASSOC-TYPE must be one of the
3230 `default-prec' `nonassoc', `left' or `right' symbols.  When ASSOC-TYPE
3231 is `default-prec', ASSOC-VALUE must be nil or t (the default).
3232 Otherwise it is a list of tokens which must have been previously
3233 declared in TOKENS.
3234
3235 NONTERMS is the list of non terminal definitions (see function
3236 `wisent-parse-nonterminals')."
3237   (working-dynamic-status "(parse input grammar)")
3238   (or (and (consp grammar) (> (length grammar) 2))
3239       (error "Bad input grammar"))
3240   
3241   (let (i r nt pl rhs pre dpre lst start-var assoc rules item
3242           token var def tokens vars defs ep-token ep-var ep-def)
3243     
3244     ;; Built-in tokens
3245     (setq ntokens 0 nvars 0)
3246     (wisent-push-token wisent-eoi-term t)
3247     (wisent-push-token wisent-error-term t)
3248     
3249     ;; Check/collect terminals
3250     (setq lst (car grammar))
3251     (while lst
3252       (wisent-push-token (car lst))
3253       (setq lst (cdr lst)))
3254     
3255     ;; Check/Set up tokens precedence & associativity
3256     (setq lst  (nth 1 grammar)
3257           pre  0
3258           defs nil
3259           dpre nil
3260           default-prec t)
3261     (while lst
3262       (setq def    (car lst)
3263             assoc  (car def)
3264             tokens (cdr def)
3265             lst    (cdr lst))
3266       (if (eq assoc 'default-prec)
3267           (progn
3268             (or (null (cdr tokens))
3269                 (memq (car tokens) '(t nil))
3270                 (error "Invalid default-prec value: %S" tokens))
3271             (setq default-prec (car tokens))
3272             (if dpre
3273                 (message "*** redefining default-prec to %s"
3274                          default-prec))
3275             (setq dpre t))
3276         (or (memq assoc '(left right nonassoc))
3277             (error "Invalid associativity syntax: %S" assoc))
3278         (setq pre (1+ pre))
3279         (while tokens
3280           (setq token  (car tokens)
3281                 tokens (cdr tokens))
3282           (if (memq token defs)
3283               (message "*** redefining precedence of `%s'" token))
3284           (or (memq token token-list)
3285               ;; Define token not previously declared.
3286               (wisent-push-token token))
3287           (setq defs (cons token defs))
3288           ;; Record the precedence and associativity of the terminal.
3289           (wisent-set-prec  token pre)
3290           (wisent-set-assoc token assoc))))
3291     
3292     ;; Check/Collect nonterminals
3293     (setq lst  (nthcdr 2 grammar)
3294           defs nil
3295           vars nil)
3296     (while lst
3297       (setq def (car lst)
3298             lst (cdr lst))
3299       (or (consp def)
3300           (error "Invalid nonterminal definition: %S" def))
3301       (if (memq (car def) token-list)
3302           (error "Nonterminal `%s' already defined as token" (car def)))
3303       (wisent-push-var (car def))
3304       (setq defs (cons def defs)))
3305     (or defs
3306         (error "No input grammar"))
3307     (setq defs (nreverse defs))
3308     
3309     ;; Set up the start symbol.
3310     (setq start-table nil)
3311     (cond
3312      
3313      ;; 1. START-LIST is nil, the start symbol is the first
3314      ;;    nonterminal defined in the grammar (Bison like).
3315      ((null start-list)
3316       (setq start-var (caar defs)))
3317      
3318      ;; 2. START-LIST contains only one element, it is the start
3319      ;;    symbol (Bison like).
3320      ((or wisent-single-start-flag (null (cdr start-list)))
3321       (setq start-var  (car start-list))
3322       (or (assq start-var defs)
3323           (error "Start symbol `%s' has no rule" start-var)))
3324      
3325      ;; 3. START-LIST contains more than one element.  All defines
3326      ;;    potential start symbols.  One of them (the first one by
3327      ;;    default) will be given at parse time to be the parser goal.
3328      ;;    If `wisent-single-start-flag' is non-nil that feature is
3329      ;;    disabled and the first nonterminal in START-LIST defines
3330      ;;    the start symbol, like in case 2 above.
3331      ((not wisent-single-start-flag)
3332       
3333       ;; START-LIST is a list of nonterminals '(nt0 ... ntN).
3334       ;; Build and push ad hoc start rules in the grammar:
3335       
3336       ;; ($STARTS ((nt0) $1) ((nt1) $1) ... ((ntN) $1))
3337       ;; ($nt1    (($$nt1 nt1) $2))
3338       ;; ...
3339       ;; ($ntN    (($$ntN ntN) $2))
3340       
3341       ;; Where internal symbols $ntI and $$ntI are respectively
3342       ;; nonterminals and terminals.
3343       
3344       ;; The internal start symbol $STARTS is used to build the
3345       ;; LALR(1) automaton.  The true default start symbol used by the
3346       ;; parser is the first nonterminal in START-LIST (nt0).
3347       (setq start-var wisent-starts-nonterm
3348             lst       (nreverse start-list))
3349       (while lst
3350         (setq var (car lst)
3351               lst (cdr lst))
3352         (or (memq var var-list)
3353             (error "Start symbol `%s' has no rule" var))
3354         (unless (assq var start-table) ;; Ignore duplicates
3355           ;; For each nt start symbol
3356           (setq ep-var   (intern (format "$%s"  var))
3357                 ep-token (intern (format "$$%s" var)))
3358           (wisent-push-token ep-token t)
3359           (wisent-push-var   ep-var   t)
3360           (setq
3361            ;; Add entry (nt . $$nt) to start-table
3362            start-table (cons (cons var ep-token) start-table)
3363            ;; Add rule ($nt (($$nt nt) $2))
3364            defs (cons (list ep-var (list (list ep-token var) '$2)) defs)
3365            ;; Add start rule (($nt) $1)
3366            ep-def (cons (list (list ep-var) '$1) ep-def))
3367           ))
3368       (wisent-push-var start-var t)
3369       (setq defs (cons (cons start-var ep-def) defs))))
3370     
3371     ;; Set up rules main data structure & RPREC, RCODE, RUSEFUL
3372     (setq rules (wisent-parse-nonterminals defs))
3373     
3374     ;; Set up the terminal & nonterminal lists.
3375     (setq nsyms      (+ ntokens nvars)
3376           token-list (nreverse token-list)
3377           lst        var-list
3378           var-list   nil)
3379     (while lst
3380       (setq var (car lst)
3381             lst (cdr lst)
3382             var-list (cons var var-list))
3383       (wisent-set-item-number ;; adjust nonterminal item number to
3384        var (+ ntokens (wisent-item-number var)))) ;; I += NTOKENS
3385     
3386     ;; Store special item numbers
3387     (setq error-token-number (wisent-item-number wisent-error-term)
3388           start-symbol       (wisent-item-number start-var))
3389     
3390     ;; Keep symbols in the TAGS vector so that TAGS[I] is the symbol
3391     ;; associated to item number I.
3392     (setq tags (vconcat token-list var-list))
3393     ;; Set up RLHS RRHS & RITEM data structures from list of rules
3394     ;; (LHS . RHS) received from `wisent-parse-nonterminals'.
3395     (setq rlhs    (make-vector (1+ nrules) nil)
3396           rrhs    (make-vector (1+ nrules) nil)
3397           ritem   (make-vector (1+ nitems) nil)
3398           i 0
3399           r 1)
3400     (while rules
3401       (aset rlhs r (wisent-item-number (caar rules)))
3402       (aset rrhs r i)
3403       (setq rhs (cdar rules)
3404             pre nil)
3405       (while rhs
3406         (setq item (wisent-item-number (car rhs)))
3407         ;; Get default precedence level of rule, that is the
3408         ;; precedence of the last terminal in it.
3409         (and (wisent-ISTOKEN item)
3410              default-prec
3411              (setq pre item))
3412         
3413         (aset ritem i item)
3414         (setq i (1+ i)
3415               rhs (cdr rhs)))
3416       ;; Setup the precedence level of the rule, that is the one
3417       ;; specified by %prec or the default one.
3418       (and (not (aref rprec r)) ;; Already set by %prec
3419            pre
3420            (wisent-prec (aref tags pre))
3421            (aset rprec r pre))
3422       (aset ritem i (- r))
3423       (setq i (1+ i)
3424             r (1+ r))
3425       (setq rules (cdr rules)))
3426     ))
3427 \f
3428 ;;;; ---------------------
3429 ;;;; Compile input grammar
3430 ;;;; ---------------------
3431
3432 ;;;###autoload
3433 (defun wisent-compile-grammar (grammar &optional start-list)
3434   "Compile the LALR(1) GRAMMAR.
3435
3436 GRAMMAR is a list (TOKENS ASSOCS . NONTERMS) where:
3437
3438 - TOKENS is a list of terminal symbols (tokens).
3439
3440 - ASSOCS is nil, or an alist of (ASSOC-TYPE . ASSOC-VALUE) elements
3441   describing the associativity of TOKENS.  ASSOC-TYPE must be one of
3442   the `default-prec' `nonassoc', `left' or `right' symbols.  When
3443   ASSOC-TYPE is `default-prec', ASSOC-VALUE must be nil or t (the
3444   default).  Otherwise it is a list of tokens which must have been
3445   previously declared in TOKENS.
3446
3447 - NONTERMS is a list of nonterminal definitions.
3448
3449 Optional argument START-LIST specify the possible grammar start
3450 symbols.  This is a list of nonterminals which must have been
3451 previously declared in GRAMMAR's NONTERMS form.  By default, the start
3452 symbol is the first nonterminal defined.  When START-LIST contains
3453 only one element, it is the start symbol.  Otherwise, all elements are
3454 possible start symbols, unless `wisent-single-start-flag' is non-nil.
3455 In that case, the first element is the start symbol, and others are
3456 ignored.
3457
3458 Return an automaton as a vector: [ACTIONS GOTOS STARTS FUNCTIONS]
3459 where:
3460
3461 - ACTIONS is a state/token matrix telling the parser what to do at
3462   every state based on the current lookahead token.  That is shift,
3463   reduce, accept or error.
3464
3465 - GOTOS is a state/nonterminal matrix telling the parser the next
3466   state to go to after reducing with each rule.
3467
3468 - STARTS is an alist which maps the allowed start nonterminal symbols
3469   to tokens that will be first shifted into the parser stack.
3470
3471 - FUNCTIONS is an obarray of semantic action symbols.  Each symbol's
3472   function definition is the semantic action lambda expression."
3473   (if (wisent-automaton-p grammar)
3474       grammar ;; Grammar already compiled just return it
3475     (wisent-with-context compile-grammar
3476       (let* ((working-status-dynamic-type 'working-text-display)
3477              (gc-cons-threshold 1000000)
3478              automaton)
3479         (garbage-collect)
3480         (working-status-forms "Compiling grammar" "done"
3481           (setq wisent-new-log-flag t)
3482           ;; Parse input grammar
3483           (wisent-parse-grammar grammar start-list)
3484           ;; Generate the LALR(1) automaton
3485           (setq automaton (wisent-parser-automaton))
3486           (working-dynamic-status t)
3487           automaton)))))
3488 \f
3489 ;;;; --------------------------
3490 ;;;; Byte compile input grammar
3491 ;;;; --------------------------
3492
3493 (require 'bytecomp)
3494
3495 ;;;###autoload
3496 (defun wisent-byte-compile-grammar (form)
3497   "Byte compile the `wisent-compile-grammar' FORM.
3498 Automatically called by the Emacs Lisp byte compiler as a
3499 `byte-compile' handler."
3500   ;; Eval the `wisent-compile-grammar' form to obtain an LALR
3501   ;; automaton internal data structure.  Then, because the internal
3502   ;; data structure contains an obarray, convert it to a lisp form so
3503   ;; it can be byte-compiled.
3504   (byte-compile-form (wisent-automaton-lisp-form (eval form))))
3505
3506 ;;;###autoload
3507 (put 'wisent-compile-grammar 'byte-compile 'wisent-byte-compile-grammar)
3508
3509 (defun wisent-automaton-lisp-form (automaton)
3510   "Return a Lisp form that produces AUTOMATON.
3511 See also `wisent-compile-grammar' for more details on AUTOMATON."
3512   (or (wisent-automaton-p automaton)
3513       (signal 'wrong-type-argument
3514               (list 'wisent-automaton-p automaton)))
3515   (let ((obn (make-symbol "ob"))        ; Generated obarray name
3516         (obv (aref automaton 3))        ; Semantic actions obarray
3517         )
3518     `(let ((,obn (make-vector 13 0)))
3519        ;; Generate code to initialize the semantic actions obarray,
3520        ;; in local variable OBN.
3521        ,@(let (obcode)
3522            (mapatoms
3523             #'(lambda (s)
3524                 (setq obcode
3525                       (cons `(fset (intern ,(symbol-name s) ,obn)
3526                                    #',(symbol-function s))
3527                             obcode)))
3528             obv)
3529            obcode)
3530        ;; Generate code to create the automaton.
3531        (vector
3532         ;; In code generated to initialize the action table, take
3533         ;; care of symbols that are interned in the semantic actions
3534         ;; obarray.
3535         (vector
3536          ,@(mapcar
3537             #'(lambda (state) ;; for each state
3538                 `(list
3539                   ,@(mapcar
3540                      #'(lambda (tr) ;; for each transition
3541                          (let ((k (car tr))  ; token
3542                                (a (cdr tr))) ; action
3543                            (if (and (symbolp a)
3544                                     (intern-soft (symbol-name a) obv))
3545                                `(cons ,(if (symbolp k) `(quote ,k) k)
3546                                       (intern-soft ,(symbol-name a) ,obn))
3547                              `(quote ,tr))))
3548                      state)))
3549             (aref automaton 0)))
3550         ;; The code of the goto table is unchanged.
3551         ,(aref automaton 1)
3552         ;; The code of the alist of start symbols is unchanged.
3553         ',(aref automaton 2)
3554         ;; The semantic actions obarray is in the local variable OBN.
3555         ,obn))))
3556
3557 (provide 'wisent-comp)
3558
3559 ;;; wisent-comp.el ends here