PrintEnglishImpl.mesa
Copyright Ó 1985, 1992 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
Brian Oki November 15, 1989 4:50:51 pm PST
Willie-s, April 23, 1992 1:54 pm PDT
DIRECTORY
Commander USING [Register, CommandProc],
CommanderOps USING [<<ArgumentVector, Failed, Parse,>> NextArgument],
Convert USING [Error, IntFromRope],
IO USING [PutF1, PutRope, rope],
Rope USING [ROPE, Cat, Concat, Substr],
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] ~ {
Converts integer numbers to their English equivalents.
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;
argv: CommanderOps.ArgumentVector ← CommanderOps.Parse[cmd: cmd ! CommanderOps.Failed => GOTO SyntaxError];
IF argv.argc < 2 THEN GOTO SyntaxError;
i ← Convert.IntFromRope[argv[1] ! Convert.Error => 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"];