1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-02 23:14:57 +03:00
inform7/inbuild/words-module/Chapter 3/Feeds.w
2020-03-11 00:21:09 +00:00

127 lines
3.8 KiB
OpenEdge ABL

[Feeds::] Feeds.
Feeds are conduits for arbitrary text to flow into the lexer, and to
be converted into wordings.
@h Definitions.
@ I feel a certain embarrassment about the frequency with which the following
code is needed throughout Inform, to create fresh source text from old. Is
this a shameless hack, sacrificing memory for the sake of a small data
structure to represent wordings? Or is it a deep insight into the
interdependency of lexical analysis and semantic understanding? The reader
must decide.
Each feed has a unique ID. At present only one is ever open at a time, but
we don't want to assume that.
@d feed_t int /* (not a typedef only because it makes trouble for inweb) */
@h Feed sessions.
There are two ways to make a feed. One is simply to call one of the |feed_text|
routines below and use its output. The other is for a multi-stage process,
that is, for when multiple pieces of text need to go into the same feed:
to start such, call |Feeds::begin| and get an ID; to end, call |Feeds::end|
with the corresponding ID back again.
=
feed_t Feeds::begin(void) {
return (feed_t) lexer_wordcount;
}
wording Feeds::end(feed_t id) {
return Wordings::new((int) id, lexer_wordcount-1);
}
@h Feeding a feed.
Within a feed session, we can pass two sorts of text into the lexer: first,
raw strings.
=
wording Feeds::feed_text(wchar_t *text) {
return Feeds::feed_text_full(text, FALSE, NULL);
}
wording Feeds::feed_stream(text_stream *text) {
return Feeds::feed_stream_full(text, FALSE, NULL);
}
wording Feeds::feed_text_expanding_strings(wchar_t *text) {
return Feeds::feed_text_full(text, TRUE, NULL);
}
wording Feeds::feed_stream_expanding_strings(text_stream *text) {
return Feeds::feed_stream_full(text, TRUE, NULL);
}
wording Feeds::feed_stream_punctuated(text_stream *text, wchar_t *pmarks) {
wording W = Feeds::feed_stream_full(text, FALSE, pmarks);
return W;
}
@ When done, we call |Vocabulary::identify_word_range|, because we are probably
running long after the initial vocabulary identification phase of Inform.
=
wording Feeds::feed_text_full(wchar_t *text, int expand_strings, wchar_t *nonstandard) {
source_location as_if_from_nowhere;
as_if_from_nowhere.file_of_origin = NULL;
as_if_from_nowhere.line_number = 1;
Lexer::feed_begins(as_if_from_nowhere);
lexer_divide_strings_at_text_substitutions = expand_strings;
lexer_allow_I6_escapes = TRUE;
if (nonstandard) {
lexer_punctuation_marks = nonstandard;
lexer_allow_I6_escapes = FALSE;
} else
lexer_punctuation_marks = STANDARD_PUNCTUATION_MARKS;
for (int i=0; text[i] != 0; i++) {
int last_cr, cr, next_cr;
if (i > 0) last_cr = text[i-1]; else last_cr = EOF;
cr = text[i];
if (cr != 0) next_cr = text[i+1]; else next_cr = EOF;
Lexer::feed_triplet(last_cr, cr, next_cr);
}
wording LEXW = Lexer::feed_ends(FALSE, NULL);
Vocabulary::identify_word_range(LEXW);
return LEXW;
}
wording Feeds::feed_stream_full(text_stream *text, int expand_strings, wchar_t *nonstandard) {
source_location as_if_from_nowhere;
as_if_from_nowhere.file_of_origin = NULL;
as_if_from_nowhere.line_number = 1;
Lexer::feed_begins(as_if_from_nowhere);
lexer_divide_strings_at_text_substitutions = expand_strings;
lexer_allow_I6_escapes = TRUE;
if (nonstandard) {
lexer_punctuation_marks = nonstandard;
lexer_allow_I6_escapes = FALSE;
} else
lexer_punctuation_marks = STANDARD_PUNCTUATION_MARKS;
for (int i=0, L=Str::len(text); i<L; i++) {
int last_cr, cr, next_cr;
if (i > 0) last_cr = Str::get_at(text, i-1); else last_cr = EOF;
cr = Str::get_at(text, i);
if (cr != 0) next_cr = Str::get_at(text, i+1); else next_cr = EOF;
Lexer::feed_triplet(last_cr, cr, next_cr);
}
wording LEXW = Lexer::feed_ends(FALSE, NULL);
Vocabulary::identify_word_range(LEXW);
return LEXW;
}
@ The only other possible action is to splice:
=
wording Feeds::feed_wording(wording W) {
return Lexer::splice_words(W);
}