cit_util/src/SIsuffix.m3


  Copyright (c) 2000 California Institute of Technology                    
  All rights reserved.                                                     
  Department of Computer Science                                           
  Pasadena, CA 91125.                                                      
                                                                           
  Author: Mika Nystrom <mika@cs.caltech.edu>                               
                                                                           
  Permission to use, copy, modify, and distribute this software            
  and its documentation for any purpose and without fee is hereby          
  granted, provided that the above copyright notice appear in all          
  copies. The California Institute of Technology makes no representations  
  about the suitability of this software for any purpose. It is            
  provided as is without express or implied warranty. Export of this     
  software outside of the United States of America may require an          
  export license.                                                          
                                                                           
 $Id: SIsuffix.m3.html,v 1.3 2010-04-29 17:17:56 wagner Exp $ 

MODULE SIsuffix;
IMPORT Text;
IMPORT Scan;
IMPORT SuffixTbl;
IMPORT Lex, FloatMode;

PROCEDURE Int(text : TEXT; mode : Mode) : INTEGER RAISES { OutOfRange, UnknownSuffix, FloatMode.Trap, Lex.Error } =
  CONST
    firstInt = FLOAT(FIRST(INTEGER), LONGREAL);
    lastInt =  FLOAT(LAST(INTEGER),  LONGREAL);
  VAR
    longReal := LongReal(text,mode);
  BEGIN
    IF longReal < firstInt OR longReal > lastInt THEN RAISE OutOfRange END;
    RETURN ROUND(longReal)
  END Int;

PROCEDURE Real(text : TEXT; mode : Mode) : REAL RAISES { UnknownSuffix, FloatMode.Trap, Lex.Error } =
  VAR
    longReal := LongReal(text,mode);
  BEGIN
    RETURN FLOAT(longReal, REAL);
  END Real;

PROCEDURE LongReal(text : TEXT; mode : Mode) : LONGREAL RAISES { UnknownSuffix, FloatMode.Trap, Lex.Error } =
  VAR
    len := Text.Length(text);
    suf := Text.GetChar(text, len - 1);
    pre := Text.Sub(text, 0, len - 1);
    val : LONGREAL;
    mult : T;
  BEGIN

    (* first check for no suffix *)
    IF suf = '.' OR (suf >= '0' AND suf <= '9') THEN
      RETURN Scan.LongReal(text)
    END;

    (* has a suffix.  Scan prefix as a number *)
    val := Scan.LongReal(pre);
    IF NOT tbl.get(suf,mult) THEN
      RAISE UnknownSuffix
    ELSE
      IF mode = Mode.Base10 THEN
        RETURN mult.size * val
      ELSIF mode = Mode.Base2 AND mult.geeky > 0.0d0 THEN
        RETURN mult.geeky * val
      ELSE
        RAISE UnknownSuffix
      END
    END
  END LongReal;

VAR tbl := NEW(SuffixTbl.Default).init();

BEGIN

  List := ARRAY OF T {
    T { 'a' , 1.0d-18, "atto" } ,
    T { 'f' , 1.0d-15, "femto" } ,
    T { 'p' , 1.0d-12, "pico" } ,
    T { 'n' , 1.0d-9 , "nano" } ,
    T { 'u' , 1.0d-6 , "micro" } ,
    T { 'm' , 1.0d-3 , "milli" } ,
    T { 'c' , 1.0d-2 , "centi" } ,
    T { 'd' , 1.0d-1 , "deci" } ,
    T { 'D' , 1.0d1  , "deka" } ,
    T { 'h' , 1.0d2  , "hecto" } ,
    T { 'k' , 1.0d3  , "kilo", KiloGeek } ,
    T { 'M' , 1.0d6  , "mega", KiloGeek * KiloGeek } ,
    T { 'G' , 1.0d9  , "giga", KiloGeek * KiloGeek * KiloGeek } ,
    T { 'T' , 1.0d12 , "tera", KiloGeek * KiloGeek * KiloGeek * KiloGeek } ,
    T { 'P' , 1.0d15 , "peta",
        KiloGeek * KiloGeek * KiloGeek * KiloGeek * KiloGeek } ,
    T { 'E' , 1.0d18 , "exa",
        KiloGeek * KiloGeek * KiloGeek * KiloGeek * KiloGeek * KiloGeek }
  };

  FOR i := FIRST(List) TO LAST(List) DO
    VAR
      x : BOOLEAN;
    BEGIN
      x := tbl.put(List[i].char, List[i]);
      <* ASSERT NOT x *>
    END
  END
END SIsuffix.