485 lines · 13.1 KB · Text
RawDownload
{open Fnlib Memory Config Mixture Const Parser; (* For Quote/Antiquote --- object language embedding. *) val quotation = ref false datatype lexingMode =    NORMALlm  | QUOTElm  | ANTIQUOTElm val lexingMode = ref NORMALlm val parCount = Stack.new() : int Stack.t fun resetLexerState() =(  lexingMode := NORMALlm;  Stack.clear parCount) (* For nesting comments *) val comment_depth = ref 0 (* The table of keywords *) val keyword_table = (Hasht.new 53 : (string,token) Hasht.t) val () =List.app (fn (str,tok) => Hasht.insert keyword_table str tok)[  ("abstype",      ABSTYPE),  ("and",          AND),  ("andalso",      ANDALSO),  ("as",           AS),  ("case",         CASE),  ("datatype",     DATATYPE),  ("do",           DO),  ("else",         ELSE),  ("eqtype",       EQTYPE),  ("end",          END),  ("exception",    EXCEPTION),  ("fn",           FN),  ("fun",          FUN),  ("functor",      FUNCTOR),  ("handle",       HANDLE),  ("if",           IF),  ("in",           IN),  ("include",      INCLUDE),  ("infix",        INFIX),  ("infixr",       INFIXR),  ("let",          LET),  ("local",        LOCAL),  ("nonfix",       NONFIX),  ("of",           OF),  ("op",           OP),  ("open",         OPEN),  ("orelse",       ORELSE),  ("prim_eqtype",  PRIM_EQTYPE),  ("prim_EQtype",  PRIM_REFTYPE),  ("prim_type",    PRIM_TYPE),  ("prim_val",     PRIM_VAL),  ("raise",        RAISE),  ("rec",          REC),  ("sharing",      SHARING),  ("sig",          SIG),  ("signature",    SIGNATURE),  ("struct",       STRUCT),  ("structure",    STRUCTURE),  ("then",         THEN),  ("type",         TYPE),  ("val",          VAL),  ("where",        WHERE),  ("while",        WHILE),  ("with",         WITH),  ("withtype",     WITHTYPE),  ("#",            HASH),  ("->",           ARROW),  ("|",            BAR),  (":>",           COLONGT),  (":",            COLON),  ("=>",           DARROW),  ("=",            EQUALS),  ("*",            STAR)] fun mkKeyword lexbuf =  let val s = getLexeme lexbuf in    Hasht.find keyword_table s    handle Subscript => ID s  end val savedLexemeStart = ref 0 val initial_string_buffer = CharArray.array(256, #"\000")val string_buff = ref initial_string_bufferval string_index = ref 0 fun reset_string_buffer() =(  string_buff := initial_string_buffer;  string_index := 0;  ()) fun store_string_char c =  let open CharArray      val len = length (!string_buff)  in    if !string_index >= len then      let val new_buff = array(len * 2, #"\000") in        copy          { src = !string_buff, si = 0, len = NONE, dst = new_buff, di = 0 };        string_buff := new_buff      end    else ();    update(!string_buff, !string_index, c);    incr string_index  end fun get_stored_string() =  let open CharArray      val s = extract(!string_buff, 0, SOME (!string_index))  in    string_buff := initial_string_buffer;    s  end (*fun splitQualId s =  let open CharVector      val len' = size s - 1      fun parse n =        if n >= len' then          ("", s)        else if sub(s, n) = #"." then          ( normalizedUnitName (extract(s, 0, SOME n)),            extract(s, n + 1, SOME(len' - n)) )        else          parse (n+1)  in parse 0 end*) (* cvr: NOTE normalizeUnitName done elsewhere now *)fun splitQualId s =  let open CharVector      val len' = size s      fun parse i n acc =        if n >= len' then          (extract(s, i, SOME (len' - i)) :: acc)        else if sub(s, n) = #"." then          parse (n+1) (n+1) ((extract(s, i, SOME (n - i)))::acc)        else          parse i (n+1) acc  in parse 0 0 [] end   fun mkQualId lexbuf =  let val  id = splitQualId(getLexeme lexbuf) in    if id = ["*"] then      QUAL_STAR { qual="", id=id }    else      QUAL_ID   { qual="", id=id }  end fun charCodeOfDecimal lexbuf i =  100 * (Char.ord(getLexemeChar lexbuf i) - 48) +   10 * (Char.ord(getLexemeChar lexbuf (i+1)) - 48) +        (Char.ord(getLexemeChar lexbuf (i+2)) - 48)  fun charCodeOfHexadecimal lexbuf i =    let fun hexval c = 	    if #"0" <= c andalso c <= #"9" then Char.ord c - 48	    else (Char.ord c - 55) mod 32;    in        4096 * hexval(getLexemeChar lexbuf (i+1)) +        256 * hexval(getLexemeChar lexbuf (i+2)) +         16 * hexval(getLexemeChar lexbuf (i+3)) +              hexval(getLexemeChar lexbuf (i+4))     end fun lexError msg lexbuf =(  resetLexerState();  raise LexicalError(msg, getLexemeStart lexbuf, getLexemeEnd lexbuf)) fun constTooLarge msg lexbuf =(  resetLexerState();  lexError (msg ^ " constant is too large") lexbuf) prim_val sml_word_of_string    : string -> word = 1 "sml_word_of_dec"prim_val sml_word_of_hexstring : string -> word = 1 "sml_word_of_hex" fun notTerminated msg lexbuf =(  resetLexerState();  raise LexicalError (msg ^ " not terminated",                      !savedLexemeStart, getLexemeEnd lexbuf)) fun skipString msg skip lexbuf =  let    val pos1 = getLexemeStart lexbuf    val pos2 = getLexemeEnd lexbuf  in    skip lexbuf;    resetLexerState();    raise (LexicalError(msg, pos1, pos2))  end fun scanString scan lexbuf =(  reset_string_buffer();  savedLexemeStart := getLexemeStart lexbuf;  scan lexbuf;  setLexStartPos lexbuf (!savedLexemeStart - getLexAbsPos lexbuf)) } rule Token = parse    [^ `\000`-`\255`]      { lexError "this will be never called!" lexbuf }  | ""      { case !lexingMode of            NORMALlm =>              TokenN lexbuf          | QUOTElm =>              (scanString Quotation lexbuf;               case !lexingMode of                   NORMALlm =>                     QUOTER (get_stored_string())                 | ANTIQUOTElm =>                     QUOTEM (get_stored_string())                 | QUOTElm =>                     fatalError "Token")          | ANTIQUOTElm =>              AntiQuotation lexbuf      } and TokenN = parse    [` ` `\n` `\r` `\t` `\^L`]  { TokenN lexbuf }  | "(*"      { savedLexemeStart := getLexemeStart lexbuf;        comment_depth := 1; Comment lexbuf; TokenN lexbuf      }  | "*)"      { lexError "unmatched comment bracket" lexbuf }  | "'" [ `A`-`Z` `a`-`z` `0`-`9` `_` `'`]+                { TYVAR   (getLexeme lexbuf) }  | "0"         { ZDIGIT 0 }  | [`1`-`9`]   { NZDIGIT   (sml_int_of_string(getLexeme lexbuf)) }  | "0" [`0`-`9`]+                { ZPOSINT2  (sml_int_of_string(getLexeme lexbuf))                  handle Fail _ => constTooLarge "integer" lexbuf                }  | [`1`-`9`] [`0`-`9`]+                { NZPOSINT2 (sml_int_of_string(getLexeme lexbuf))                  handle Fail _ => constTooLarge "integer" lexbuf                }  | "~" [`0`-`9`]+                { NEGINT    (sml_int_of_string(getLexeme lexbuf))                  handle Fail _ => constTooLarge "integer" lexbuf                }  | "~"? "0x" [`0`-`9` `a`-`f` `A`-`F`]+                { NEGINT    (sml_hex_of_string(getLexeme lexbuf))                  handle Fail _ => constTooLarge "integer" lexbuf                }  | "0w" [`0`-`9`]+                { WORD (sml_word_of_string(getLexeme lexbuf))                  handle Fail _ => constTooLarge "word" lexbuf                }  | "0wx" [`0`-`9` `a`-`f` `A`-`F`]+                { WORD (sml_word_of_hexstring(getLexeme lexbuf))                  handle Fail _ => constTooLarge "word" lexbuf                }  | "~"? [`0`-`9`]+ (`.` [`0`-`9`]+)? ([`e` `E`] `~`? [`0`-`9`]+)?                { REAL (sml_float_of_string (getLexeme lexbuf))                  handle Fail _ => constTooLarge "real" lexbuf                }  | "\""      { scanString String lexbuf;        STRING (get_stored_string())      }  | "#\""      { scanString String lexbuf;        let val s = get_stored_string() in          if size s <> 1 then            lexError "ill-formed character constant" lexbuf          else ();          CHAR (CharVector.sub(s, 0))        end }  | "_"         { UNDERBAR }  | ","         { COMMA }  | "..."       { DOTDOTDOT }  | "{"         { LBRACE }  | "}"         { RBRACE }  | "["         { LBRACKET }  | "#["        { HASHLBRACKET }  | "]"         { RBRACKET }  | "("     { if not(Stack.null parCount) then         Stack.push (Stack.pop parCount + 1) parCount       else ();       LPAREN     }  | ")"      { if not(Stack.null parCount) then          let val count = Stack.pop parCount - 1 in            if count = 0 then              (lexingMode := QUOTElm; Token lexbuf)            else              (Stack.push count parCount; RPAREN)          end        else          RPAREN      }  | ";"         { SEMICOLON }  | (eof | `\^Z`) { EOF }  | ""          { if !quotation then TokenIdQ lexbuf else TokenId lexbuf } and TokenId = parse    ( [`A`-`Z` `a`-`z`] [ `A`-`Z` `a`-`z` `0`-`9` `_` `'`]*    | [`!` `%` `&` `$` `#` `+` `-` `/` `:` `<` `=` `>` `?` `@` `\\`       `~` `\`` `^` `|` `*`]+ )      { mkKeyword lexbuf }  | ((  [`A`-`Z` `a`-`z`] [ `A`-`Z` `a`-`z` `0`-`9` `_` `'`]*      | [`!` `%` `&` `$` `#` `+` `-` `/` `:` `<` `=` `>` `?` `@` `\\`        `~` `\`` `^` `|` `*`]+ )      ".")+    ( [`A`-`Z` `a`-`z`] [ `A`-`Z` `a`-`z` `0`-`9` `_` `'`]*    | [`!` `%` `&` `$` `#` `+` `-` `/` `:` `<` `=` `>` `?` `@` `\\`       `~` `\`` `^` `|` `*`]+ )      { mkQualId lexbuf }  | _      { lexError "ill-formed token" lexbuf } and TokenIdQ = parse    ( [`A`-`Z` `a`-`z`] [ `A`-`Z` `a`-`z` `0`-`9` `_` `'`]*    | [`!` `%` `&` `$` `#` `+` `-` `/` `:` `<` `=` `>` `?` `@` `\\`       `~` `^` `|` `*`]+ )      { mkKeyword lexbuf }  | ((  [`A`-`Z` `a`-`z`] [ `A`-`Z` `a`-`z` `0`-`9` `_` `'`]*      | [`!` `%` `&` `$` `#` `+` `-` `/` `:` `<` `=` `>` `?` `@` `\\`        `~` `^` `|` `*`]+ )     ".")+    ( [`A`-`Z` `a`-`z`] [ `A`-`Z` `a`-`z` `0`-`9` `_` `'`]*    | [`!` `%` `&` `$` `#` `+` `-` `/` `:` `<` `=` `>` `?` `@` `\\`       `~` `^` `|` `*`]+ )      { mkQualId lexbuf }  | "`"      { lexingMode := QUOTElm; QUOTEL }  | _      { lexError "ill-formed token" lexbuf } and Comment = parse    "(*"      { (incr comment_depth; Comment lexbuf) }  | "*)"      { (decr comment_depth;         if !comment_depth > 0 then Comment lexbuf else ()) }  | (eof | `\^Z`)      { notTerminated "comment" lexbuf }  | _      { Comment lexbuf } and String = parse    `"`      { () }  | `\\` [`\\` `"` `a` `b` `t` `n` `v` `f` `r`]      { store_string_char(char_for_backslash(getLexemeChar lexbuf 1));        String lexbuf }  | `\\` [` ` `\t` `\n` `\r`]+ `\\`      { String lexbuf }  | `\\` `^` [`@`-`_`]      { store_string_char(          Char.chr(Char.ord(getLexemeChar lexbuf 2) - 64));        String lexbuf }  | `\\` [`0`-`9`] [`0`-`9`] [`0`-`9`]      { let val code = charCodeOfDecimal lexbuf 1 in          if code >= 256 then            skipString "character code is too large" SkipString lexbuf          else ();          store_string_char(Char.chr code);          String lexbuf        end }  | "\\u" [`0`-`9``a`-`f``A`-`F`] [`0`-`9``a`-`f``A`-`F`]           [`0`-`9``a`-`f``A`-`F`] [`0`-`9``a`-`f``A`-`F`]      { let val code = charCodeOfHexadecimal lexbuf 1 in          if code >= 256 then            skipString "character code is too large" SkipString lexbuf          else ();          store_string_char(Char.chr code);          String lexbuf        end }  | `\\`      { skipString "ill-formed escape sequence" SkipString lexbuf }  | (eof | `\^Z`)      { notTerminated "string" lexbuf }  | [`\n` `\r`]      { skipString "newline not permitted in string" SkipString lexbuf }  | [`\^A`-`\^Z` `\127` `\255`]      { skipString "invalid character in string" SkipString lexbuf }  | _      { (store_string_char(getLexemeChar lexbuf 0);         String lexbuf) } and SkipString = parse    `"`      { () }  | `\\` [`\\` `"` `n` `t`]      { SkipString lexbuf }  | `\\` [` ` `\t` `\n` `\r`]+ `\\`      { SkipString lexbuf }  | (eof | `\^Z`)      { notTerminated "string" lexbuf }  | _      { SkipString lexbuf } and Quotation = parse    "`"      { lexingMode := NORMALlm }  | `^`      { lexingMode := ANTIQUOTElm }  | `\r`      { Quotation lexbuf }  | [`\t` `\n`]      { (store_string_char(getLexemeChar lexbuf 0);         Quotation lexbuf) }  | (eof | `\^Z`)      { lexingMode := NORMALlm;        notTerminated "quotation" lexbuf      }  | [`\^A`-`\^Z` `\127` `\255`]      { skipString "invalid character in quotation" SkipQuotation lexbuf }  | _      { (store_string_char(getLexemeChar lexbuf 0);         Quotation lexbuf) } and SkipQuotation = parse    "`"      { lexingMode := NORMALlm }  | (eof | `\^Z`)      { lexingMode := NORMALlm;        notTerminated "quotation" lexbuf      }  | _      { SkipQuotation lexbuf } and AntiQuotation = parse    ( [`A`-`Z` `a`-`z`] [ `A`-`Z` `a`-`z` `0`-`9` `_` `'`]*    | [`!` `%` `&` `$` `#` `+` `-` `/` `:` `<` `=` `>` `?` `@` `\\`       `~` `|` `*`]+ )      { lexingMode := QUOTElm;        mkKeyword lexbuf      }  | "("      { Stack.push 1 parCount; lexingMode := NORMALlm;        TokenN lexbuf      }  | "`"      { lexingMode := NORMALlm;        lexError "antiquotation is missing" lexbuf      }  | (eof | `\^Z`)      { lexingMode := NORMALlm;        notTerminated "antiquotation" lexbuf      }  | _      { lexingMode := QUOTElm;        lexError "ill-formed antiquotation" lexbuf      };