summary refs log tree commit diff
path: root/src/guile/silex/output.scm
diff options
context:
space:
mode:
Diffstat (limited to 'src/guile/silex/output.scm')
-rw-r--r--src/guile/silex/output.scm1078
1 files changed, 1078 insertions, 0 deletions
diff --git a/src/guile/silex/output.scm b/src/guile/silex/output.scm
new file mode 100644
index 0000000..fc76b01
--- /dev/null
+++ b/src/guile/silex/output.scm
@@ -0,0 +1,1078 @@
+; SILex - Scheme Implementation of Lex
+; Copyright (C) 2001  Danny Dube'
+; 
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation; either version 2
+; of the License, or (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; 
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, write to the Free Software
+; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+;
+; Nettoie les actions en enlevant les lignes blanches avant et apres
+;
+
+(define out-split-in-lines
+  (lambda (s)
+    (let ((len (string-length s)))
+      (let loop ((i 0) (start 0))
+	(cond ((= i len)
+	       '())
+	      ((char=? (string-ref s i) #\newline)
+	       (cons (substring s start (+ i 1))
+		     (loop (+ i 1) (+ i 1))))
+	      (else
+	       (loop (+ i 1) start)))))))
+
+(define out-empty-line?
+  (lambda (s)
+    (let ((len (- (string-length s) 1)))
+      (let loop ((i 0))
+	(cond ((= i len)
+	       #t)
+	      ((char-whitespace? (string-ref s i))
+	       (loop (+ i 1)))
+	      (else
+	       #f))))))
+
+; Enleve les lignes vides dans une liste avant et apres l'action
+(define out-remove-empty-lines
+  (lambda (lines)
+    (let loop ((lines lines) (top? #t))
+      (if (null? lines)
+	  '()
+	  (let ((line (car lines)))
+	    (cond ((not (out-empty-line? line))
+		   (cons line (loop (cdr lines) #f)))
+		  (top?
+		   (loop (cdr lines) #t))
+		  (else
+		   (let ((rest (loop (cdr lines) #f)))
+		     (if (null? rest)
+			 '()
+			 (cons line rest))))))))))
+
+; Enleve les lignes vides avant et apres l'action
+(define out-clean-action
+  (lambda (s)
+    (let* ((lines (out-split-in-lines s))
+	   (clean-lines (out-remove-empty-lines lines)))
+      (apply string-append clean-lines))))
+
+
+
+
+;
+; Pretty-printer pour les booleens, la liste vide, les nombres,
+; les symboles, les caracteres, les chaines, les listes et les vecteurs
+;
+
+; Colonne limite pour le pretty-printer (a ne pas atteindre)
+(define out-max-col 76)
+
+(define out-flatten-list
+  (lambda (ll)
+    (let loop ((ll ll) (part-out '()))
+      (if (null? ll)
+	  part-out
+	  (let* ((new-part-out (loop (cdr ll) part-out))
+		 (head (car ll)))
+	    (cond ((null? head)
+		   new-part-out)
+		  ((pair? head)
+		   (loop head new-part-out))
+		  (else
+		   (cons head new-part-out))))))))
+
+(define out-force-string
+  (lambda (obj)
+    (if (char? obj)
+	(string obj)
+	obj)))
+
+; Transforme une liste impropre en une liste propre qui s'ecrit
+; de la meme facon
+(define out-regular-list
+  (let ((symbolic-dot (string->symbol ".")))
+    (lambda (p)
+      (let ((tail (cdr p)))
+	(cond ((null? tail)
+	       p)
+	      ((pair? tail)
+	       (cons (car p) (out-regular-list tail)))
+	      (else
+	       (list (car p) symbolic-dot tail)))))))
+
+; Cree des chaines d'espaces de facon paresseuse
+(define out-blanks
+  (let ((cache-v (make-vector 80 #f)))
+    (lambda (n)
+      (or (vector-ref cache-v n)
+	  (let ((result (make-string n #\space)))
+	    (vector-set! cache-v n result)
+	    result)))))
+
+; Insere le separateur entre chaque element d'une liste non-vide
+(define out-separate
+  (lambda (text-l sep)
+    (if (null? (cdr text-l))
+	text-l
+	(cons (car text-l) (cons sep (out-separate (cdr text-l) sep))))))
+
+; Met des donnees en colonnes.  Retourne comme out-pp-aux-list
+(define out-pp-columns
+  (lambda (left right wmax txt&lens)
+    (let loop1 ((tls txt&lens) (lwmax 0) (lwlast 0) (lines '()))
+      (if (null? tls)
+	  (vector #t 0 lwmax lwlast (reverse lines))
+	  (let loop2 ((tls tls) (len 0) (first? #t) (prev-pad 0) (line '()))
+	    (cond ((null? tls)
+		   (loop1 tls
+			  (max len lwmax)
+			  len
+			  (cons (reverse line) lines)))
+		  ((> (+ left len prev-pad 1 wmax) out-max-col)
+		   (loop1 tls
+			  (max len lwmax)
+			  len
+			  (cons (reverse line) lines)))
+		  (first?
+		   (let ((text     (caar tls))
+			 (text-len (cdar tls)))
+		     (loop2 (cdr tls)
+			    (+ len text-len)
+			    #f
+			    (- wmax text-len)
+			    (cons text line))))
+		  ((pair? (cdr tls))
+		   (let* ((prev-pad-s (out-blanks prev-pad))
+			  (text     (caar tls))
+			  (text-len (cdar tls)))
+		     (loop2 (cdr tls)
+			    (+ len prev-pad 1 text-len)
+			    #f
+			    (- wmax text-len)
+			    (cons text (cons " " (cons prev-pad-s line))))))
+		  (else
+		   (let ((prev-pad-s (out-blanks prev-pad))
+			 (text     (caar tls))
+			 (text-len (cdar tls)))
+		     (if (> (+ left len prev-pad 1 text-len) right)
+			 (loop1 tls
+				(max len lwmax)
+				len
+				(cons (reverse line) lines))
+			 (loop2 (cdr tls)
+				(+ len prev-pad 1 text-len)
+				#f
+				(- wmax text-len)
+				(append (list text " " prev-pad-s)
+					line)))))))))))
+
+; Retourne un vecteur #( multiline? width-all width-max width-last text-l )
+(define out-pp-aux-list
+  (lambda (l left right)
+    (let loop ((l l) (multi? #f) (wall -1) (wmax -1) (wlast -1) (txt&lens '()))
+      (if (null? l)
+	  (cond (multi?
+		 (vector #t wall wmax wlast (map car (reverse txt&lens))))
+		((<= (+ left wall) right)
+		 (vector #f wall wmax wlast (map car (reverse txt&lens))))
+		((<= (+ left wmax 1 wmax) out-max-col)
+		 (out-pp-columns left right wmax (reverse txt&lens)))
+		(else
+		 (vector #t wall wmax wlast (map car (reverse txt&lens)))))
+	  (let* ((obj (car l))
+		 (last? (null? (cdr l)))
+		 (this-right (if last? right out-max-col))
+		 (result (out-pp-aux obj left this-right))
+		 (obj-multi? (vector-ref result 0))
+		 (obj-wmax   (vector-ref result 1))
+		 (obj-wlast  (vector-ref result 2))
+		 (obj-text   (vector-ref result 3)))
+	    (loop (cdr l)
+		  (or multi? obj-multi?)
+		  (+ wall obj-wmax 1)
+		  (max wmax obj-wmax)
+		  obj-wlast
+		  (cons (cons obj-text obj-wmax) txt&lens)))))))
+
+; Retourne un vecteur #( multiline? wmax wlast text )
+(define out-pp-aux
+  (lambda (obj left right)
+    (cond ((boolean? obj)
+	   (vector #f 2 2 (if obj '("#t") '("#f"))))
+	  ((null? obj)
+	   (vector #f 2 2 '("()")))
+	  ((number? obj)
+	   (let* ((s (number->string obj))
+		  (len (string-length s)))
+	     (vector #f len len (list s))))
+	  ((symbol? obj)
+	   (let* ((s (symbol->string obj))
+		  (len (string-length s)))
+	     (vector #f len len (list s))))
+	  ((char? obj)
+	   (cond ((char=? obj #\space)
+		  (vector #f 7 7 (list "#\\space")))
+		 ((char=? obj #\newline)
+		  (vector #f 9 9 (list "#\\newline")))
+		 (else
+		  (vector #f 3 3 (list "#\\" obj)))))
+	  ((string? obj)
+	   (let loop ((i (- (string-length obj) 1))
+		      (len 1)
+		      (text '("\"")))
+	     (if (= i -1)
+		 (vector #f (+ len 1) (+ len 1) (cons "\"" text))
+		 (let ((c (string-ref obj i)))
+		   (cond ((char=? c #\\)
+			  (loop (- i 1) (+ len 2) (cons "\\\\" text)))
+			 ((char=? c #\")
+			  (loop (- i 1) (+ len 2) (cons "\\\"" text)))
+			 (else
+			  (loop (- i 1) (+ len 1) (cons (string c) text))))))))
+	  ((pair? obj)
+	   (let* ((l (out-regular-list obj))
+		  (result (out-pp-aux-list l (+ left 1) (- right 1)))
+		  (multiline? (vector-ref result 0))
+		  (width-all  (vector-ref result 1))
+		  (width-max  (vector-ref result 2))
+		  (width-last (vector-ref result 3))
+		  (text-l     (vector-ref result 4)))
+	     (if multiline?
+		 (let* ((sep (list #\newline (out-blanks left)))
+			(formatted-text (out-separate text-l sep))
+			(text (list "(" formatted-text ")")))
+		   (vector #t
+			   (+ (max width-max (+ width-last 1)) 1)
+			   (+ width-last 2)
+			   text))
+		 (let* ((sep (list " "))
+			(formatted-text (out-separate text-l sep))
+			(text (list "(" formatted-text ")")))
+		   (vector #f (+ width-all 2) (+ width-all 2) text)))))
+	  ((and (vector? obj) (zero? (vector-length obj)))
+	   (vector #f 3 3 '("#()")))
+	  ((vector? obj)
+	   (let* ((l (vector->list obj))
+		  (result (out-pp-aux-list l (+ left 2) (- right 1)))
+		  (multiline? (vector-ref result 0))
+		  (width-all  (vector-ref result 1))
+		  (width-max  (vector-ref result 2))
+		  (width-last (vector-ref result 3))
+		  (text-l     (vector-ref result 4)))
+	     (if multiline?
+		 (let* ((sep (list #\newline (out-blanks (+ left 1))))
+			(formatted-text (out-separate text-l sep))
+			(text (list "#(" formatted-text ")")))
+		   (vector #t
+			   (+ (max width-max (+ width-last 1)) 2)
+			   (+ width-last 3)
+			   text))
+		 (let* ((sep (list " "))
+			(formatted-text (out-separate text-l sep))
+			(text (list "#(" formatted-text ")")))
+		   (vector #f (+ width-all 3) (+ width-all 3) text)))))
+	  (else
+	   (display "Internal error: out-pp")
+	   (newline)))))
+
+; Retourne la chaine a afficher
+(define out-pp
+  (lambda (obj col)
+    (let* ((list-rec-of-strings-n-chars
+	    (vector-ref (out-pp-aux obj col out-max-col) 3))
+	   (list-of-strings-n-chars
+	    (out-flatten-list list-rec-of-strings-n-chars))
+	   (list-of-strings
+	    (map out-force-string list-of-strings-n-chars)))
+      (apply string-append list-of-strings))))
+
+
+
+
+;
+; Nice-printer, plus rapide mais moins beau que le pretty-printer
+;
+
+(define out-np
+  (lambda (obj start)
+    (letrec ((line-pad
+	      (string-append (string #\newline)
+			     (out-blanks (- start 1))))
+	     (step-line
+	      (lambda (p)
+		(set-car! p line-pad)))
+	     (p-bool
+	      (lambda (obj col objw texts hole cont)
+		(let ((text (if obj "#t" "#f")))
+		  (cont (+ col 2) (+ objw 2) (cons text texts) hole))))
+	     (p-number
+	      (lambda (obj col objw texts hole cont)
+		(let* ((text (number->string obj))
+		       (len (string-length text)))
+		  (cont (+ col len) (+ objw len) (cons text texts) hole))))
+	     (p-symbol
+	      (lambda (obj col objw texts hole cont)
+		(let* ((text (symbol->string obj))
+		       (len (string-length text)))
+		  (cont (+ col len) (+ objw len) (cons text texts) hole))))
+	     (p-char
+	      (lambda (obj col objw texts hole cont)
+		(let* ((text
+			(cond ((char=? obj #\space) "#\\space")
+			      ((char=? obj #\newline) "#\\newline")
+			      (else (string-append "#\\" (string obj)))))
+		       (len (string-length text)))
+		  (cont (+ col len) (+ objw len) (cons text texts) hole))))
+	     (p-list
+	      (lambda (obj col objw texts hole cont)
+		(p-tail obj (+ col 1) (+ objw 1) (cons "(" texts) hole cont)))
+	     (p-vector
+	      (lambda (obj col objw texts hole cont)
+		(p-list (vector->list obj)
+			(+ col 1) (+ objw 1) (cons "#" texts) hole cont)))
+	     (p-tail
+	      (lambda (obj col objw texts hole cont)
+		(if (null? obj)
+		    (cont (+ col 1) (+ objw 1) (cons ")" texts) hole)
+		    (p-obj (car obj) col objw texts hole
+			   (make-cdr-cont obj cont)))))
+	     (make-cdr-cont
+	      (lambda (obj cont)
+		(lambda (col objw texts hole)
+		  (cond ((null? (cdr obj))
+			 (cont (+ col 1) (+ objw 1) (cons ")" texts) hole))
+			((> col out-max-col)
+			 (step-line hole)
+			 (let ((hole2 (cons " " texts)))
+			   (p-cdr obj (+ start objw 1) 0 hole2 hole2 cont)))
+			(else
+			 (let ((hole2 (cons " " texts)))
+			   (p-cdr obj (+ col 1) 0 hole2 hole2 cont)))))))
+	     (p-cdr
+	      (lambda (obj col objw texts hole cont)
+		(if (pair? (cdr obj))
+		    (p-tail (cdr obj) col objw texts hole cont)
+		    (p-dot col objw texts hole
+			   (make-cdr-cont (list #f (cdr obj)) cont)))))
+	     (p-dot
+	      (lambda (col objw texts hole cont)
+		(cont (+ col 1) (+ objw 1) (cons "." texts) hole)))
+	     (p-obj
+	      (lambda (obj col objw texts hole cont)
+		(cond ((boolean? obj)
+		       (p-bool obj col objw texts hole cont))
+		      ((number? obj)
+		       (p-number obj col objw texts hole cont))
+		      ((symbol? obj)
+		       (p-symbol obj col objw texts hole cont))
+		      ((char? obj)
+		       (p-char obj col objw texts hole cont))
+		      ((or (null? obj) (pair? obj))
+		       (p-list obj col objw texts hole cont))
+		      ((vector? obj)
+		       (p-vector obj col objw texts hole cont))))))
+      (p-obj obj start 0 '() (cons #f #f)
+	     (lambda (col objw texts hole)
+	       (if (> col out-max-col)
+		   (step-line hole))
+	       (apply string-append (reverse texts)))))))
+
+
+
+
+;
+; Fonction pour afficher une table
+; Appelle la sous-routine adequate pour le type de fin de table
+;
+
+; Affiche la table d'un driver
+(define out-print-table
+  (lambda (args-alist
+	   <<EOF>>-action <<ERROR>>-action rules
+	   nl-start no-nl-start arcs-v acc-v
+	   port)
+    (let* ((filein
+	    (cdr (assq 'filein args-alist)))
+	   (table-name
+	    (cdr (assq 'table-name args-alist)))
+	   (pretty?
+	    (assq 'pp args-alist))
+	   (counters-type
+	    (let ((a (assq 'counters args-alist)))
+	      (if a (cdr a) 'line)))
+	   (counters-param-list
+	    (cond ((eq? counters-type 'none)
+		   ")")
+		  ((eq? counters-type 'line)
+		   " yyline)")
+		  (else ; 'all
+		   " yyline yycolumn yyoffset)")))
+	   (counters-param-list-short
+	    (if (char=? (string-ref counters-param-list 0) #\space)
+		(substring counters-param-list
+			   1
+			   (string-length counters-param-list))
+		counters-param-list))
+	   (clean-eof-action
+	    (out-clean-action <<EOF>>-action))
+	   (clean-error-action
+	    (out-clean-action <<ERROR>>-action))
+	   (rule-op
+	    (lambda (rule) (out-clean-action (get-rule-action rule))))
+	   (rules-l
+	    (vector->list rules))
+	   (clean-actions-l
+	    (map rule-op rules-l))
+	   (yytext?-l
+	    (map get-rule-yytext? rules-l)))
+
+      ; Commentaires prealables
+      (display ";" port)
+      (newline port)
+      (display "; Table generated from the file " port)
+      (display filein port)
+      (display " by SILex 1.0" port)
+      (newline port)
+      (display ";" port)
+      (newline port)
+      (newline port)
+
+      ; Ecrire le debut de la table
+      (display "(define " port)
+      (display table-name port)
+      (newline port)
+      (display "  (vector" port)
+      (newline port)
+
+      ; Ecrire la description du type de compteurs
+      (display "   '" port)
+      (write counters-type port)
+      (newline port)
+
+      ; Ecrire l'action pour la fin de fichier
+      (display "   (lambda (yycontinue yygetc yyungetc)" port)
+      (newline port)
+      (display "     (lambda (yytext" port)
+      (display counters-param-list port)
+      (newline port)
+      (display clean-eof-action port)
+      (display "       ))" port)
+      (newline port)
+
+      ; Ecrire l'action pour le cas d'erreur
+      (display "   (lambda (yycontinue yygetc yyungetc)" port)
+      (newline port)
+      (display "     (lambda (yytext" port)
+      (display counters-param-list port)
+      (newline port)
+      (display clean-error-action port)
+      (display "       ))" port)
+      (newline port)
+
+      ; Ecrire le vecteur des actions des regles ordinaires
+      (display "   (vector" port)
+      (newline port)
+      (let loop ((al clean-actions-l) (yyl yytext?-l))
+	(if (pair? al)
+	    (let ((yytext? (car yyl)))
+	      (display "    " port)
+	      (write yytext? port)
+	      (newline port)
+	      (display "    (lambda (yycontinue yygetc yyungetc)" port)
+	      (newline port)
+	      (if yytext?
+		  (begin
+		    (display "      (lambda (yytext" port)
+		    (display counters-param-list port))
+		  (begin
+		    (display "      (lambda (" port)
+		    (display counters-param-list-short port)))
+	      (newline port)
+	      (display (car al) port)
+	      (display "        ))" port)
+	      (if (pair? (cdr al))
+		  (newline port))
+	      (loop (cdr al) (cdr yyl)))))
+      (display ")" port)
+      (newline port)
+
+      ; Ecrire l'automate
+      (cond ((assq 'portable args-alist)
+	     (out-print-table-chars
+	      pretty?
+	      nl-start no-nl-start arcs-v acc-v
+	      port))
+	    ((assq 'code args-alist)
+	     (out-print-table-code
+	      counters-type (vector-length rules) yytext?-l
+	      nl-start no-nl-start arcs-v acc-v
+	      port))
+	    (else
+	     (out-print-table-data
+	      pretty?
+	      nl-start no-nl-start arcs-v acc-v
+	      port))))))
+
+;
+; Affiche l'automate sous forme d'arbres de decision
+; Termine la table du meme coup
+;
+
+(define out-print-table-data
+  (lambda (pretty? nl-start no-nl-start arcs-v acc-v port)
+    (let* ((len (vector-length arcs-v))
+	   (trees-v (make-vector len)))
+      (let loop ((i 0))
+	(if (< i len)
+	    (begin
+	      (vector-set! trees-v i (prep-arcs->tree (vector-ref arcs-v i)))
+	      (loop (+ i 1)))))
+
+      ; Decrire le format de l'automate
+      (display "   'decision-trees" port)
+      (newline port)
+
+      ; Ecrire l'etat de depart pour le cas "debut de la ligne"
+      (display "   " port)
+      (write nl-start port)
+      (newline port)
+
+      ; Ecrire l'etat de depart pour le cas "pas au debut de la ligne"
+      (display "   " port)
+      (write no-nl-start port)
+      (newline port)
+
+      ; Ecrire la table de transitions
+      (display "   '" port)
+      (if pretty?
+	  (display (out-pp trees-v 5) port)
+	  (display (out-np trees-v 5) port))
+      (newline port)
+
+      ; Ecrire la table des acceptations
+      (display "   '" port)
+      (if pretty?
+	  (display (out-pp acc-v 5) port)
+	  (display (out-np acc-v 5) port))
+
+      ; Ecrire la fin de la table
+      (display "))" port)
+      (newline port))))
+
+;
+; Affiche l'automate sous forme de listes de caracteres taggees
+; Termine la table du meme coup
+;
+
+(define out-print-table-chars
+  (lambda (pretty? nl-start no-nl-start arcs-v acc-v port)
+    (let* ((len (vector-length arcs-v))
+	   (portable-v (make-vector len))
+	   (arc-op (lambda (arc)
+		     (cons (class->tagged-char-list (car arc)) (cdr arc)))))
+      (let loop ((s 0))
+	(if (< s len)
+	    (let* ((arcs (vector-ref arcs-v s))
+		   (port-arcs (map arc-op arcs)))
+	      (vector-set! portable-v s port-arcs)
+	      (loop (+ s 1)))))
+
+      ; Decrire le format de l'automate
+      (display "   'tagged-chars-lists" port)
+      (newline port)
+
+      ; Ecrire l'etat de depart pour le cas "debut de la ligne"
+      (display "   " port)
+      (write nl-start port)
+      (newline port)
+
+      ; Ecrire l'etat de depart pour le cas "pas au debut de la ligne"
+      (display "   " port)
+      (write no-nl-start port)
+      (newline port)
+
+      ; Ecrire la table de transitions
+      (display "   '" port)
+      (if pretty?
+	  (display (out-pp portable-v 5) port)
+	  (display (out-np portable-v 5) port))
+      (newline port)
+
+      ; Ecrire la table des acceptations
+      (display "   '" port)
+      (if pretty?
+	  (display (out-pp acc-v 5) port)
+	  (display (out-np acc-v 5) port))
+
+      ; Ecrire la fin de la table
+      (display "))" port)
+      (newline port))))
+
+;
+; Genere l'automate en code Scheme
+; Termine la table du meme coup
+;
+
+(define out-print-code-trans3
+  (lambda (margin tree action-var port)
+    (newline port)
+    (display (out-blanks margin) port)
+    (cond ((eq? tree 'err)
+	   (display action-var port))
+	  ((number? tree)
+	   (display "(state-" port)
+	   (display tree port)
+	   (display " " port)
+	   (display action-var port)
+	   (display ")" port))
+	  ((eq? (car tree) '=)
+	   (display "(if (= c " port)
+	   (display (list-ref tree 1) port)
+	   (display ")" port)
+	   (out-print-code-trans3 (+ margin 4)
+				  (list-ref tree 2)
+				  action-var
+				  port)
+	   (out-print-code-trans3 (+ margin 4)
+				  (list-ref tree 3)
+				  action-var
+				  port)
+	   (display ")" port))
+	  (else
+	   (display "(if (< c " port)
+	   (display (list-ref tree 0) port)
+	   (display ")" port)
+	   (out-print-code-trans3 (+ margin 4)
+				  (list-ref tree 1)
+				  action-var
+				  port)
+	   (out-print-code-trans3 (+ margin 4)
+				  (list-ref tree 2)
+				  action-var
+				  port)
+	   (display ")" port)))))
+
+(define out-print-code-trans2
+  (lambda (margin tree action-var port)
+    (newline port)
+    (display (out-blanks margin) port)
+    (display "(if c" port)
+    (out-print-code-trans3 (+ margin 4) tree action-var port)
+    (newline port)
+    (display (out-blanks (+ margin 4)) port)
+    (display action-var port)
+    (display ")" port)))
+
+(define out-print-code-trans1
+  (lambda (margin tree action-var port)
+    (newline port)
+    (display (out-blanks margin) port)
+    (if (eq? tree 'err)
+	(display action-var port)
+	(begin
+	  (display "(let ((c (read-char)))" port)
+	  (out-print-code-trans2 (+ margin 2) tree action-var port)
+	  (display ")" port)))))
+
+(define out-print-table-code
+  (lambda (counters nbrules yytext?-l
+	   nl-start no-nl-start arcs-v acc-v
+	   port)
+    (let* ((counters-params
+	    (cond ((eq? counters 'none) ")")
+		  ((eq? counters 'line) " yyline)")
+		  ((eq? counters 'all)  " yyline yycolumn yyoffset)")))
+	   (counters-params-short
+	    (cond ((eq? counters 'none) ")")
+		  ((eq? counters 'line) "yyline)")
+		  ((eq? counters 'all)  "yyline yycolumn yyoffset)")))
+	   (nbstates (vector-length arcs-v))
+	   (trees-v (make-vector nbstates)))
+      (let loop ((s 0))
+	(if (< s nbstates)
+	    (begin
+	      (vector-set! trees-v s (prep-arcs->tree (vector-ref arcs-v s)))
+	      (loop (+ s 1)))))
+
+      ; Decrire le format de l'automate
+      (display "   'code" port)
+      (newline port)
+
+      ; Ecrire l'entete de la fonction
+      (display "   (lambda (<<EOF>>-pre-action" port)
+      (newline port)
+      (display "            <<ERROR>>-pre-action" port)
+      (newline port)
+      (display "            rules-pre-action" port)
+      (newline port)
+      (display "            IS)" port)
+      (newline port)
+
+      ; Ecrire le debut du letrec et les variables d'actions brutes
+      (display "     (letrec" port)
+      (newline port)
+      (display "         ((user-action-<<EOF>> #f)" port)
+      (newline port)
+      (display "          (user-action-<<ERROR>> #f)" port)
+      (newline port)
+      (let loop ((i 0))
+	(if (< i nbrules)
+	    (begin
+	      (display "          (user-action-" port)
+	      (write i port)
+	      (display " #f)" port)
+	      (newline port)
+	      (loop (+ i 1)))))
+
+      ; Ecrire l'extraction des fonctions du IS
+      (display "          (start-go-to-end    " port)
+      (display "(cdr (assq 'start-go-to-end IS)))" port)
+      (newline port)
+      (display "          (end-go-to-point    " port)
+      (display "(cdr (assq 'end-go-to-point IS)))" port)
+      (newline port)
+      (display "          (init-lexeme        " port)
+      (display "(cdr (assq 'init-lexeme IS)))" port)
+      (newline port)
+      (display "          (get-start-line     " port)
+      (display "(cdr (assq 'get-start-line IS)))" port)
+      (newline port)
+      (display "          (get-start-column   " port)
+      (display "(cdr (assq 'get-start-column IS)))" port)
+      (newline port)
+      (display "          (get-start-offset   " port)
+      (display "(cdr (assq 'get-start-offset IS)))" port)
+      (newline port)
+      (display "          (peek-left-context  " port)
+      (display "(cdr (assq 'peek-left-context IS)))" port)
+      (newline port)
+      (display "          (peek-char          " port)
+      (display "(cdr (assq 'peek-char IS)))" port)
+      (newline port)
+      (display "          (read-char          " port)
+      (display "(cdr (assq 'read-char IS)))" port)
+      (newline port)
+      (display "          (get-start-end-text " port)
+      (display "(cdr (assq 'get-start-end-text IS)))" port)
+      (newline port)
+      (display "          (user-getc          " port)
+      (display "(cdr (assq 'user-getc IS)))" port)
+      (newline port)
+      (display "          (user-ungetc        " port)
+      (display "(cdr (assq 'user-ungetc IS)))" port)
+      (newline port)
+
+      ; Ecrire les variables d'actions
+      (display "          (action-<<EOF>>" port)
+      (newline port)
+      (display "           (lambda (" port)
+      (display counters-params-short port)
+      (newline port)
+      (display "             (user-action-<<EOF>> \"\"" port)
+      (display counters-params port)
+      (display "))" port)
+      (newline port)
+      (display "          (action-<<ERROR>>" port)
+      (newline port)
+      (display "           (lambda (" port)
+      (display counters-params-short port)
+      (newline port)
+      (display "             (user-action-<<ERROR>> \"\"" port)
+      (display counters-params port)
+      (display "))" port)
+      (newline port)
+      (let loop ((i 0) (yyl yytext?-l))
+	(if (< i nbrules)
+	    (begin
+	      (display "          (action-" port)
+	      (display i port)
+	      (newline port)
+	      (display "           (lambda (" port)
+	      (display counters-params-short port)
+	      (newline port)
+	      (if (car yyl)
+		  (begin
+		    (display "             (let ((yytext" port)
+		    (display " (get-start-end-text)))" port)
+		    (newline port)
+		    (display "               (start-go-to-end)" port)
+		    (newline port)
+		    (display "               (user-action-" port)
+		    (display i port)
+		    (display " yytext" port)
+		    (display counters-params port)
+		    (display ")))" port)
+		    (newline port))
+		  (begin
+		    (display "             (start-go-to-end)" port)
+		    (newline port)
+		    (display "             (user-action-" port)
+		    (display i port)
+		    (display counters-params port)
+		    (display "))" port)
+		    (newline port)))
+	      (loop (+ i 1) (cdr yyl)))))
+
+      ; Ecrire les variables d'etats
+      (let loop ((s 0))
+	(if (< s nbstates)
+	    (let* ((tree (vector-ref trees-v s))
+		   (acc (vector-ref acc-v s))
+		   (acc-eol (car acc))
+		   (acc-no-eol (cdr acc)))
+	      (display "          (state-" port)
+	      (display s port)
+	      (newline port)
+	      (display "           (lambda (action)" port)
+	      (cond ((not acc-eol)
+		     (out-print-code-trans1 13 tree "action" port))
+		    ((not acc-no-eol)
+		     (newline port)
+		     (if (eq? tree 'err)
+			 (display "             (let* ((c (peek-char))" port)
+			 (display "             (let* ((c (read-char))" port))
+		     (newline port)
+		     (display "                    (new-action (if (o" port)
+		     (display "r (not c) (= c lexer-integer-newline))" port)
+		     (newline port)
+		     (display "                                  " port)
+		     (display "  (begin (end-go-to-point) action-" port)
+		     (display acc-eol port)
+		     (display ")" port)
+		     (newline port)
+		     (display "                       " port)
+		     (display "             action)))" port)
+		     (if (eq? tree 'err)
+			 (out-print-code-trans1 15 tree "new-action" port)
+			 (out-print-code-trans2 15 tree "new-action" port))
+		     (display ")" port))
+		    ((< acc-eol acc-no-eol)
+		     (newline port)
+		     (display "             (end-go-to-point)" port)
+		     (newline port)
+		     (if (eq? tree 'err)
+			 (display "             (let* ((c (peek-char))" port)
+			 (display "             (let* ((c (read-char))" port))
+		     (newline port)
+		     (display "                    (new-action (if (o" port)
+		     (display "r (not c) (= c lexer-integer-newline))" port)
+		     (newline port)
+		     (display "                      " port)
+		     (display "              action-" port)
+		     (display acc-eol port)
+		     (newline port)
+		     (display "                      " port)
+		     (display "              action-" port)
+		     (display acc-no-eol port)
+		     (display ")))" port)
+		     (if (eq? tree 'err)
+			 (out-print-code-trans1 15 tree "new-action" port)
+			 (out-print-code-trans2 15 tree "new-action" port))
+		     (display ")" port))
+		    (else
+		     (let ((action-var
+			    (string-append "action-"
+					   (number->string acc-eol))))
+		       (newline port)
+		       (display "             (end-go-to-point)" port)
+		       (out-print-code-trans1 13 tree action-var port))))
+	      (display "))" port)
+	      (newline port)
+	      (loop (+ s 1)))))
+
+      ; Ecrire la variable de lancement de l'automate
+      (display "          (start-automaton" port)
+      (newline port)
+      (display "           (lambda ()" port)
+      (newline port)
+      (if (= nl-start no-nl-start)
+	  (begin
+	    (display "             (if (peek-char)" port)
+	    (newline port)
+	    (display "                 (state-" port)
+	    (display nl-start port)
+	    (display " action-<<ERROR>>)" port)
+	    (newline port)
+	    (display "                 action-<<EOF>>)" port))
+	  (begin
+	    (display "             (cond ((not (peek-char))" port)
+	    (newline port)
+	    (display "                    action-<<EOF>>)" port)
+	    (newline port)
+	    (display "                   ((= (peek-left-context)" port)
+	    (display " lexer-integer-newline)" port)
+	    (newline port)
+	    (display "                    (state-" port)
+	    (display nl-start port)
+	    (display " action-<<ERROR>>))" port)
+	    (newline port)
+	    (display "                   (else" port)
+	    (newline port)
+	    (display "                    (state-" port)
+	    (display no-nl-start port)
+	    (display " action-<<ERROR>>)))" port)))
+      (display "))" port)
+      (newline port)
+
+      ; Ecrire la fonction principale de lexage
+      (display "          (final-lexer" port)
+      (newline port)
+      (display "           (lambda ()" port)
+      (newline port)
+      (display "             (init-lexeme)" port)
+      (newline port)
+      (cond ((eq? counters 'none)
+	     (display "             ((start-automaton))" port))
+	    ((eq? counters 'line)
+	     (display "             (let ((yyline (get-start-line)))" port)
+	     (newline port)
+	     (display "               ((start-automaton) yyline))" port))
+	    ((eq? counters 'all)
+	     (display "             (let ((yyline (get-start-line))" port)
+	     (newline port)
+	     (display "                   (yycolumn (get-start-column))" port)
+	     (newline port)
+	     (display "                   (yyoffset (get-start-offset)))" port)
+	     (newline port)
+	     (display "               ((start-automat" port)
+	     (display "on) yyline yycolumn yyoffset))" port)))
+      (display "))" port)
+
+      ; Fermer les bindings du grand letrec
+      (display ")" port)
+      (newline port)
+
+      ; Initialiser les variables user-action-XX
+      (display "       (set! user-action-<<EOF>>" port)
+      (display " (<<EOF>>-pre-action" port)
+      (newline port)
+      (display "                                  final-lexer" port)
+      (display " user-getc user-ungetc))" port)
+      (newline port)
+      (display "       (set! user-action-<<ERROR>>" port)
+      (display " (<<ERROR>>-pre-action" port)
+      (newline port)
+      (display "                                    final-lexer" port)
+      (display " user-getc user-ungetc))" port)
+      (newline port)
+      (let loop ((r 0))
+	(if (< r nbrules)
+	    (let* ((str-r (number->string r))
+		   (blanks (out-blanks (string-length str-r))))
+	      (display "       (set! user-action-" port)
+	      (display str-r port)
+	      (display " ((vector-ref rules-pre-action " port)
+	      (display (number->string (+ (* 2 r) 1)) port)
+	      (display ")" port)
+	      (newline port)
+	      (display blanks port)
+	      (display "                           final-lexer " port)
+	      (display "user-getc user-ungetc))" port)
+	      (newline port)
+	      (loop (+ r 1)))))
+
+      ; Faire retourner le lexer final et fermer la table au complet
+      (display "       final-lexer))))" port)
+      (newline port))))
+
+;
+; Fonctions necessaires a l'initialisation automatique du lexer
+;
+
+(define out-print-driver-functions
+  (lambda (args-alist port)
+    (let ((counters   (cdr (or (assq 'counters args-alist) '(z . line))))
+	  (table-name (cdr (assq 'table-name args-alist))))
+      (display ";" port)
+      (newline port)
+      (display "; User functions" port)
+      (newline port)
+      (display ";" port)
+      (newline port)
+      (newline port)
+      (display "(define lexer #f)" port)
+      (newline port)
+      (newline port)
+      (if (not (eq? counters 'none))
+	  (begin
+	    (display "(define lexer-get-line   #f)" port)
+	    (newline port)
+	    (if (eq? counters 'all)
+		(begin
+		  (display "(define lexer-get-column #f)" port)
+		  (newline port)
+		  (display "(define lexer-get-offset #f)" port)
+		  (newline port)))))
+      (display "(define lexer-getc       #f)" port)
+      (newline port)
+      (display "(define lexer-ungetc     #f)" port)
+      (newline port)
+      (newline port)
+      (display "(define lexer-init" port)
+      (newline port)
+      (display "  (lambda (input-type input)" port)
+      (newline port)
+      (display "    (let ((IS (lexer-make-IS input-type input '" port)
+      (write counters port)
+      (display ")))" port)
+      (newline port)
+      (display "      (set! lexer (lexer-make-lexer " port)
+      (display table-name port)
+      (display " IS))" port)
+      (newline port)
+      (if (not (eq? counters 'none))
+	  (begin
+	    (display "      (set! lexer-get-line   (lexer-get-func-line IS))"
+		     port)
+	    (newline port)
+	    (if (eq? counters 'all)
+		(begin
+		  (display
+		   "      (set! lexer-get-column (lexer-get-func-column IS))"
+		   port)
+		  (newline port)
+		  (display
+		   "      (set! lexer-get-offset (lexer-get-func-offset IS))"
+		   port)
+		  (newline port)))))
+      (display "      (set! lexer-getc       (lexer-get-func-getc IS))" port)
+      (newline port)
+      (display "      (set! lexer-ungetc     (lexer-get-func-ungetc IS)))))"
+	       port)
+      (newline port))))
+
+;
+; Fonction principale
+; Affiche une table ou un driver complet
+;
+
+(define output
+  (lambda (args-alist
+	   <<EOF>>-action <<ERROR>>-action rules
+	   nl-start no-nl-start arcs acc)
+    (let* ((fileout          (cdr (assq 'fileout args-alist)))
+	   (port             (open-output-file fileout))
+	   (complete-driver? (cdr (assq 'complete-driver? args-alist))))
+      (if complete-driver?
+	  (begin
+	    (out-print-run-time-lib port)
+	    (newline port)))
+      (out-print-table args-alist
+		       <<EOF>>-action <<ERROR>>-action rules
+		       nl-start no-nl-start arcs acc
+		       port)
+      (if complete-driver?
+	  (begin
+	    (newline port)
+	    (out-print-driver-functions args-alist port)))
+      (close-output-port port))))