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