Таки доделал на КП/ББ -- ох и утомительный же язык для задач по обработке строк (((
MODULE Lem;
IMPORT In, Out, Services;
TYPE String = ARRAY 1000 OF CHAR;
TYPE
PLs = POINTER TO ARRAY OF PL;
PL = POINTER TO L;
L = RECORD
s : String;
vs: PLs;
END;
VAR
zemlya,
mogut_byt_unictozheny, ne_mogut_byt_unictozheny,
no_uchyonye, no_paren, zhenyatsya : PL;
zemlyas,
mogut_byt_unictozhenys, ne_mogut_byt_unictozhenys,
no_uchyonyes, no_parens, no_parenss2, uchyonyes, yavlyatutsyas,
delayut_vsyakoes0, delayut_vsyakoes5 : PLs;
vse_gibnut, razrushaetsya, mal_ogr, konec,
sushestv, kotoroe, kotorye, delayut_vsyakoe, yavlyatutsya,
i, is, no, ok, no_oni : PLs;
armiey : String;
seed: INTEGER;
PROCEDURE Set(VAR pl: PL; IN s: String; vs: PLs);
BEGIN
NEW(pl); pl.s := s; pl.vs := vs;
END Set;
PROCEDURE Init();
BEGIN
konec := NIL;
NEW(no_oni, 4);
Set(no_oni[0], "но они умирают от чёрной оспы", konec);
Set(no_oni[1], "и поэтому они убивают нас", konec);
Set(no_oni[2], "и поэтому они устанавливают систему доброжелательной диктатуры", konec);
Set(no_oni[3], "и поэтому они съедают нас", konec);
NEW(kotoroe, 3);
Set(kotoroe[0], "которое отказывает", no_oni);
Set(kotoroe[1], "которое их убивает", konec);
Set(kotoroe[2], "которое превращает их в мерзкие глыбы", konec);
Set(no_uchyonye, "но учёные изобретают новое оружие", kotoroe);
NEW(ok, 3);
Set(ok[0], "и они умирают", konec);
Set(ok[1], "и они улетают", konec);
Set(ok[2], "и они превращаются в мерзкие глыбы", konec);
Set(zhenyatsya, "и женятся и живут долго и счастливо", konec);
NEW(no_parenss2, 4);
no_parenss2[0] := zhenyatsya;
no_parenss2[1] := ok[0];
no_parenss2[2] := ok[1];
no_parenss2[3] := ok[2];
NEW(no_parens, 3);
Set(no_parens[0], "один хитрый парень убеждает их что люди 'OK'", ok);
Set(no_parens[1], "священник рассказывает им о Боге", ok);
Set(no_parens[2], "влюбляются в красивую девушку", no_parenss2);
Set(no_paren, "но", no_parens);
NEW(no, 6);
no[0] := no_uchyonye;
no[1] := no_paren;
no[2] := no_oni[0];
no[3] := no_oni[1];
no[4] := no_oni[2];
no[5] := no_oni[3];
armiey := "сухопутной армией, морским флотом, авиацией, морской пехотой и (или) войсками береговой охраны";
NEW(mogut_byt_unictozhenys, 3);
Set(mogut_byt_unictozhenys[0], "толпой парней с факелами", konec);
Set(mogut_byt_unictozhenys[1], armiey, konec);
Set(mogut_byt_unictozhenys[2], "атомной бомбой", konec);
NEW(ne_mogut_byt_unictozhenys, 3);
Set(ne_mogut_byt_unictozhenys[0], "толпой парней с факелами", no);
Set(ne_mogut_byt_unictozhenys[1], armiey, no);
Set(ne_mogut_byt_unictozhenys[2], "атомной бомбой", no);
Set(mogut_byt_unictozheny, "могут быть уничтожены", mogut_byt_unictozhenys);
Set(ne_mogut_byt_unictozheny, "не могут быть уничтожены", ne_mogut_byt_unictozhenys);
NEW(is, 2);
is[0] := mogut_byt_unictozheny;
is[1] := ne_mogut_byt_unictozheny;
NEW(i, 1);
Set(i[0], "и", is);
NEW(yavlyatutsyas, 2);
Set(yavlyatutsyas[0], "радиоактивными", i);
Set(yavlyatutsyas[1], "нерадиоактивными", i);
NEW(yavlyatutsya, 1);
Set(yavlyatutsya[0], "и являются", yavlyatutsyas);
NEW(delayut_vsyakoes0, 2);
Set(delayut_vsyakoes0[0], "похищают их и исчезают", konec);
delayut_vsyakoes0[1] := yavlyatutsya[0];
NEW(delayut_vsyakoes5, 2);
Set(delayut_vsyakoes5[0], "и съедают нас", konec);
delayut_vsyakoes5[1] := yavlyatutsya[0];
NEW(delayut_vsyakoe, 6);
Set(delayut_vsyakoe[0], "желают наших женщин", delayut_vsyakoes0);
Set(delayut_vsyakoe[1], "ведут себя дружелюбно", konec);
Set(delayut_vsyakoe[2], "ведут себя дружелюбно, но их никто не понимает", yavlyatutsya);
Set(delayut_vsyakoe[3], "не понимают нас", yavlyatutsya);
Set(delayut_vsyakoe[4], "отлично понимают нас", yavlyatutsya);
Set(delayut_vsyakoe[5], "воспринимают нас только как пищу", delayut_vsyakoes5);
NEW(kotorye, 1);
Set(kotorye[0], "которые", delayut_vsyakoe);
NEW(sushestv, 8);
Set(sushestv[0], "насекомых", kotorye);
Set(sushestv[1], "пресмыкающихся", kotorye);
Set(sushestv[2], "роботов", kotorye);
Set(sushestv[3], "внеземных существ", kotorye);
Set(sushestv[4], "марсиан", kotorye);
Set(sushestv[5], "селенитов", kotorye);
Set(sushestv[6], "внегалактических чудовищ", kotorye);
Set(sushestv[7], "различных странных предметов", kotorye);
NEW(mal_ogr, 2);
Set(mal_ogr[0], "маленьких", sushestv);
Set(mal_ogr[1], "огромных", sushestv);
NEW(uchyonyes, 2);
Set(uchyonyes[0], "создают", mal_ogr);
Set(uchyonyes[1], "открывают", mal_ogr);
NEW(vse_gibnut, 2);
Set(vse_gibnut[0], "все гибнут", konec);
Set(vse_gibnut[1], "почти все гибнут", konec);
NEW(razrushaetsya, 3);
Set(razrushaetsya[0], "разрушается", konec);
Set(razrushaetsya[1], "не разрушается, но", vse_gibnut);
Set(razrushaetsya[2], "остаётся невредимой", konec);
NEW(zemlyas, 6);
Set(zemlyas[0], "сгорает и", vse_gibnut);
Set(zemlyas[1], "замерзает и", vse_gibnut);
Set(zemlyas[2], "падает на Солнце и", vse_gibnut);
Set(zemlyas[3], "сталкивается с огромной кометой и", razrushaetsya);
Set(zemlyas[4], "учёные", uchyonyes);
Set(zemlyas[5], "подвергается нашествию", mal_ogr);
Set(zemlya, "Земля", zemlyas);
END Init;
PROCEDURE UniRand (): REAL;
CONST a = 16807; m = 2147483647; q = m DIV a; r = m MOD a;
BEGIN
seed := a * (seed MOD q) - r * (seed DIV q);
IF seed <= 0 THEN seed := seed + m END;
RETURN seed * (1.0 / m)
END UniRand;
PROCEDURE Rnd(x: INTEGER): INTEGER;
BEGIN
RETURN SHORT(ENTIER(x * UniRand ()))
END Rnd;
PROCEDURE Sentence*(): POINTER TO String;
VAR
n: INTEGER;
strout: POINTER TO String;
PROCEDURE write_str(s: String);
VAR i: INTEGER;
BEGIN
FOR i := 0 TO LEN(s$) - 1 DO
strout[n] := s[i];
INC(n);
END
END write_str;
PROCEDURE Sntnc(z: PL);
BEGIN
IF z # NIL THEN
write_str(z.s);
IF z.vs = NIL THEN
write_str(".");
ELSE
write_str(" ");
Sntnc(z.vs[Rnd(LEN(z.vs))])
END
END
END Sntnc;
BEGIN
n := 0;
NEW(strout);
Sntnc(zemlya);
RETURN strout
END Sentence;
PROCEDURE Do*();
BEGIN
Out.Open;
Out.String(Sentence());
Out.Ln;
END Do;
BEGIN
Init();
seed := SHORT(Services.Ticks());
END Lem.
Исчерпывающего тестирования не делал, так что возможны ошибки -- это же не хацкель какой-нить там...