; 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.
;
; Gestion d'erreurs
;
(define lex-exit-continuation #f)
(define lex-unwind-protect-list '())
(define lex-error-filename #f)
(define lex-unwind-protect
(lambda (proc)
(set! lex-unwind-protect-list (cons proc lex-unwind-protect-list))))
(define lex-error
(lambda (line column . l)
(let* ((linestr (if line (number->string line) #f))
(colstr (if column (number->string column) #f))
(namelen (string-length lex-error-filename))
(linelen (if line (string-length linestr) -1))
(collen (if column (string-length colstr) -1))
(totallen (+ namelen 1 linelen 1 collen 2)))
(display "Lex error:")
(newline)
(display lex-error-filename)
(if line
(begin
(display ":")
(display linestr)))
(if column
(begin
(display ":")
(display colstr)))
(display ": ")
(let loop ((l l))
(if (null? l)
(newline)
(let ((item (car l)))
(display item)
(if (equal? '#\newline item)
(let loop2 ((i totallen))
(if (> i 0)
(begin
(display #\space)
(loop2 (- i 1))))))
(loop (cdr l)))))
(newline)
(let loop ((l lex-unwind-protect-list))
(if (pair? l)
(begin
((car l))
(loop (cdr l)))))
(lex-exit-continuation #f))))
;
; Decoupage des arguments
;
(define lex-recognized-args
'(complete-driver?
filein
table-name
fileout
counters
portable
code
pp))
(define lex-valued-args
'(complete-driver?
filein
table-name
fileout
counters))
(define lex-parse-args
(lambda (args)
(let loop ((args args))
(if (null? args)
'()
(let ((sym (car args)))
(cond ((not (symbol? sym))
(lex-error #f #f "bad option list."))
((not (memq sym lex-recognized-args))
(lex-error #f #f "unrecognized option \"" sym "\"."))
((not (memq sym lex-valued-args))
(cons (cons sym '()) (loop (cdr args))))
((null? (cdr args))
(lex-error #f #f "the value of \"" sym "\" not specified."))
(else
(cons (cons sym (cadr args)) (loop (cddr args))))))))))
;
; Differentes etapes de la fabrication de l'automate
;
(define lex1
(lambda (filein)
; (display "lex1: ") (write (get-internal-run-time)) (newline)
(parser filein)))
(define lex2
(lambda (filein)
(let* ((result (lex1 filein))
(<<EOF>>-action (car result))
(<<ERROR>>-action (cadr result))
(rules (cddr result)))
; (display "lex2: ") (write (get-internal-run-time)) (newline)
(append (list <<EOF>>-action <<ERROR>>-action rules)
(re2nfa rules)))))
(define lex3
(lambda (filein)
(let* ((result (lex2 filein))
(<<EOF>>-action (list-ref result 0))
(<<ERROR>>-action (list-ref result 1))
(rules (list-ref result 2))
(nl-start (list-ref result 3))
(no-nl-start (list-ref result 4))
(arcs (list-ref result 5))
(acc (list-ref result 6)))
; (display "lex3: ") (write (get-internal-run-time)) (newline)
(append (list <<EOF>>-action <<ERROR>>-action rules)
(noeps nl-start no-nl-start arcs acc)))))
(define lex4
(lambda (filein)
(let* ((result (lex3 filein))
(<<EOF>>-action (list-ref result 0))
(<<ERROR>>-action (list-ref result 1))
(rules (list-ref result 2))
(nl-start (list-ref result 3))
(no-nl-start (list-ref result 4))
(arcs (list-ref result 5))
(acc (list-ref result 6)))
; (display "lex4: ") (write (get-internal-run-time)) (newline)
(append (list <<EOF>>-action <<ERROR>>-action rules)
(sweep nl-start no-nl-start arcs acc)))))
(define lex5
(lambda (filein)
(let* ((result (lex4 filein))
(<<EOF>>-action (list-ref result 0))
(<<ERROR>>-action (list-ref result 1))
(rules (list-ref result 2))
(nl-start (list-ref result 3))
(no-nl-start (list-ref result 4))
(arcs (list-ref result 5))
(acc (list-ref result 6)))
; (display "lex5: ") (write (get-internal-run-time)) (newline)
(append (list <<EOF>>-action <<ERROR>>-action rules)
(nfa2dfa nl-start no-nl-start arcs acc)))))
(define lex6
(lambda (args-alist)
(let* ((filein (cdr (assq 'filein args-alist)))
(result (lex5 filein))
(<<EOF>>-action (list-ref result 0))
(<<ERROR>>-action (list-ref result 1))
(rules (list-ref result 2))
(nl-start (list-ref result 3))
(no-nl-start (list-ref result 4))
(arcs (list-ref result 5))
(acc (list-ref result 6)))
; (display "lex6: ") (write (get-internal-run-time)) (newline)
(prep-set-rules-yytext? rules)
(output args-alist
<<EOF>>-action <<ERROR>>-action
rules nl-start no-nl-start arcs acc)
#t)))
(define lex7
(lambda (args)
(call-with-current-continuation
(lambda (exit)
(set! lex-exit-continuation exit)
(set! lex-unwind-protect-list '())
(set! lex-error-filename (cadr (memq 'filein args)))
(let* ((args-alist (lex-parse-args args))
(result (lex6 args-alist)))
; (display "lex7: ") (write (get-internal-run-time)) (newline)
result)))))
;
; Fonctions principales
;
(define lex
(lambda (filein fileout . options)
(lex7 (append (list 'complete-driver? #t
'filein filein
'table-name "lexer-default-table"
'fileout fileout)
options))))
(define lex-tables
(lambda (filein table-name fileout . options)
(lex7 (append (list 'complete-driver? #f
'filein filein
'table-name table-name
'fileout fileout)
options))))