<<>> <> <> <> <> <> <> <<>> <<>> DIRECTORY Commander USING [Register, CommandProc], CommanderOps USING [<> NextArgument], Convert USING [Error, IntFromRope], IO USING [PutF1, PutRope, rope], Rope USING [ROPE, Cat, Concat, Substr], PrintEnglish; PrintEnglishImpl: CEDAR PROGRAM IMPORTS Commander, CommanderOps, 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.Concat[r, teens[i-10]]; RETURN; }; digit ¬ i/10; IF digit # 0 THEN r ¬ Rope.Concat[r, tens[digit]]; i ¬ i MOD 10; IF i # 0 THEN r ¬ Rope.Concat[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[CommanderOps.NextArgument[cmd] ! Convert.Error => GOTO SyntaxError]; IO.PutF1[cmd.out, "%g\n", IO.rope[IntToEnglish[i]]]; EXITS SyntaxError => IO.PutRope[cmd.err, "Integer not specified.\n"]; }; Commander.Register[key: "Number", proc: Number, doc: "Print out the english equivalent of an integer"]; <<>> END. <> <> <> <> <> <> <<>> <> <> <<>>