|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.