<> <> <> <> <<>> <<>> 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 = { <<[cmd: Commander.Handle] RETURNS [result: REF ANY _ NIL, msg: ROPE _ NIL]>> i: INT; < GOTO SyntaxError];>> <> < GOTO SyntaxError];>> 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. <> <> <> <> <> <> <<>> <> <> <<>>