Here’s a try that uses Text Capture to look ahead:
Include Text Capture by Eric Eve.
Lab is a room.
Capturing text for article is initially false.
To say a-an of -- beginning a-an_of:
if text capturing is active: [if we're capturing text already, we can't start capturing it again for the article, so we punt--a better solution would be to buffer the old captured text to another variable]
say "a ";
otherwise:
now capturing text for article is true;
start capturing text.
To say end a-an -- ending a-an_of:
if capturing text for article is true: [if we wound up not capturing text for the article, we don't want to do this]
stop capturing text;
if character number 1 in "[captured text]" is a vowel:
say "an [captured text]";
otherwise:
say "a [captured text]";
now capturing text for article is false.
To decide whether (letter - a text) is a vowel:
if letter exactly matches the regular expression "a|e|i|o|u|A|E|I|O|U", yes;
no.
Every turn: say "You see [a-an of][one of]red[or]orange[or]yellow[or]green[or]blue[or]indigo[or]violet[cycling][end a-an] light."
Of course, if you’re already using Text Capture it gets awkward. Also it won’t capture exceptions like “uniform” or “honest” or “ytterbium,” which I guess you’d have to special-case in the part that currently tests whether it begins with a vowel. Also when I tried to get A-An to work with uppercase articles, I got errors–presumably I could solve that by making the substitution [capital A-An], though it seems inelegant. (Or I might have just messed up.)