DIRECTORY Commander USING [Register, CommandProc], CommandTool USING [ArgumentVector, Failed, Parse, NextArgument], Convert USING [Error, IntFromRope], IO USING [PutF, rope], Rope USING [ROPE, Cat, Substr], PrintEnglish; PrintEnglishImpl: CEDAR PROGRAM IMPORTS Commander, CommandTool, Convert, IO, Rope EXPORTS PrintEnglish ~ BEGIN ROPE: TYPE ~ Rope.ROPE; largestMajor: INT = 3; -- the largest INT is in the billions majors: ARRAY [0..21] OF ROPE = [ -- most of these are not currently used, but are included for completeness "", " thousand", " million", " billion", " trillion", " quadrillion", " quintillion", " sextillion", " septillion", " octillion", " nonillion", " decillion", " undecillion", " duodecillion", " tredecillion", " quattuordecillion", " quindecillion", " sexdecillion", " septendecillion", " octodecillion", " novemdecillion", " vigintillion" ]; ones: ARRAY [0..9] OF ROPE = [ " zero", " one", " two", " three", " four", " five", " six", " seven", " eight", " nine" ]; teens: ARRAY [0..9] OF ROPE = [ " ten", " eleven", " twelve", " thirteen", " fourteen", " fifteen", " sixteen", " seventeen", " eighteen", " nineteen" ]; tens: ARRAY [0..9] OF ROPE = [ " zero", " ten", " twenty", " thirty", " forty", " fifty", " sixty", " seventy", " eighty", " ninety" ]; Power: PROC [i: INT, power: INT] RETURNS [INT] ~ { result: INT _ 1; THROUGH [1..power] DO result _ result * i; ENDLOOP; RETURN[result]; }; SmallIntToEnglish: PROC [i: INT] RETURNS [r: ROPE] ~ { digit: INT; r _ NIL; digit _ i/100; IF digit # 0 THEN r _ Rope.Cat[r, ones[digit], " hundred"]; i _ i MOD 100; IF i IN [10..19] THEN { r _ Rope.Cat[r, teens[i-10]]; RETURN; }; digit _ i/10; IF digit # 0 THEN r _ Rope.Cat[r, tens[digit]]; i _ i MOD 10; IF i # 0 THEN r _ Rope.Cat[r, ones[i]]; }; IntToEnglish: PUBLIC PROC [i: INT] RETURNS [r: ROPE] ~ { high: INT; mIndex: INT _ largestMajor; mValue: INT; r _ NIL; WHILE mIndex >= 0 DO mValue _ Power[1000, mIndex]; high _ i / mValue; IF high # 0 THEN { r _ Rope.Cat[r, SmallIntToEnglish[high], majors[mIndex]]; i _ i MOD mValue; }; mIndex _ mIndex -1; ENDLOOP; IF r = NIL THEN r _ " zero"; r _ Rope.Substr[base: r, start: 1]; -- to remove initial blank space }; Number: Commander.CommandProc = { i: INT; i _ Convert.IntFromRope[CommandTool.NextArgument[cmd] ! Convert.Error => GOTO SyntaxError]; IO.PutF[cmd.out, "%g\n", IO.rope[IntToEnglish[i]]]; EXITS SyntaxError => IO.PutF[cmd.err, "Integer not specified.\n"]; }; Commander.Register[key: "Number", proc: Number, doc: "Print out the english equivalent of an integer"]; END. PrintEnglishImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Doug Terry July 8, 1985 2:06:25 pm PDT Doug Terry, March 4, 1986 2:52:29 pm PST Converts integer numbers to their English equivalents. [cmd: Commander.Handle] RETURNS [result: REF ANY _ NIL, msg: ROPE _ NIL] argv: CommandTool.ArgumentVector _ CommandTool.Parse[cmd: cmd ! CommandTool.Failed => GOTO SyntaxError]; IF argv.argc < 2 THEN GOTO SyntaxError; i _ Convert.IntFromRope[argv[1] ! Convert.Error => GOTO SyntaxError]; Doug Terry, February 27, 1986 1:06:05 pm PST changes to: DIRECTORY, PrintEnglishImpl, IMPORTS, EXPORTS, ~, Power, SmallIntToEnglish, IntToEnglish, Number, END Doug Terry, February 27, 1986 1:10:18 pm PST changes to: DIRECTORY, IMPORTS, Number Doug Terry, February 28, 1986 4:27:28 pm PST changes to: IntToEnglish, DIRECTORY Doug Terry, March 4, 1986 2:52:29 pm PST changes to: DIRECTORY, Number ΚJ˜codešœ™Kšœ<™