
Two words are enough for TAKE LAMP. They are not enough for UNLOCK THE DOOR WITH THE KEY. This section builds the parser BEACON uses: it reads a sentence of up to four kinds of word, throws away the words that carry no meaning, and works out what the player asked for.
Every word in the table now has a kind as well as a place:
type
Kind = (Unknown, Verb, Noun, Prep, Noise);
| Kind | Words | What the parser does |
|---|---|---|
Verb | TAKE, OPEN, UNLOCK | remembers it in V |
Noun | LAMP, DOOR, KEY | the first noun in N1, a noun after a preposition in N2 |
Prep | WITH, IN | remembers it in P |
Noise | THE, A, AN | nothing at all |
Noise words need no code: the case on the kind has no branch for Noise, so they fall through and are forgotten. That is all "skipping" them takes.
UNLOCK THE DOOR WITH THE KEY comes out as V = UNLOCK, N1 = DOOR, P = WITH, N2 = KEY.
When Find returns 0, the parser stops at once and says which word it was: I don't know SWORD. It is the single most useful thing a parser can tell a player, and Zork does the same, quoting the unknown word back (S7). Parse returns False, so the rest of the program knows not to act.
LOOK makes sense alone. GET does not. A set says which verbs need a noun:
NeedNoun: set of 1..Count = [1, 2, 3, 4, 6];
The numbers are places in the table: TAKE, GET, OPEN, UNLOCK and FILL. When one of them comes without a noun, the program asks: What do you want to GET?
program Sentence;
type
Str12 = string[12];
Str40 = string[40];
Kind = (Unknown, Verb, Noun,
Prep, Noise);
const
Count = 16;
Words: array[1..Count] of Str12 =
('TAKE', 'GET', 'OPEN', 'UNLOCK',
'LOOK', 'FILL', 'LAMP', 'KEY',
'DOOR', 'OIL', 'CROWBAR', 'WITH',
'IN', 'THE', 'A', 'AN');
Kinds: array[1..Count] of Kind =
(Verb, Verb, Verb, Verb, Verb,
Verb, Noun, Noun, Noun, Noun,
Noun, Prep, Prep, Noise, Noise,
Noise);
NeedNoun: set of 1..Count =
[1, 2, 3, 4, 6];
var
Line: Str40;
V, N1, P, N2: Integer;
function Find(W: Str12): Integer;
var
I, Found: Integer;
begin
Found := 0;
for I := 1 to Count do
if Words[I] = W then
Found := I;
Find := Found;
end;
function Parse(S: Str40): Boolean;
var
W: Str12;
K, Pl: Integer;
Ok: Boolean;
begin
V := 0; N1 := 0; P := 0; N2 := 0;
Ok := True;
S := S + ' ';
while Ok and (S <> '') do
begin
Pl := Pos(' ', S);
W := Copy(S, 1, Pl - 1);
Delete(S, 1, Pl);
if W <> '' then
begin
K := Find(W);
if K = 0 then
begin
Writeln('I don''t know ', W);
Ok := False;
end
else
case Kinds[K] of
Verb: V := K;
Prep: P := K;
Noun: if P = 0 then N1 := K
else N2 := K;
end;
end;
end;
Parse := Ok;
end;
begin
repeat
Write('> ');
Readln(Line);
if Parse(Line) then
if V = 0 then
Writeln('There is no verb.')
else if (V in NeedNoun)
and (N1 = 0) then
Writeln('What do you want to ',
Words[V], '?')
else
begin
Write(Words[V]);
if N1 > 0 then
Write(' ', Words[N1]);
if P > 0 then
Write(' ', Words[P]);
if N2 > 0 then
Write(' ', Words[N2]);
Writeln;
end;
until Line = '';
end.
The table is short enough to search straight down; BEACON's, in S18, is in order and searched S9's way.
Starting from
A new work file SENTENCE. Type in capitals. ENTER alone ends it.
What you should see
> TAKE THE LAMP
TAKE LAMP
> UNLOCK THE DOOR WITH THE KEY
UNLOCK DOOR WITH KEY
> GET
What do you want to GET?
> LOOK
LOOK
> TAKE THE SWORD
I don't know SWORD
> THE LAMP
There is no verb.
> FILL LAMP WITH OIL
FILL LAMP WITH OIL
5 to NeedNoun. What does LOOK say now?Noun: branch to Noun: N1 := K;. What do the two sentences with WITH come out as?Words[V] in the question to W. What does the compiler say, and why can the main program not see W?10.1 Put S5's Tidy in front of Parse, so that Take the lamp! and unlock door, with key. work.
10.2 Make GET a true synonym of TAKE: add a typed constant Same that gives, for each word, the word it means, and have the parser keep that in V. GET alone should then ask What do you want to TAKE?
10.3 A preposition with no noun after it is a half-finished sentence. Answer OPEN THE DOOR WITH with WITH what?
Worked solutions are in Appendix II.
| Symptom | Cause |
|---|---|
| The second noun replaces the first | The Noun branch does not look at P. |
Error 41 naming a word you used in Parse | Variables declared in a function belong to it. |
There is no verb for a sentence with a verb | The verb's kind in the table is wrong, or the lists are out of step. |
Every word has a kind: verb, noun, preposition or noise. The parser keeps the verb, the first noun, the preposition and the noun after it; noise words fall through the case and vanish; an unknown word stops the parse with its name; a set says which verbs need a noun. That is the whole of BEACON's parser.
S11, Text In The Program: part two begins. The game has a great deal to say. Where does it all go?
This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.