Annotation of researchv10no/cmd/sml/lib/lexgen/lexgen.sml, revision 1.1

1.1     ! root        1: (*  Lexical analyzer generator for Standard ML.
        !             2:         Version 1.1, February 1989
        !             3: 
        !             4: Copyright (c) 1989 by Andrew W. Appel, James S. Mattson, David R. Tarditi
        !             5: 
        !             6: This software comes with ABSOLUTELY NO WARRANTY.
        !             7: This software is subject only to the PRINCETON STANDARD ML SOFTWARE LIBRARY
        !             8: COPYRIGHT NOTICE, LICENSE AND DISCLAIMER, (in the file "COPYRIGHT",
        !             9: distributed with this software). You may copy and distribute this software;
        !            10: see the COPYRIGHT NOTICE for details and restrictions.
        !            11: 
        !            12:     Changes:
        !            13:        7/25/89(drt): added %header declaration, code to place
        !            14:                      user declarations at same level as makeLexer, etc.
        !            15:                      This is needed for the parser generator.
        !            16: 
        !            17:        10/89(awa):   added %arg declaration (see lexgen.doc).
        !            18: *)
        !            19: 
        !            20: functor RedBlack(B : sig type key
        !            21:                         val > : key*key->bool
        !            22:                     end):
        !            23:            sig type tree
        !            24:                type key
        !            25:                val empty : tree
        !            26:                val insert : key * tree -> tree
        !            27:                val lookup : key * tree -> key
        !            28:                exception notfound of key
        !            29:            end =
        !            30: struct
        !            31:  open B
        !            32:  datatype color = RED | BLACK
        !            33:  datatype tree = empty | tree of key * color * tree * tree
        !            34:  exception notfound of key
        !            35: 
        !            36:  fun insert (key,t) =
        !            37:   let fun f empty = tree(key,RED,empty,empty)
        !            38:         | f (tree(k,BLACK,l,r)) =
        !            39:            if key>k
        !            40:            then case f r
        !            41:                 of r as tree(rk,RED, rl as tree(rlk,RED,rll,rlr),rr) =>
        !            42:                        (case l
        !            43:                         of tree(lk,RED,ll,lr) =>
        !            44:                                tree(k,RED,tree(lk,BLACK,ll,lr),
        !            45:                                           tree(rk,BLACK,rl,rr))
        !            46:                          | _ => tree(rlk,BLACK,tree(k,RED,l,rll),
        !            47:                                                tree(rk,RED,rlr,rr)))
        !            48:                  | r as tree(rk,RED,rl, rr as tree(rrk,RED,rrl,rrr)) =>
        !            49:                        (case l
        !            50:                         of tree(lk,RED,ll,lr) =>
        !            51:                                tree(k,RED,tree(lk,BLACK,ll,lr),
        !            52:                                           tree(rk,BLACK,rl,rr))
        !            53:                          | _ => tree(rk,BLACK,tree(k,RED,l,rl),rr))
        !            54:                  | r => tree(k,BLACK,l,r)
        !            55:            else if k>key
        !            56:            then case f l
        !            57:                 of l as tree(lk,RED,ll, lr as tree(lrk,RED,lrl,lrr)) =>
        !            58:                        (case r
        !            59:                         of tree(rk,RED,rl,rr) =>
        !            60:                                tree(k,RED,tree(lk,BLACK,ll,lr),
        !            61:                                           tree(rk,BLACK,rl,rr))
        !            62:                          | _ => tree(lrk,BLACK,tree(lk,RED,ll,lrl),
        !            63:                                                tree(k,RED,lrr,r)))
        !            64:                  | l as tree(lk,RED, ll as tree(llk,RED,lll,llr), lr) =>
        !            65:                        (case r
        !            66:                         of tree(rk,RED,rl,rr) =>
        !            67:                                tree(k,RED,tree(lk,BLACK,ll,lr),
        !            68:                                           tree(rk,BLACK,rl,rr))
        !            69:                          | _ => tree(lk,BLACK,ll,tree(k,RED,lr,r)))
        !            70:                  | l => tree(k,BLACK,l,r)
        !            71:            else tree(key,BLACK,l,r)
        !            72:         | f (tree(k,RED,l,r)) =
        !            73:            if key>k then tree(k,RED,l, f r)
        !            74:            else if k>key then tree(k,RED, f l, r)
        !            75:            else tree(key,RED,l,r)
        !            76:    in case f t
        !            77:       of tree(k,RED, l as tree(_,RED,_,_), r) => tree(k,BLACK,l,r)
        !            78:        | tree(k,RED, l, r as tree(_,RED,_,_)) => tree(k,BLACK,l,r)
        !            79:        | t => t
        !            80:   end
        !            81: 
        !            82: 
        !            83:  fun lookup (key,t) =
        !            84:   let fun look empty = raise (notfound key)
        !            85:        | look (tree(k,_,l,r)) =
        !            86:                if k>key then look l
        !            87:                else if key>k then look r
        !            88:                else k
        !            89:    in look t
        !            90:   end
        !            91: 
        !            92: end
        !            93: 
        !            94: signature LEXGEN =
        !            95:   sig
        !            96:      val lexGen: string -> unit
        !            97:   end
        !            98: 
        !            99: structure LexGen: LEXGEN =
        !           100:    struct
        !           101: 
        !           102:    datatype token = CHARS of bool array | QMARK | STAR | PLUS | BAR
        !           103:          | LP | RP | CARAT | DOLLAR | SLASH | STATE of string list
        !           104:          | REPS of int * int | ID of string | ACTION of string
        !           105:          | BOF | EOF | ASSIGN | SEMI | ARROW | LEXMARK | LEXSTATES  |
        !           106:            COUNT | REJECT | FULLCHARSET | STRUCT | HEADER | ARG
        !           107:        
        !           108:    datatype exp = EPS | CLASS of bool array * int | CLOSURE of exp
        !           109:                | ALT of exp * exp | CAT of exp * exp | TRAIL of int
        !           110:                | END of int
        !           111: 
        !           112:    (* flags describing input Lex spec. - unnecessary code is omitted *)
        !           113:    (* if possible *)
        !           114: 
        !           115:    val CharFormat = ref false; 
        !           116:    val UsesTrailingContext = ref false;
        !           117:    val UsesPrevNewLine = ref false;
        !           118:    
        !           119:    (* flags for various bells & whistles that Lex has.  These slow the
        !           120:       lexer down and should be omitted from production lexers (if you
        !           121:       really want speed) *)
        !           122: 
        !           123:    val CountNewLines = ref false;
        !           124:    val HaveReject = ref false;
        !           125: 
        !           126:    (* Can increase size of character set *)
        !           127: 
        !           128:    val CharSetSize = ref 128;
        !           129: 
        !           130:    (* Can name structure or declare header code *)
        !           131:  
        !           132:    val StrName = ref "Mlex"
        !           133:    val HeaderCode = ref ""
        !           134:    val HeaderDecl = ref false
        !           135:    val ArgCode = ref (NONE: string option)
        !           136:    val StrDecl = ref false
        !           137: 
        !           138:    val ResetFlags = fn () => (CountNewLines := false; HaveReject := false;
        !           139:                               CharSetSize := 128; StrName := "Mlex";
        !           140:                                HeaderCode := ""; HeaderDecl:= false;
        !           141:                                ArgCode := NONE;
        !           142:                                StrDecl := false)
        !           143: 
        !           144:    val LexOut = ref(std_out);
        !           145:    val say = fn x => output (!LexOut) x
        !           146: 
        !           147: (* Union: merge two sorted lists of integers *)
        !           148: 
        !           149: fun union(a,b) = let val rec merge = fn
        !           150:          (nil,nil,z) => z
        !           151:        | (nil,el::more,z) => merge(nil,more,el::z)
        !           152:        | (el::more,nil,z) => merge(more,nil,el::z)
        !           153:        | (x::morex,y::morey,z) => if (x:int)=(y:int)
        !           154:                then merge(morex,morey,x::z)
        !           155:                else if x>y then merge(morex,y::morey,x::z)
        !           156:                else merge(x::morex,morey,y::z)
        !           157:        in merge(rev a,rev b,nil)
        !           158: end
        !           159: 
        !           160: (* Nullable: compute if a important expression parse tree node is nullable *)
        !           161: 
        !           162: val rec nullable = fn
        !           163:          EPS => true
        !           164:        | CLASS(_) => false
        !           165:        | CLOSURE(_) => true
        !           166:        | ALT(n1,n2) => nullable(n1) orelse nullable(n2)
        !           167:        | CAT(n1,n2) => nullable(n1) andalso nullable(n2)
        !           168:        | TRAIL(_) => true
        !           169:        | END(_) => false
        !           170: 
        !           171: (* FIRSTPOS: firstpos function for parse tree expressions *)
        !           172: 
        !           173: and firstpos = fn
        !           174:          EPS => nil
        !           175:        | CLASS(_,i) => [i]
        !           176:        | CLOSURE(n) => firstpos(n)
        !           177:        | ALT(n1,n2) => union(firstpos(n1),firstpos(n2))
        !           178:        | CAT(n1,n2) => if nullable(n1) then union(firstpos(n1),firstpos(n2))
        !           179:                else firstpos(n1)
        !           180:        | TRAIL(i) => [i]
        !           181:        | END(i) => [i]
        !           182: 
        !           183: (* LASTPOS: Lastpos function for parse tree expressions *)
        !           184: 
        !           185: and lastpos = fn
        !           186:          EPS => nil
        !           187:        | CLASS(_,i) => [i]
        !           188:        | CLOSURE(n) => lastpos(n)
        !           189:        | ALT(n1,n2) => union(lastpos(n1),lastpos(n2))
        !           190:        | CAT(n1,n2) => if nullable(n2) then union(lastpos(n1),lastpos(n2))
        !           191:                else lastpos(n2)
        !           192:        | TRAIL(i) => [i]
        !           193:        | END(i) => [i]
        !           194:        ;
        !           195: 
        !           196: (* ++: Increment an integer reference *)
        !           197: 
        !           198: fun ++(x) : int = (x := !x + 1; !x);
        !           199: 
        !           200: structure dict =
        !           201:     struct
        !           202:        type 'a relation = 'a * 'a -> bool
        !           203:         abstype ('b,'a) dictionary = DATA of { Table : ('b * 'a) list,
        !           204:                                          Leq : 'b * 'b -> bool }
        !           205:        with
        !           206:            exception LOOKUP
        !           207:            fun create Leqfunc = DATA { Table = nil, Leq = Leqfunc }
        !           208:            fun lookup (DATA { Table = entrylist, Leq = leq }) key =
        !           209:                let fun search [] = raise LOOKUP
        !           210:                      | search((k,item)::entries) =
        !           211:                        if leq(key,k)
        !           212:                        then if leq(k,key) then item else raise LOOKUP
        !           213:                        else search entries
        !           214:                in search entrylist
        !           215:                end
        !           216:             fun enter (DATA { Table = entrylist, Leq = leq })
        !           217:                (newentry as (key : 'b,item :'a)) : ('b,'a) dictionary =
        !           218:                   let val gt = fn a => fn b => not (leq(a,b))
        !           219:                       val eq = fn k => fn k' => (leq(k,k')) andalso (leq(k',k))
        !           220:                       fun update nil = [ newentry ]
        !           221:                         | update ((entry as (k,_))::entries) =
        !           222:                              if (eq  key k) then newentry::entries
        !           223:                              else if gt k key then newentry::(entry::entries)
        !           224:                              else entry::(update entries)
        !           225:                   in DATA { Table = update entrylist, Leq = leq }
        !           226:                   end
        !           227:             fun listofdict (DATA { Table = entrylist,Leq = leq}) =
        !           228:                let fun f (nil,r) = rev r
        !           229:                      | f (a::b,r) = f (b,a::r)
        !           230:                in f(entrylist,nil)
        !           231:                end
        !           232:       end
        !           233: end
        !           234: 
        !           235: open dict; 
        !           236: 
        !           237: (* INPUT.ML : Input w/ one character push back capability *)
        !           238: 
        !           239: val LineNum = ref 1;
        !           240: 
        !           241: abstype ibuf =
        !           242:        BUF of instream * {b : string ref, p : int ref}
        !           243: with
        !           244:        fun make_ibuf(s) = BUF (s, {b=ref"", p = ref 0})
        !           245:        fun close_ibuf (BUF (s,_)) = close_in(s)
        !           246:        exception eof
        !           247:        fun getch (a as (BUF(s,{b,p}))) = 
        !           248:                 if (!p = (size (!b)))
        !           249:                   then (b := input s (max(1,min(1024,can_input s)));
        !           250:                         p := 0;
        !           251:                         if (size (!b))=0
        !           252:                            then raise eof 
        !           253:                            else getch a)
        !           254:                   else (let val ch = substring(!b,!p,1)
        !           255:                         in (if ch = "\n"
        !           256:                                 then LineNum := !LineNum + 1
        !           257:                                 else ();
        !           258:                             p := !p + 1;
        !           259:                             ch)
        !           260:                         end)
        !           261:        fun ungetch(BUF(s,{b,p})) = (
        !           262:           if substring(!b,!p,1) = "\n"
        !           263:              then LineNum := !LineNum - 1
        !           264:              else ();
        !           265:           p := !p - 1)
        !           266: end;
        !           267: 
        !           268: exception error
        !           269: 
        !           270: val pr_err = fn x => (output std_out ("mlex: syntax error in line "^
        !           271:                            (makestring (!LineNum))^
        !           272:                            ": "^x^"\n"); raise error)
        !           273: 
        !           274: exception syntax_error; (* error in user's input file *)
        !           275: 
        !           276: exception lex_error; (* unexpected error in lexer *)
        !           277: 
        !           278: val LexBuf = ref(make_ibuf(std_in));
        !           279: val LexState = ref 0;
        !           280: val NextTok = ref BOF;
        !           281: val inquote = ref false;
        !           282: 
        !           283: fun AdvanceTok () : unit =
        !           284: 
        !           285: let fun isletter(x:string) = x>="a" andalso x<="z" orelse x>="A" andalso x<="Z";
        !           286: fun isdigit(x:string) = x>="0" andalso x<="9";
        !           287: (* check for valid (non-leading) identifier character (added by JHR) *)
        !           288: fun isidentchr c = (
        !           289:       (isletter c) orelse (isdigit c) orelse (c = "_") orelse (c = "'"))
        !           290: fun atoi(s:string) : int =
        !           291:        let val rec num = fn
        !           292:        (x::y,n) => if isdigit(x) then num(y,10*n+ord(x)-(ord "0")) else n
        !           293:        | (_,n) => n
        !           294: in num(explode(s),0)
        !           295: end;
        !           296: 
        !           297: val rec skipws = fn () => case nextch() of
        !           298:                  " " => skipws()
        !           299:                | "\t" => skipws() 
        !           300:                | "\n" => skipws()
        !           301:                | x => x
        !           302:                
        !           303:        and nextch = fn () => getch(!LexBuf) 
        !           304: 
        !           305:        and escaped = fn () => case nextch() of
        !           306:                  "b" => "\008"
        !           307:                | "n" => "\n"
        !           308:                | "t" => "\t"
        !           309:                | x =>
        !           310:                  let fun f(n,c,t) =
        !           311:                    if c=3 then
        !           312:                        if n>=  (!CharSetSize) then 
        !           313:                           pr_err("illegal ascii escape '"^t^"'")
        !           314:                        else chr n
        !           315:                    else let val ch=nextch()
        !           316:                         in if isdigit ch then
        !           317:                               f(n*10+(ord ch)-(ord "0"),c+1,t^ch)
        !           318:                            else pr_err("illegal ascii escape '"^t^"'")
        !           319:                         end
        !           320:                   in if isdigit x then
        !           321:                        f((ord x)-ord("0"),1,x)
        !           322:                      else x
        !           323:                   end
        !           324:        
        !           325:        and onechar = fn x => let val c = array(!CharSetSize,false) in
        !           326:                update(c,ord(x),true); CHARS(c)
        !           327:                end
        !           328:                
        !           329:        in case !LexState of 0 => let val makeTok = fn () =>
        !           330:                case skipws() of
        !           331:                        (* Lex % operators *)
        !           332:                  "%" => (case nextch() of 
        !           333:                          "%" => LEXMARK
        !           334:                        | a => let fun f s =
        !           335:                                    let val a = nextch()
        !           336:                                    in if isletter a then f(a::s)
        !           337:                                        else (ungetch(!LexBuf);
        !           338:                                              implode(rev s))
        !           339:                                    end
        !           340:                                val command = f [a]
        !           341:                                in if command = "reject" then REJECT
        !           342:                                   else if command = "count" then COUNT
        !           343:                                   else if command = "full" then FULLCHARSET
        !           344:                                   else if command = "s" then LEXSTATES
        !           345:                                   else if command = "S" then LEXSTATES
        !           346:                                   else if command = "structure" then STRUCT
        !           347:                                   else if command = "header" then HEADER
        !           348:                                   else if command = "arg" then ARG
        !           349:                                   else pr_err "unknown % operator "
        !           350:                                end
        !           351:                             )
        !           352:                        (* semicolon (for end of LEXSTATES) *)
        !           353:                | ";" => SEMI
        !           354:                        (* anything else *)
        !           355:                | ch => if isletter(ch) then
        !           356:                         let fun getID matched =
        !           357:                             let val x = nextch()
        !           358: (**** fix by JHR
        !           359:                             in if isletter(x) orelse isdigit(x) orelse
        !           360:                                    x = "_" orelse x = "'"
        !           361: ****)
        !           362:                             in if (isidentchr x)
        !           363:                                 then getID (x::matched)
        !           364:                                 else (ungetch(!LexBuf); implode(rev matched))
        !           365:                             end
        !           366:                        in ID(getID [ch])
        !           367:                        end
        !           368:                      else (pr_err ("bad character: " ^ ch))
        !           369:        in NextTok := makeTok()
        !           370:        end
        !           371:        | 1 => let val rec makeTok = fn () =>
        !           372:                if !inquote then case nextch() of
        !           373:                        (* inside quoted string *)
        !           374:                  "\\" => onechar(escaped())
        !           375:                | "\"" => (inquote := false; makeTok())
        !           376:                | x => onechar(x)
        !           377:                else case skipws() of
        !           378:                        (* single character operators *)
        !           379:                  "?" => QMARK
        !           380:                | "*" => STAR
        !           381:                | "+" => PLUS
        !           382:                | "|" => BAR
        !           383:                | "(" => LP
        !           384:                | ")" => RP
        !           385:                | "^" => CARAT
        !           386:                | "$" => DOLLAR
        !           387:                | "/" => SLASH
        !           388:                | ";" => SEMI
        !           389:                | "." => let val c = array(!CharSetSize,true) in
        !           390:                                update(c,10,false); CHARS(c)
        !           391:                        end
        !           392:                        (* assign and arrow *)
        !           393:                | "=" => let val c = nextch() in
        !           394:                        if c=">" then ARROW else (ungetch(!LexBuf); ASSIGN)
        !           395:                end
        !           396:                        (* character set *)
        !           397:                | "[" => let val rec classch = fn () => let val x = skipws()
        !           398:                                in if x="\\" then escaped() else x
        !           399:                                end;
        !           400:                        val first = classch();
        !           401:                        val flag = (first<>"^");
        !           402:                        val c = array(!CharSetSize,not flag);
        !           403:                        val rec add = fn x => if x="" then ()
        !           404:                                else update(c,ord(x),flag)
        !           405:                        and range = fn (x,y) =>
        !           406:                                if x>y then (pr_err "bad char. range")
        !           407:                                else let val i = ref(ord(x)) and j = ord(y)
        !           408:                                in while !i<=j do (add(chr(!i)); i := !i + 1)
        !           409:                                end
        !           410:                        and getClass = fn (last) => case classch() of
        !           411:                                  "]" => (add(last); c)
        !           412:                                | "-" => if last<>"" then 
        !           413:                                let val x = classch() in
        !           414:                                        if x="]" then (add(last);add("-"); c)
        !           415:                                        else (range(last,x);getClass(""))
        !           416:                                end
        !           417:                                else getClass("-")
        !           418:                                | x => (add(last); getClass(x))
        !           419:                in CHARS(getClass(if first="^" then "" else first))
        !           420:                end
        !           421:                        (* Start States specification *)
        !           422:                | "<" => let val rec get_state = fn (prev,matched) =>
        !           423:                        case nextch() of
        !           424:                          ">" => matched::prev
        !           425:                        | "," => get_state(matched::prev,"")
        !           426:                        | x => if isletter(x) then get_state(prev,matched^x)
        !           427:                                else (pr_err "bad start state list")
        !           428:                in STATE(get_state(nil,""))
        !           429:                end
        !           430:                        (* {id} or repititions *)
        !           431:                | "{" => let val ch = nextch() in if isletter(ch) then
        !           432:                        let val rec getID = fn (matched) =>
        !           433:                        case nextch() of
        !           434:                          "}" => matched
        !           435: (**** fix by JHR
        !           436:                        | x => if isletter(x) orelse isdigit(x) then
        !           437: ****)
        !           438:                        | x => if (isidentchr x) then
        !           439:                                getID(matched^x)
        !           440:                                else (pr_err "invalid char. class name")
        !           441:                        in ID(getID(ch))
        !           442:                        end
        !           443:                        else if isdigit(ch) then
        !           444:                         let val rec get_r = fn
        !           445:                                (matched,r1) => case nextch() of
        !           446:                                  "}" => let val n = atoi(matched) in
        !           447:                                        if r1 = ~1 then (n,n) else (r1,n)
        !           448:                                        end
        !           449:                                | "," => if r1 = ~1 then get_r("",atoi(matched))
        !           450:                                       else (pr_err "invalid repetitions spec.")
        !           451:                                | x => if isdigit(x) then get_r(matched^x,r1)
        !           452:                               else (pr_err "invalid char in repetitions spec")
        !           453:                         in REPS(get_r(ch,~1))
        !           454:                         end
        !           455:                        else (pr_err "bad repetitions spec")
        !           456:                end
        !           457:                        (* Lex % operators *)
        !           458:                | "%" => if nextch() = "%" then LEXMARK else 
        !           459:                            (ungetch(!LexBuf); onechar ("%"))
        !           460:                        (* backslash escape *)
        !           461:                | "\\" => onechar(escaped())
        !           462:                        (* start quoted string *)
        !           463:                | "\"" => (inquote := true; makeTok())
        !           464:                        (* anything else *)
        !           465:                | ch => onechar(ch)
        !           466:        in NextTok := makeTok()
        !           467:        end
        !           468:        | 2 => NextTok :=
        !           469:             (case skipws()
        !           470:                 of "(" => let fun GetAct (lpct,x) =
        !           471:                           case getch(!LexBuf)
        !           472:                                 of "(" => GetAct (lpct+1,"("::x)
        !           473:                                  | ")" => if lpct = 0 then (implode (rev x))
        !           474:                                                      else GetAct(lpct-1,")"::x)
        !           475:                                  | y => GetAct(lpct,y::x)
        !           476:                        in ACTION (GetAct (0,nil))
        !           477:                        end
        !           478:                 | ";" => SEMI
        !           479:                 | c => (pr_err ("invalid character "^c)))
        !           480:        | _ => raise lex_error
        !           481: end
        !           482: handle eof => NextTok := EOF ;
        !           483: 
        !           484: fun GetTok (_:unit) : token = 
        !           485:        let val t = !NextTok in AdvanceTok(); t
        !           486:        end;
        !           487: val SymTab = ref (create String.<=) : (string,exp) dictionary ref
        !           488: 
        !           489: fun GetExp () : exp =
        !           490: 
        !           491:        let val rec optional = fn e => ALT(EPS,e)
        !           492: 
        !           493:        and newline = fn () => let val c = array(!CharSetSize,false) in
        !           494:                update(c,10,true); c
        !           495:                end
        !           496:        
        !           497:        and endline = fn e => trail(e,CLASS(newline(),0))
        !           498:        
        !           499:        and trail = fn (e1,e2) => CAT(CAT(e1,TRAIL(0)),e2)
        !           500:        
        !           501:        and closure1 = fn e => CAT(e,CLOSURE(e))
        !           502:        
        !           503:        and repeat = fn (min,max,e) => let val rec rep = fn
        !           504:                  (0,0) => EPS
        !           505:                | (0,1) => ALT(e,EPS)
        !           506:                | (0,i) => CAT(rep(0,1),rep(0,i-1))
        !           507:                | (i,j) => CAT(e,rep(i-1,j-1))
        !           508:        in rep(min,max)
        !           509:        end
        !           510:        
        !           511:        and exp0 = fn () => case GetTok() of
        !           512:                  CHARS(c) => exp1(CLASS(c,0))
        !           513:                | LP => let val e = exp0() in
        !           514:                 if !NextTok = RP then
        !           515:                  (AdvanceTok(); exp1(e))
        !           516:                 else (pr_err "missing '('") end
        !           517:                | ID(name) => exp1(lookup(!SymTab)(name))
        !           518:                | _ => raise syntax_error
        !           519:                
        !           520:        and exp1 = fn (e) => case !NextTok of
        !           521:                  SEMI => e
        !           522:                | ARROW => e
        !           523:                | EOF => e
        !           524:                | LP => exp2(e,exp0())
        !           525:                | RP => e
        !           526:                | t => (AdvanceTok(); case t of
        !           527:                          QMARK => exp1(optional(e))
        !           528:                        | STAR => exp1(CLOSURE(e))
        !           529:                        | PLUS => exp1(closure1(e))
        !           530:                        | CHARS(c) => exp2(e,CLASS(c,0))
        !           531:                        | BAR => ALT(e,exp0())
        !           532:                        | DOLLAR => endline(e)
        !           533:                        | SLASH => trail(e,exp0())
        !           534:                        | REPS(i,j) => exp1(repeat(i,j,e))
        !           535:                        | ID(name) => exp2(e,lookup(!SymTab)(name))
        !           536:                        | _ => raise syntax_error)
        !           537:                        
        !           538:        and exp2 = fn (e1,e2) => case !NextTok of
        !           539:                  SEMI => CAT(e1,e2)
        !           540:                | ARROW => CAT(e1,e2)
        !           541:                | EOF => CAT(e1,e2)
        !           542:                | LP => exp2(CAT(e1,e2),exp0())
        !           543:                | RP => CAT(e1,e2)
        !           544:                | t => (AdvanceTok(); case t of
        !           545:                          QMARK => exp1(CAT(e1,optional(e2)))
        !           546:                        | STAR => exp1(CAT(e1,CLOSURE(e2)))
        !           547:                        | PLUS => exp1(CAT(e1,closure1(e2)))
        !           548:                        | CHARS(c) => exp2(CAT(e1,e2),CLASS(c,0))
        !           549:                        | BAR => ALT(CAT(e1,e2),exp0())
        !           550:                        | DOLLAR => endline(CAT(e1,e2))
        !           551:                        | SLASH => trail(CAT(e1,e2),exp0())
        !           552:                        | REPS(i,j) => exp1(CAT(e1,repeat(i,j,e2)))
        !           553:                        | ID(name) => exp2(CAT(e1,e2),lookup(!SymTab)(name))
        !           554:                        | _ => raise syntax_error)
        !           555: in exp0()
        !           556: end;
        !           557: val StateTab = ref(create(String.<=)) : (string,int) dictionary ref 
        !           558: 
        !           559: val StateNum = ref 0;
        !           560: 
        !           561: fun GetStates () : int list =
        !           562: 
        !           563:    let fun add nil sl = sl
        !           564:          | add (x::y) sl = add y (union ([lookup (!StateTab)(x)],sl))
        !           565: 
        !           566:        fun addall i sl = 
        !           567:            if i <= !StateNum then addall (i+2) (union ([i],sl))
        !           568:            else sl
        !           569: 
        !           570:        fun incall (x::y) = (x+1)::incall y
        !           571:          | incall nil = nil
        !           572: 
        !           573:        fun addincs nil = nil
        !           574:          | addincs (x::y) = x::(x+1)::addincs y
        !           575: 
        !           576:        val state_list =
        !           577:           case !NextTok of 
        !           578:             STATE s => (AdvanceTok(); LexState := 1; add s nil)
        !           579:             | _ => addall 1 nil
        !           580:                
        !           581:       in case !NextTok
        !           582:           of CARAT => (LexState := 1; AdvanceTok(); UsesPrevNewLine := true;
        !           583:                        incall state_list)
        !           584:            | _ => addincs state_list
        !           585:       end
        !           586: 
        !           587: val LeafNum = ref ~1;
        !           588: 
        !           589: fun renum(e : exp) : exp =
        !           590:        let val rec label = fn
        !           591:          EPS => EPS
        !           592:        | CLASS(x,_) => CLASS(x,++LeafNum)
        !           593:        | CLOSURE(e) => CLOSURE(label(e))
        !           594:        | ALT(e1,e2) => ALT(label(e1),label(e2))
        !           595:        | CAT(e1,e2) => CAT(label(e1),label(e2))
        !           596:        | TRAIL(i) => TRAIL(++LeafNum)
        !           597:        | END(i) => END(++LeafNum)
        !           598: in label(e)
        !           599: end;
        !           600: 
        !           601: exception parse_error;
        !           602: 
        !           603: fun parse() : (string * (int list * exp) list * ((string,string) dictionary)) =
        !           604:        let val Accept = ref (create String.<=) : (string,string) dictionary ref
        !           605:        val rec ParseRtns = fn l => case getch(!LexBuf) of
        !           606:                  "%" => let val c = getch(!LexBuf) in
        !           607:                           if c="%" then (implode (rev l))
        !           608:                           else ParseRtns(c::"%"::l)
        !           609:                        end
        !           610:                | c => ParseRtns(c::l)
        !           611:        and ParseDefs = fn () =>
        !           612:                (LexState:=0; AdvanceTok(); case !NextTok of
        !           613:                  LEXMARK => ()
        !           614:                | LEXSTATES =>
        !           615:                   let fun f () = (case !NextTok of (ID i) =>
        !           616:                                    (StateTab := enter(!StateTab)(i,++StateNum);
        !           617:                                     ++StateNum; AdvanceTok(); f())
        !           618:                                        | _ => ())
        !           619:                   in AdvanceTok(); f ();
        !           620:                      if !NextTok=SEMI then ParseDefs() else 
        !           621:                        (pr_err "expected ';'")
        !           622:                   end
        !           623:                | ID x => (LexState:=1; AdvanceTok(); if GetTok() = ASSIGN
        !           624:                          then (SymTab := enter(!SymTab)(x,GetExp());
        !           625:                               if !NextTok = SEMI then ParseDefs()
        !           626:                               else (pr_err "expected ';'"))
        !           627:                        else raise syntax_error)
        !           628:                | REJECT => (HaveReject := true; ParseDefs())
        !           629:                | COUNT => (CountNewLines := true; ParseDefs())
        !           630:                | FULLCHARSET => (CharSetSize := 256; ParseDefs())
        !           631:                | HEADER => (LexState := 2; AdvanceTok();
        !           632:                             case GetTok()
        !           633:                             of ACTION s => 
        !           634:                                if (!StrDecl) then
        !           635:                                   (pr_err "cannot have both %s and %header \
        !           636:                                    \declarations")
        !           637:                                else if (!HeaderDecl) then
        !           638:                                   (pr_err "duplicate %header declarations")
        !           639:                                else 
        !           640:                                    (HeaderCode := s; LexState := 0;
        !           641:                                     HeaderDecl := true; ParseDefs())
        !           642:                                | _ => raise syntax_error)
        !           643:                 | ARG => (LexState := 2; AdvanceTok();
        !           644:                             case GetTok()
        !           645:                             of ACTION s => 
        !           646:                                (case !ArgCode
        !           647:                                   of SOME _ => pr_err "duplicate %arg declarations"
        !           648:                                    | NONE => ArgCode := SOME s;
        !           649:                                 LexState := 0;
        !           650:                                 ParseDefs())
        !           651:                                | _ => raise syntax_error)
        !           652:                | STRUCT => (AdvanceTok();
        !           653:                            case !NextTok of
        !           654:                               (ID i) =>
        !           655:                                if (!HeaderDecl) then
        !           656:                                   (pr_err "cannot have both %s and %header \
        !           657:                                    \declarations")
        !           658:                                else if (!StrDecl) then
        !           659:                                   (pr_err "duplicate %s declarations")
        !           660:                                else StrName := i
        !           661:                                 | _  => (pr_err "expected ID");
        !           662:                                ParseDefs())
        !           663:                | _ => raise syntax_error)
        !           664:        and ParseRules =
        !           665:                fn rules => (LexState:=1; AdvanceTok(); case !NextTok of
        !           666:                  LEXMARK => rules
        !           667:                | EOF => rules
        !           668:                | _ =>
        !           669:                 let val s = GetStates()
        !           670:                     val e = renum(CAT(GetExp(),END(0)))
        !           671:                 in
        !           672:                 if !NextTok = ARROW then 
        !           673:                   (LexState:=2; AdvanceTok();
        !           674:                    case GetTok() of ACTION(act) =>
        !           675:                      if !NextTok=SEMI then
        !           676:                        (Accept:=enter(!Accept) (makestring (!LeafNum),act);
        !           677:                         ParseRules((s,e)::rules))
        !           678:                      else (pr_err "expected ';'")
        !           679:                    | _ => raise syntax_error)
        !           680:                  else (pr_err "expected '=>'")
        !           681:                end)
        !           682: in let val usercode = ParseRtns nil
        !           683:    in (ParseDefs(); (usercode,ParseRules(nil),!Accept))
        !           684:    end
        !           685: end handle syntax_error => (pr_err "")
        !           686: 
        !           687: fun makebegin () : unit =
        !           688:    let fun make nil = ()
        !           689:         | make ((x,n:int)::y)=(say "val "; say x; say " = " ;
        !           690:                                say "STARTSTATE ";
        !           691:                                say (makestring n); say ";\n"; make y)
        !           692:    in say "\n(* start state definitions *)\n\n"; make(listofdict(!StateTab))
        !           693:    end
        !           694:                        
        !           695: structure L = 
        !           696:        struct
        !           697:          nonfix >
        !           698:          type key = int list * string
        !           699:          fun > ((key,item:string),(key',item')) =
        !           700:            let fun f ((a:int)::a') (b::b') = if Integer.> (a,b) then true
        !           701:                                           else if a=b then f a' b'
        !           702:                                           else false
        !           703:                  | f _ _ = false
        !           704:            in f key key'
        !           705:            end
        !           706:        end
        !           707: 
        !           708: structure RB = RedBlack(L)
        !           709: 
        !           710: fun maketable (fins:(int * (int list)) list,
        !           711:             tcs :(int * (int list)) list,
        !           712:             tcpairs: (int * int) list,
        !           713:             trans : (int*(int list)) list) : unit =
        !           714: 
        !           715: (* Fins = (state #, list of final leaves for the state) list
        !           716:    tcs = (state #, list of trailing context leaves which begin in this state)
        !           717:         list
        !           718:    tcpairs = (trailing context leaf, end leaf) list
        !           719:    trans = (state #,list of transitions for state) list *)
        !           720: 
        !           721:    let datatype elem = N of int | T of int | D of int
        !           722:        val count = ref 0
        !           723:        val _ = (if length(trans)<256 then CharFormat := true
        !           724:                 else CharFormat := false;
        !           725:                 if length(tcpairs)> 0 then 
        !           726:                    (UsesTrailingContext := true;
        !           727:                     say "\ndatatype yyfinstate = N of int | \
        !           728:                           \ T of int | D of int\n")
        !           729:                 else (UsesTrailingContext := false;
        !           730:                        say "\ndatatype yyfinstate = N of int");
        !           731:                 say "\ntype statedata = {fin : yyfinstate list, trans: ";
        !           732:                 case !CharFormat of
        !           733:                       true => say "string}"
        !           734:                     | false => say "int array}";
        !           735:                 say "\n(* transition & final state table *)\nval tab = let\n")
        !           736:        val newfins =
        !           737:          let fun IsEndLeaf t =
        !           738:             let fun f ((l,e)::r) = if (e=t) then true else f r
        !           739:                   | f nil = false in f tcpairs end
        !           740: 
        !           741:         fun GetEndLeaf t = 
        !           742:           let fun f ((tl,el)::r) = if (tl=t) then el else f r
        !           743:            in f tcpairs
        !           744:           end
        !           745:         fun GetTrConLeaves s =
        !           746:           let fun f ((s',l)::r) = if (s = s') then l else f r
        !           747:                 | f nil = nil
        !           748:           in f tcs
        !           749:           end
        !           750:         fun sort_leaves s =
        !           751:           let fun insert (x:int) (a::b) =
        !           752:                 if (x <= a) then x::(a::b)
        !           753:                 else a::(insert x b)
        !           754:                 | insert x nil = [x]
        !           755:           in fold (fn (x,r) => insert x r) s nil
        !           756:           end
        !           757:         fun conv a = if (IsEndLeaf a) then (D a) else (N a)
        !           758:         fun merge (a::a',b::b') =
        !           759:           if (a <= b) then (conv a)::merge(a',b::b')
        !           760:           else (T b)::(merge(a::a',b'))
        !           761:           | merge (a::a',nil) = (conv a)::(merge (a',nil))
        !           762:           | merge (nil,b::b') = (T b)::(merge (b',nil))
        !           763:           | merge (nil,nil) = nil
        !           764: 
        !           765:        in map (fn (x,l) =>
        !           766:          rev (merge (l,
        !           767:                sort_leaves (map (fn x => GetEndLeaf x) (GetTrConLeaves x)))))
        !           768:                    fins
        !           769:        end
        !           770: 
        !           771:        val rs =
        !           772:         let open RB
        !           773:             fun makeItems x =
        !           774:               let fun MakeList(nil,i) = ()
        !           775:                     | MakeList([(x:int)],i) = say (makestring x)
        !           776:                     | MakeList(x::tl,16) =
        !           777:                       (say "\n"; say (makestring x); say ","; MakeList(tl,1))
        !           778:                     | MakeList(x::tl,i) =
        !           779:                       (say (makestring x); say ","; MakeList(tl,i+1))
        !           780:                   fun MakeString(nil,i) = ()
        !           781:                     | MakeString(((x:int)::tl),i) =
        !           782:                         let val x = (makestring x)
        !           783:                             val x' = (case size x of
        !           784:                                       1 => "00" ^ x | 2 => "0" ^ x | 3 => x)
        !           785:                         in if i=16
        !           786:                            then (say "\\\n\\\\"; say x'; MakeString(tl,1))
        !           787:                            else (say "\\"; say x'; MakeString(tl,i+1))
        !           788:                         end
        !           789:                in case !CharFormat of
        !           790:                    true => (say " =\n\""; MakeString(x,0); say "\"\n")
        !           791:                  | false => (say " = arrayoflist\n["; MakeList(x,0); say "]\n")
        !           792:                end
        !           793:            fun makeEntry(nil,rs,t) = rev rs
        !           794:              | makeEntry(((l:int,x)::y),rs,t) =
        !           795:                  let val name = "s" ^ (makestring l)
        !           796:                  in let val (r,n) = lookup ((x,name),t)
        !           797:                      in makeEntry(y,(n::rs),t)
        !           798:                      end handle notfound _ => (count := !count+1;
        !           799:                         say "val "; say name; makeItems x;
        !           800:                          makeEntry(y,(name::rs),(insert ((x,name),t))))
        !           801:                  end
        !           802:        in (makeEntry(trans,nil,empty))
        !           803:        end
        !           804: 
        !           805:        fun makeTable(nil,nil) = ()
        !           806:          | makeTable(a::a',b::b') =
        !           807:             let fun makeItems nil = ()
        !           808:                   | makeItems (hd::tl) =
        !           809:                     let val (t,n) =
        !           810:                         case hd of
        !           811:                           (N i) => ("(N ",i)
        !           812:                         | (T i) => ("(T ",i)
        !           813:                         | (D i) => ("(D ",i)
        !           814:                     in (say t; say (makestring n); say ")";
        !           815:                         if null tl
        !           816:                         then ()
        !           817:                         else (say ","; makeItems tl))
        !           818:                     end
        !           819:              in (say "{fin = ["; makeItems b;
        !           820:                  say "], trans = "; say a; say "}";
        !           821:                  if null a'
        !           822:                  then ()
        !           823:                  else (say ",\n"; makeTable(a',b')))
        !           824:              end
        !           825: 
        !           826:        fun msg x = output std_out x
        !           827: 
        !           828:   in (say "in arrayoflist\n["; makeTable(rs,newfins); say "]\nend\n";
        !           829:     msg ("\nNumber of states = " ^ (makestring (length trans)));
        !           830:     msg ("\nNumber of distinct rows = " ^ (makestring (!count)));
        !           831:     msg ("\nApprox. memory size of trans. table = " ^
        !           832:          (makestring (!count*(!CharSetSize)*(if !CharFormat then 1 else 8))));
        !           833:     msg " bytes\n")
        !           834: end
        !           835: 
        !           836: (* makeaccept: Takes a (string,string) dictionary, prints case statement for
        !           837:    accepting leaf actions.  The key strings are the leaf #'s, the data strings
        !           838:    are the actions *)
        !           839: 
        !           840: fun makeaccept ends =
        !           841:     let fun startline f = if f then say "  " else say "| "
        !           842:         fun make(nil,f) = (startline f; say "_ => raise Internal.LexerError\n")
        !           843:          | make((x,a)::y,f) = (startline f; say x; say " => (";
        !           844:                                 say a; say ")\n"; make(y,false))
        !           845:     in make (listofdict(ends),true)
        !           846:     end
        !           847:                        
        !           848: fun leafdata(e:(int list * exp) list) =
        !           849:        let val fp = array(!LeafNum + 1,nil)
        !           850:        and leaf = array(!LeafNum + 1,EPS)
        !           851:        and tcpairs = ref nil
        !           852:        and trailmark = ref ~1;
        !           853:        val rec add = fn
        !           854:                  (nil,x) => ()
        !           855:                | (hd::tl,x) => (update(fp,hd,union(fp sub hd,x));
        !           856:                        add(tl,x))
        !           857:        and moredata = fn
        !           858:                  CLOSURE(e1) =>
        !           859:                        (moredata(e1); add(lastpos(e1),firstpos(e1)))
        !           860:                | ALT(e1,e2) => (moredata(e1); moredata(e2))
        !           861:                | CAT(e1,e2) => (moredata(e1); moredata(e2);
        !           862:                        add(lastpos(e1),firstpos(e2)))
        !           863:                | CLASS(x,i) => update(leaf,i,CLASS(x,i))
        !           864:                | TRAIL(i) => (update(leaf,i,TRAIL(i)); if !trailmark = ~1
        !           865:                        then trailmark := i else ())
        !           866:                | END(i) => (update(leaf,i,END(i)); if !trailmark <> ~1
        !           867:                        then (tcpairs := (!trailmark,i)::(!tcpairs);
        !           868:                        trailmark := ~1) else ())
        !           869:                | _ => ()
        !           870:        and makedata = fn
        !           871:                  nil => ()
        !           872:                | (_,x)::tl => (moredata(x);makedata(tl))
        !           873:        in trailmark := ~1; makedata(e); (fp,leaf,!tcpairs)
        !           874:        end;
        !           875:        
        !           876: fun makedfa(rules) =
        !           877: let val StateTab = ref (create(String.<=)) : (string,int) dictionary ref
        !           878:     val fintab = ref (create(Integer.<=)) : (int,(int list)) dictionary ref
        !           879:     val transtab = ref (create(Integer.<=)) : (int,int list) dictionary ref
        !           880:     val tctab = ref (create(Integer.<=)) : (int,(int list)) dictionary ref
        !           881:     val (fp, leaf, tcpairs) = leafdata(rules);
        !           882: 
        !           883: fun visit (state,statenum) =
        !           884:        let val transitions = gettrans(state) in
        !           885:           fintab := enter(!fintab)(statenum,getfin(state));
        !           886:           tctab := enter(!tctab)(statenum,gettc(state));
        !           887:           transtab := enter(!transtab)(statenum,transitions)
        !           888:        end
        !           889:        
        !           890: and visitstarts (states) =
        !           891:        let fun vs nil i = ()
        !           892:              | vs (hd::tl) i = (visit (hd,i); vs tl (i+1))
        !           893:        in vs states 0
        !           894:        end
        !           895:        
        !           896: and hashstate(s: int list) =
        !           897:        let val rec hs =
        !           898:                fn (nil,z) => z
        !           899:                 | ((x:int)::y,z) => hs(y,z ^ " " ^ (makestring x))
        !           900:        in hs(s,"")
        !           901:        end
        !           902:        
        !           903: and find(s) = lookup(!StateTab)(hashstate(s))
        !           904: 
        !           905: and add(s,n) = StateTab := enter(!StateTab)(hashstate(s),n)
        !           906: 
        !           907: and getstate (state) =
        !           908:        find(state)
        !           909:        handle LOOKUP => let val n = ++StateNum in
        !           910:                add(state,n); visit(state,n); n
        !           911:                end
        !           912:                
        !           913: and getfin state =
        !           914:        let fun f nil fins = fins
        !           915:              | f (hd::tl) fins =
        !           916:                 case (leaf sub hd) 
        !           917:                    of END _ => f tl (hd::fins)
        !           918:                     | _ => f tl fins
        !           919:        in f state nil
        !           920:        end
        !           921: 
        !           922: and gettc state =
        !           923:        let fun f nil fins = fins
        !           924:              | f (hd::tl) fins =
        !           925:                 case (leaf sub hd) 
        !           926:                    of TRAIL _ => f tl (hd::fins)
        !           927:                     | _ => f tl fins
        !           928:        in f state nil
        !           929:        end
        !           930: 
        !           931: and gettrans (state) =
        !           932:       let fun loop c tlist =
        !           933:         let fun cktrans nil r = r
        !           934:               | cktrans (hd::tl) r =
        !           935:                  case (leaf sub hd) of
        !           936:                   CLASS(i,_)=>
        !           937:                        (if (i sub c) then cktrans tl (union(r,fp sub hd))
        !           938:                         else cktrans tl r handle Subscript => 
        !           939:                                                cktrans tl r
        !           940:                        )
        !           941:                   | _ => cktrans tl r
        !           942:         in if c >= 0 then
        !           943:              let val v=cktrans state nil
        !           944:              in loop (c-1) (if v=nil then 0::tlist else (getstate v)::tlist)
        !           945:              end
        !           946:            else tlist
        !           947:         end
        !           948:      in loop ((!CharSetSize) - 1) nil
        !           949:      end
        !           950:        
        !           951: and startstates() =
        !           952:        let val startarray = array(!StateNum + 1, nil);
        !           953:             fun listofarray(a,n) =
        !           954:                let fun f i l = if i >= 0 then  f (i-1) ((a sub i)::l) else l
        !           955:                in f (n-1) nil end
        !           956:        val rec makess = fn
        !           957:                  nil => ()
        !           958:                | (startlist,e)::tl => (fix(startlist,firstpos(e));makess(tl))
        !           959:        and fix = fn
        !           960:                  (nil,_) => ()
        !           961:                | (s::tl,firsts) => (update(startarray,s,
        !           962:                        union(firsts,startarray sub s));
        !           963:                        fix(tl,firsts))
        !           964:        in makess(rules);listofarray(startarray, !StateNum + 1)
        !           965:        end
        !           966:        
        !           967: in visitstarts(startstates());
        !           968: (listofdict(!fintab),listofdict(!transtab),listofdict(!tctab),tcpairs)
        !           969: end
        !           970: 
        !           971: val skel_hd = 
        !           972: "   struct\n\
        !           973: \    structure UserDeclarations =\n\
        !           974: \      struct\n\
        !           975: \"
        !           976: 
        !           977: 
        !           978: val skel_mid2 =
        !           979: "                     | Internal.D i =>\n\
        !           980: \                       let val newrs =\n\
        !           981: \                         if (List.exists (fn x => i=x) rs) then rs\n\
        !           982: \                         else i::rs\n\
        !           983: \                       in action (i,(acts::l),newrs)\n\
        !           984: \                       end\n\
        !           985: \                     | Internal.T k =>\n\
        !           986: \                       let fun f (a::b,r) =\n\
        !           987: \                            if a=k\n\
        !           988: \                              then action(i,(((Internal.N a)::acts)::l),(b@r))\n\
        !           989: \                              else f (b,a::r)\n\
        !           990: \                             | f (nil,r) = action(i,(acts::l),rs)\n\
        !           991: \                        in f (rs,nil)\n\
        !           992: \                        end\n\
        !           993: \"
        !           994: 
        !           995: fun lexGen(infile) =
        !           996:     let val outfile = infile ^ ".sml"
        !           997:       fun PrintLexer (ends) =
        !           998:     let val sayln = fn x => (say x; say "\n")
        !           999:      in case !ArgCode 
        !          1000:         of NONE => (sayln "fun lex () : Internal.result =";
        !          1001:                     sayln "let fun continue() = lex() in")
        !          1002:          | SOME s => (say "fun lex "; say "(yyarg as ("; say s; sayln ")) =";
        !          1003:                       sayln "let fun continue() : Internal.result = ");
        !          1004:         say "  let fun scan (s,AcceptingLeaves : Internal.yyfinstate";
        !          1005:         sayln " list list,l,i0) =";
        !          1006:         if !UsesTrailingContext
        !          1007:             then say "\tlet fun action (i,nil,rs)"
        !          1008:             else say "\tlet fun action (i,nil)";
        !          1009:         sayln " = raise LexError";
        !          1010:         if !UsesTrailingContext
        !          1011:             then sayln "\t| action (i,nil::l,rs) = action(i-1,l,rs)"
        !          1012:             else sayln "\t| action (i,nil::l) = action (i-1,l)";
        !          1013:         if !UsesTrailingContext
        !          1014:             then sayln "\t| action (i,(node::acts)::l,rs) ="
        !          1015:             else sayln "\t| action (i,(node::acts)::l) =";
        !          1016:         sayln "\t\tcase node of";
        !          1017:         sayln "\t\t    Internal.N yyk => ";
        !          1018:         sayln "\t\t\t(let val yytext = substring(!yyb,i0,i-i0)";
        !          1019:         if !CountNewLines 
        !          1020:            then (sayln "\t\t\tval _ = yylineno :=";
        !          1021:                  sayln "(fold (fn (x,r) => if x =\"\\n\" then r+1 else r)";
        !          1022:                  sayln "(explode yytext) (!yylineno))")
        !          1023:            else ();
        !          1024:         sayln "\t\t\topen UserDeclarations Internal.StartStates";
        !          1025:         sayln " in (yypos := i; case yyk of ";
        !          1026:         sayln "";
        !          1027:         sayln "\t\t\t(* Application actions *)\n";
        !          1028:         makeaccept(ends);
        !          1029:         say "\n\t\t) end ";
        !          1030:         if !HaveReject
        !          1031:            then (say "handle Reject => action(i,acts::l";
        !          1032:                  if !UsesTrailingContext
        !          1033:                    then say ",rs)" 
        !          1034:                    else say ")")
        !          1035:            else ();
        !          1036:          say ")\n\n";
        !          1037:         if (!UsesTrailingContext) then say skel_mid2 else ();
        !          1038:         sayln "\tval {fin,trans} = Internal.tab sub s";
        !          1039:         sayln "\tval NewAcceptingLeaves = fin::AcceptingLeaves";
        !          1040:         sayln "\tin if l = !yybl then";
        !          1041:         sayln "\t    let val newchars= if !yydone then \"\" else yyinput 1024";
        !          1042:         sayln "\t    in if (size newchars)=0";
        !          1043:         sayln "\t\t  then (yydone := true;";
        !          1044:         say "\t\t        if (l=i0) then UserDeclarations.eof ";
        !          1045:         sayln (case !ArgCode of NONE => "()" | SOME _ => "yyarg");
        !          1046:         say   "\t\t                  else action(l,NewAcceptingLeaves";
        !          1047:         if !UsesTrailingContext then
        !          1048:            sayln ",nil))" else sayln "))";
        !          1049:         sayln "\t\t  else (if i0=l then yyb := newchars";
        !          1050:         sayln "\t\t     else yyb := substring(!yyb,i0,l-i0)^newchars;";
        !          1051:         sayln "\t\t     yybl := size (!yyb);";
        !          1052:         sayln "\t\t     scan (s,AcceptingLeaves,l-i0,0))";
        !          1053:         sayln "\t    end";
        !          1054:         sayln "\t  else let val NewChar = ordof(!yyb,l)";
        !          1055:          (say "\t\tval NewState = ";
        !          1056:           case (!CharFormat)
        !          1057:            of true => sayln "ordof(trans,NewChar)"
        !          1058:             | false => sayln "(trans sub NewChar)");
        !          1059:         say "\t\tin if NewState=0 then action(l,NewAcceptingLeaves";
        !          1060:         if !UsesTrailingContext then sayln ",nil)" else sayln ")";
        !          1061:         sayln "\t\telse scan(NewState,NewAcceptingLeaves,l+1,i0)";
        !          1062:         sayln "\tend";
        !          1063:         sayln "\tend";
        !          1064:         if !UsesPrevNewLine then () else sayln "(*";
        !          1065:         sayln "\tval start= if substring(!yyb,!yypos-1,1)=\"\\n\"";
        !          1066:         sayln "then !yybegin+1 else !yybegin";
        !          1067:         if !UsesPrevNewLine then () else sayln "*)";
        !          1068:         say "\tin scan(";
        !          1069:         if !UsesPrevNewLine then say "start" 
        !          1070:         else say "!yybegin (* start *)";
        !          1071:         sayln ",nil,!yypos,!yypos)";
        !          1072:         sayln "    end";
        !          1073:         sayln (case !ArgCode of NONE => "end" | SOME _ => "in continue end");
        !          1074:         sayln "  in lex";
        !          1075:         sayln "  end";
        !          1076:         sayln "end"
        !          1077:        end
        !          1078: 
        !          1079:     in (UsesPrevNewLine := false;
        !          1080:        ResetFlags();
        !          1081:         LexBuf := make_ibuf(open_in infile);
        !          1082:        LexOut := open_out(outfile);
        !          1083:        StateNum := 2;
        !          1084:        LineNum := 1;
        !          1085:        StateTab := enter(create(String.<=))("INITIAL",1);
        !          1086:        LeafNum := ~1;
        !          1087:        let
        !          1088:           val (user_code,rules,ends) = parse();
        !          1089:           val (fins,trans,tctab,tcpairs) = makedfa(rules)
        !          1090:        in
        !          1091:          if (!HeaderDecl)
        !          1092:              then say (!HeaderCode)
        !          1093:              else say ("structure " ^ (!StrName));
        !          1094:          say "=\n";
        !          1095:          say skel_hd;
        !          1096:          say user_code;
        !          1097:          say "end (* end of user routines *)\n";
        !          1098:          say "exception LexError (* raised if illegal leaf ";
        !          1099:          say "action tried *)\n";
        !          1100:          say "structure Internal =\n\tstruct\n";
        !          1101:          maketable(fins,tctab,tcpairs,trans);
        !          1102:          say "structure StartStates =\n\tstruct\n";
        !          1103:          say "\tdatatype yystartstate = STARTSTATE of int\n";
        !          1104:          makebegin();
        !          1105:          say "\nend\n";
        !          1106:          say "type result = UserDeclarations.lexresult\n";
        !          1107:          say "\texception LexerError (* raised if illegal leaf ";
        !          1108:          say "action tried *)\n";
        !          1109:          if !HaveReject 
        !          1110:            then say "\texception Reject\t(* for implementing REJECT *)\n"
        !          1111:            else ();
        !          1112:          say "end\n\n";
        !          1113:          if !CountNewLines then say "val yylineno = ref 0\n\n" else ();
        !          1114:          say "fun makeLexer yyinput = \n";
        !          1115:          say "let \n";
        !          1116:          say "\tval yyb = ref \"\\n\" \t\t(* buffer *)\n\
        !          1117:          \\tval yybl = ref 1\t\t(*buffer length *)\n\
        !          1118:          \\tval yypos = ref 1\t\t(* location of next character to use *)\n\
        !          1119:          \\tval yydone = ref false\t\t(* eof found yet? *)\n\
        !          1120:          \\tval yybegin = ref 1\t\t(*Current 'start state' for lexer *)\n\
        !          1121:          \\n\tval YYBEGIN = fn (Internal.StartStates.STARTSTATE x) =>\n\
        !          1122:          \\t\t yybegin := x\n\n";
        !          1123:          if !HaveReject
        !          1124:          then say "\tval REJECT = fn () => raise Internal.Reject\n\n"
        !          1125:          else ();
        !          1126:          PrintLexer(ends);
        !          1127:          close_ibuf(!LexBuf);
        !          1128:           close_out(!LexOut)
        !          1129:         end)
        !          1130:     end
        !          1131: end

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.