aboutsummaryrefslogtreecommitdiff
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))))