aboutsummaryrefslogtreecommitdiffstats
path: root/doc/design/s5_4
blob: b91d7ceed3758f1b77d3845f09619ec5194a77d5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
@SubSection
    @Tag { lookahead }
    @Title { The limited lookahead problem }
@Begin
@PP
Basser Lout assumes that there will be enough internal memory to hold
the symbol table plus a few pages, but not an entire document.  This
section describes the consequent problems and how they were solved.
Other interpreters, notably interactive editors running on virtual
memory systems, would not necessarily need this assumption.
@PP
Although Basser Lout can read and format any legal input, its memory
consumption will be optimized when the bulk of the document resides in
galleys whose targets can be identified at the moment they are
encountered.  Let us take the typical example of a root galley which
is a list of pages, a @Code "@BodyText" galley targeted into the
pages, @Code "@Chapter" galleys targeted into {@Code "@BodyText"},
and @Code "@Section" galleys targeted into the @Code "@Chapter"
galleys:
@ID @OneRow @Code {
"@PageList"
"//"
"@BodyText"
"//"
"@Chapter {"
"    @Section { ... }"
"    @Section { ... }"
"    ..."
"    @Section { ... }"
"}"
"@Chapter {"
"    ..."
"}"
}
Basser Lout is able to read and process such galleys one paragraph at
a time (strictly, from one @Code "//" at the outer level of a galley
to the next), as we now describe.
@PP
When the parser encounters the beginning of a galley, like @Code "@Chapter"
or {@Code "@Section"}, it initiates a new galley process.  The special
receptive symbol @Code "@Input" is substituted for the as yet
unread right parameter of the galley.  As each paragraph of the right
parameter is read, it is deleted from the parse tree and injected into
the galley's {@Code "@Input"}.  The galley is then resumed.  The parser
thus acts as an extra
concurrent process; it has low priority, so that input is read only when
there is nothing else to do.  Since galleys may be nested, a stack of
@Code "@Input" symbols is needed, each with its own environment and
style.  If a galley is encountered for which a target is not immediately
identifiable (a footnote, for example), it is read in its entirety and
hung in pure parse tree form from an @I UNATTACHED index in the usual way,
with an environment but without a style.  It will be flushed later
when its component is promoted.
@PP
In addition to producing a steady flow of components from input, we must
also ensure that receptive symbols do not unduly block their
promotion.  The @Code "@FootSect" symbol at the foot of each page is a
typical example:  until it is deleted the page cannot be printed.
@PP
Receptive symbols are expanded only on demand, so @Code "@FootSect" can
be deleted as soon as we can prove that it is not wanted.  The symbol
table can tell us that only @Code "@FootNote" galleys (with
@Code "@FootPlace&&following" targets) want it, so it might be possible
to deduce that @Code "@FootSect" may be deleted as soon as body text
enters the following page.
@PP
The author was unable to make this work, so Basser Lout requires the
user to identify those galleys which will carry the bulk of the document
({@Code "@Chapter"}, {@Code "@Section"}, {@Code "@BodyText"}) as
{@I {forcing galleys}}, by writing @Code "force into" instead of
@Code "into" in their definitions.  As described in the previous
section, when a forcing galley attaches to a target, all receptive
symbols preceding the target in its galley are deleted, removing all
impediments to flushing.  For example, when a forcing body text galley
enters a new page, the @Code "@FootSect" symbol on the preceding page
will be deleted.  It seems likely that a system which could afford to
wait until all input was read before deleting any receptive symbols
would not need forcing galleys.
@PP
Galleys whose targets are a long way from their invocation points can be
a problem.  If the direction is {@Code "following"}, such galleys are
held in internal memory for a long time, unless they are to be
sorted.  If the direction is
{@Code "preceding"}, then either the entire intervening document must be
held in memory (prevented by the target from flushing), or else some
forcing galley prematurely deletes the target, leaving the galley bereft.
@PP
The typical example of the latter case occurs when the galley is an
entry in the table of contents, launched backwards from the beginning of
a chapter or section.  Its target in the table of contents will have
been deleted long before, to permit the rest of the document to print,
so the galley ultimately emerges as an unattached galley promoted out of
the root galley.  All such galleys are written to an auxiliary file,
indexed by the missing target.  On the next run, just before that target
is deleted, the auxiliary file is checked and any galleys for it are
read in and flushed.
@End @SubSection