;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; ;;; Language Technologies Institute ;;; ;;; Carnegie Mellon University ;;; ;;; Copyright (c) 1999 ;;; ;;; All Rights Reserved. ;;; ;;; ;;; ;;; Permission is hereby granted, free of charge, to use and distribute ;;; ;;; this software and its documentation without restriction, including ;;; ;;; without limitation the rights to use, copy, modify, merge, publish, ;;; ;;; distribute, sublicense, and/or sell copies of this work, and to ;;; ;;; permit persons to whom this work is furnished to do so, subject to ;;; ;;; the following conditions: ;;; ;;; 1. The code must retain the above copyright notice, this list of ;;; ;;; conditions and the following disclaimer. ;;; ;;; 2. Any modifications must be clearly marked as such. ;;; ;;; 3. Original authors' names are not deleted. ;;; ;;; 4. The authors' names are not used to endorse or promote products ;;; ;;; derived from this software without specific prior written ;;; ;;; permission. ;;; ;;; ;;; ;;; CARNEGIE MELLON UNIVERSITY AND THE CONTRIBUTORS TO THIS WORK ;;; ;;; DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ;;; ;;; ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT ;;; ;;; SHALL CARNEGIE MELLON UNIVERSITY NOR THE CONTRIBUTORS BE LIABLE ;;; ;;; FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ;;; ;;; WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN ;;; ;;; AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ;;; ;;; ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF ;;; ;;; THIS SOFTWARE. ;;; ;;; ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Author: Alan W Black (awb@cs.cmu.edu) ;;; ;;; Date: December 1999 ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; ;;; Generate a C compilable lts rules. ;;; ;;; ;;; ;;; Two modes, from decision graphs as wfsts or from CART trees ;;; ;;; ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; These are preordained by the LTS building process (set! lts_context_window_size 4) (set! lts_context_extra_feats 1) (define (ltsregextoC name trees idir odir) "(ltsregextoC name idir odir) Converts its wfsts to a C compilation structure for flite. Assumes $idir/[a-z].tree.wfst to compile from." (let ((ofde (fopen (path-append odir (string-append name "_lts_rules.c")) "w")) (ofdm (fopen (path-append odir (string-append name "_lts_model.c")) "w")) (ofdh (fopen (path-append odir (string-append name "_lts_model.h")) "w")) (ifd) (rule_index nil)) (set! lts_pos 0) (set! phone_table (list "epsilon")) (set! letter_table (list "nothing" "#" "0")) (set! letter_table (append letter_table (mapcar car trees))) (format ofde "/*******************************************************/\n") (format ofde "/** Autogenerated lts rules (regex) for %s */\n" name) (format ofde "/** from %s */\n" idir) (format ofde "/*******************************************************/\n") (format ofde "\n") (format ofde "#include \"cst_string.h\"\n") (format ofde "#include \"cst_lts.h\"\n") (format ofde "#include \"cst_lexicon.h\"\n") (format ofdm "/*******************************************************/\n") (format ofdm "/** Autogenerated lts rules (regex) for %s */\n" name) (format ofdm "/** from %s */\n" idir) (format ofdm "/*******************************************************/\n") (format ofdm "\n") (format ofdm "#include \"cst_string.h\"\n") (format ofdm "#include \"cst_lts.h\"\n") (format ofdm "#include \"cst_lexicon.h\"\n") (format ofdm "#include \"%s_lts_model.h\"\n\n" name) (format ofdm "const cst_lts_model %s_lts_model[] = \n" name) (format ofdm "{\n") (set! ln 0) (mapcar (lambda (l) (let ((ifd (fopen (path-append idir (string-append l ".tree.wfst")) "r"))) (format t "doing: %s\n" l) (format ofdm " /** letter \"%s\" **/\n" l) (format ofdh " /** letter \"%s\" **/\n" l) (set! rule_index (cons (list l lts_pos ln) rule_index)) (set! lts_pos (dump_lts_wfst ln ifd ofdm ofdh lts_pos)) (fclose ifd) (set! ln (+ 1 ln)) )) (cdr (cddr letter_table)) ) (format ofdm " 0, 0, 0,0, 0,0\n") (format ofdm "};\n") ;; Make the letter table be the same order as the rule inde (+2) ;; The phone table (bytes to phone names) (format ofde "\n") (format ofde "const char * const %s_lts_phone_table[%d] = \n" name (+ 1 (length phone_table))) (format ofde "{\n") (mapcar (lambda (p) (format ofde " \"%s\",\n" p)) phone_table) (format ofde " NULL\n") (format ofde "};\n") ;; The letter_table (bytes to letter names) (format ofde "\n") (format ofde "const char * const %s_lts_letter_table[%d] = \n" name (+ 1 (length letter_table))) (format ofde "{\n") (mapcar (lambda (p) (format ofde " \"%s\",\n" p)) letter_table) (format ofde " NULL\n") (format ofde "};\n") ;; Which rule starts where (format ofde "\n") (format ofde "const cst_lts_addr %s_lts_letter_index[%d] = \n" name (+ 1 (length rule_index)) ) (format ofde "{\n") (mapcar (lambda (p) (format ofde " %d, /* %s */\n" (car (cdr p)) (car p))) (reverse rule_index)) (format ofde " 0\n") (format ofde "};\n") (format ofde "\n") ; (format ofde "const cst_lts_rules %s_lts_rules = {\n" name) ; (format ofde " \"%s\",\n" name) ; (format ofde " %s_lts_letter_index,\n" name) ; (format ofde " %s_lts_model,\n" name) ; (format ofde " %s_lts_phone_table,\n" name) ; (format ofde " 4, /* context_window_size */\n") ; (format ofde " 1, /* context_extra_feats */\n") ; (format ofde " %s_lts_letter_table\n" name) ; (format ofde "};\n") ; (format ofde "\n") (fclose ofde) (fclose ofdh) (fclose ofdm) )) (define (dump_lts_wfst ln ifd ofde ofdh lts_pos) "(dump_lts_wfst ifd ofde ofdh lts_pos) Dump the WFST as a byte table to ifd. Jumps are dumped as #define's to ofdh so forward references work. lts_pos is the rule position. Each state is saves as feature value true_addr false_addr Feature and value are single bytes, which addrs are double bytes." (let ((state)) ;; Skip WFST header (while (not (string-equal (set! state (readfp ifd)) "EST_Header_End")) (if (equal? state (eof-val)) (error "eof in lts regex file"))) (while (not (equal? (set! state (readfp ifd)) (eof-val))) (format ofdh "#define LTS_STATE_%d_%d %s\n" ln (car (car state)) (lts_bytify lts_pos)) (cond ((string-equal "final" (car (cdr (car state)))) (set! lts_pos (- lts_pos 1)) t) ;; do nothing ((string-matches (car (car (cdr state))) ".*_.*") (format ofde " %s, '%s', %s , %s , \n" (lts_feat (car (car (cdr state)))) (lts_val (car (car (cdr state)))) ; (lts_phone (lts_letter (car (car (cdr state)))) 0 letter_table) (format nil "LTS_STATE_%d_%d" ln (car (cdr (cdr (car (cdr (cdr state))))))) (format nil "LTS_STATE_%d_%d" ln (car (cdr (cdr (car (cdr state)))))))) (t ;; its a letter output state (format ofde " 255, %s, 0,0 , 0,0 , \n" (lts_phone (car (car (cdr state))) 0 phone_table)))) (set! lts_pos (+ 1 lts_pos))) lts_pos)) (define (lts_feat trans) "(lts_feat trans) Returns the feature number represented in this transition name." (let ((fname (substring trans 5 (- (length trans) 11)))) (if (string-matches fname ".*_i?") (set! fname (string-before fname "_"))) (cond ((string-equal fname "p.p.p.p.name") 0) ((string-equal fname "p.p.p.name") 1) ((string-equal fname "p.p.name") 2) ((string-equal fname "p.name") 3) ((string-equal fname "n.name") 4) ((string-equal fname "n.n.name") 5) ((string-equal fname "n.n.n.name") 6) ((string-equal fname "n.n.n.n.name") 7) (t (error (format nil "ltsregex2C: unknown feat %s %s\n" fname trans )))))) (define (lts_letter trans) "(lts_val trans) The letter being tested." (string-before (string-after trans "is_") "_")) (define (lts_val trans) "(lts_val trans) The letter being tested." (substring trans (- (length trans) 2) 1)) (define (lts_phone p n table) (cond ((string-equal p (car table)) n) ((not (cdr table)) ;; new p (set-cdr! table (list p)) (+ 1 n)) (t (lts_phone p (+ 1 n) (cdr table))))) (define (lts_bytify n) "(lts_bytify n) Return this short as a two byte comma separated string." (let ((xx (format nil "%04x" n))) ;; This is unfortunately byte order specific (format nil "0x%s,0x%s" (substring xx 2 2) (substring xx 0 2)))) (provide 'make_lts)