2020-02-17 00:01:50 +02:00
|
|
|
[SourceText::] Source Text.
|
|
|
|
|
2020-05-06 17:31:53 +03:00
|
|
|
Using the lexer and syntax analysis modules to read in Inform 7 source text.
|
2020-02-17 00:01:50 +02:00
|
|
|
|
2020-05-06 14:55:04 +03:00
|
|
|
@h Bridge to the Lexer.
|
2020-05-06 17:31:53 +03:00
|
|
|
Lexing is the business of the //words// module, and we need to tell it what
|
|
|
|
data type to use when referencing natural languages.
|
2020-05-06 14:55:04 +03:00
|
|
|
|
2020-05-13 01:33:17 +03:00
|
|
|
@d NATURAL_LANGUAGE_WORDS_TYPE struct inform_language
|
2020-05-06 14:55:04 +03:00
|
|
|
|
|
|
|
@ Lexical errors -- overly long words, half-open quotations, and such -- are
|
|
|
|
converted into copy errors and attached to the copy currently being worked on.
|
|
|
|
The following callback function performs that service.
|
|
|
|
|
|
|
|
//words// has no convenient way to keep track of what copy we're working on,
|
|
|
|
so we will simply store it in a global variable.
|
|
|
|
|
2020-05-06 17:31:53 +03:00
|
|
|
@d PROBLEM_WORDS_CALLBACK SourceText::lexer_problem_handler
|
2020-02-17 00:01:50 +02:00
|
|
|
|
|
|
|
=
|
2020-02-18 01:50:21 +02:00
|
|
|
inbuild_copy *currently_lexing_into = NULL;
|
2020-05-06 14:55:04 +03:00
|
|
|
void SourceText::lexer_problem_handler(int err, text_stream *desc, wchar_t *word) {
|
|
|
|
if (err == MEMORY_OUT_LEXERERROR)
|
|
|
|
Errors::fatal("Out of memory: unable to create lexer workspace");
|
|
|
|
if (currently_lexing_into) {
|
|
|
|
copy_error *CE = CopyErrors::new_WT(LEXER_CE, err, word, desc);
|
|
|
|
Copies::attach_error(currently_lexing_into, CE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@ This next function is our bridge to the lexer (see //words: Text From Files//),
|
|
|
|
and is used for reading text files of source into either projects or extensions.
|
|
|
|
Note that it doesn't attach the fed text to the copy: the caller must do that,
|
|
|
|
perhaps combining our feed with that of others.
|
2020-02-18 01:50:21 +02:00
|
|
|
|
2020-05-06 14:55:04 +03:00
|
|
|
=
|
2023-07-13 02:23:12 +03:00
|
|
|
int source_reader_in_documentation_only_mode = FALSE;
|
|
|
|
|
|
|
|
int SourceText::for_documentation_only(int state) {
|
|
|
|
int old_state = source_reader_in_documentation_only_mode;
|
|
|
|
source_reader_in_documentation_only_mode = state;
|
|
|
|
return old_state;
|
|
|
|
}
|
|
|
|
|
2020-02-17 11:43:20 +02:00
|
|
|
source_file *SourceText::read_file(inbuild_copy *C, filename *F, text_stream *synopsis,
|
2023-07-13 02:23:12 +03:00
|
|
|
int primary) {
|
|
|
|
int documentation_only = source_reader_in_documentation_only_mode;
|
2020-02-18 01:50:21 +02:00
|
|
|
currently_lexing_into = C;
|
2020-02-17 00:01:50 +02:00
|
|
|
general_pointer ref = STORE_POINTER_inbuild_copy(NULL);
|
|
|
|
FILE *handle = Filenames::fopen(F, "r");
|
2020-02-18 01:50:21 +02:00
|
|
|
source_file *sf = NULL;
|
|
|
|
if (handle) {
|
|
|
|
text_stream *leaf = Filenames::get_leafname(F);
|
|
|
|
if (primary) leaf = I"main source text";
|
2023-05-16 10:11:55 +03:00
|
|
|
int mode = UNICODE_UFBHM;
|
|
|
|
target_vm *vm = Supervisor::current_vm();
|
|
|
|
if (TargetVMs::is_16_bit(vm)) mode = ZSCII_UFBHM;
|
2020-02-18 01:50:21 +02:00
|
|
|
sf = TextFromFiles::feed_open_file_into_lexer(F, handle,
|
2023-05-16 10:11:55 +03:00
|
|
|
leaf, documentation_only, ref, mode);
|
2020-02-18 01:50:21 +02:00
|
|
|
if (sf == NULL) {
|
2020-03-29 19:39:17 +03:00
|
|
|
Copies::attach_error(C, CopyErrors::new_F(OPEN_FAILED_CE, -1, F));
|
2020-02-18 01:50:21 +02:00
|
|
|
} else {
|
|
|
|
fclose(handle);
|
2020-03-04 21:34:23 +02:00
|
|
|
#ifdef CORE_MODULE
|
2021-09-13 02:33:30 +03:00
|
|
|
if ((documentation_only == FALSE) && (Main::silence_is_golden() == FALSE))
|
|
|
|
@<Tell console output about the file@>;
|
2020-03-04 21:34:23 +02:00
|
|
|
#endif
|
2020-02-18 01:50:21 +02:00
|
|
|
}
|
2020-02-17 00:01:50 +02:00
|
|
|
}
|
2020-02-18 01:50:21 +02:00
|
|
|
currently_lexing_into = NULL;
|
2020-02-17 00:01:50 +02:00
|
|
|
return sf;
|
|
|
|
}
|
|
|
|
|
|
|
|
@ This is where messages like
|
2020-04-08 01:02:44 +03:00
|
|
|
= (text as ConsoleText)
|
|
|
|
I've also read Standard Rules by Graham Nelson, which is 27204 words long.
|
|
|
|
=
|
2020-05-06 14:55:04 +03:00
|
|
|
are printed to |stdout| (not |stderr|), though occasionally I think silence is
|
2020-02-17 11:43:20 +02:00
|
|
|
golden and that these messages could go. It's a moot point for almost all users,
|
2020-05-06 14:55:04 +03:00
|
|
|
though, because the console output is concealed from them by the Inform UI
|
|
|
|
applications.
|
2020-02-17 00:01:50 +02:00
|
|
|
|
|
|
|
@<Tell console output about the file@> =
|
2020-05-06 14:55:04 +03:00
|
|
|
char *message = "I've also read %S, which is %d words long.\n";
|
2020-02-17 00:01:50 +02:00
|
|
|
if (primary) message = "I've now read %S, which is %d words long.\n";
|
2020-05-06 14:55:04 +03:00
|
|
|
int wc = TextFromFiles::total_word_count(sf);
|
2020-02-17 00:01:50 +02:00
|
|
|
WRITE_TO(STDOUT, message, synopsis, wc);
|
|
|
|
STREAM_FLUSH(STDOUT);
|
|
|
|
LOG(message, synopsis, wc);
|
2020-02-18 01:50:21 +02:00
|
|
|
|
2020-05-21 02:11:29 +03:00
|
|
|
@h Bridge to the problems system.
|
|
|
|
These are both used when issuing problem messages on content in the relevant
|
|
|
|
source files.
|
|
|
|
|
|
|
|
@d DESCRIBE_SOURCE_FILE_PROBLEMS_CALLBACK SourceText::describe_source_file
|
|
|
|
|
|
|
|
=
|
|
|
|
text_stream *SourceText::describe_source_file(text_stream *paraphrase,
|
|
|
|
source_file *referred, text_stream *file) {
|
|
|
|
paraphrase = I"source text";
|
2023-04-25 12:37:50 +03:00
|
|
|
inform_extension *E = NULL;
|
|
|
|
if (referred) {
|
|
|
|
E = Extensions::corresponding_to(referred);
|
|
|
|
} else {
|
|
|
|
TEMPORARY_TEXT(matched_filename)
|
|
|
|
inform_extension *F;
|
|
|
|
LOOP_OVER(F, inform_extension) {
|
|
|
|
if (F->read_into_file) {
|
|
|
|
Str::clear(matched_filename);
|
|
|
|
WRITE_TO(matched_filename, "%f",
|
|
|
|
TextFromFiles::get_filename(F->read_into_file));
|
|
|
|
if (Str::eq(matched_filename, file)) E = F;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-05-21 02:11:29 +03:00
|
|
|
if (E) {
|
|
|
|
inbuild_work *work = E->as_copy->edition->work;
|
|
|
|
if ((work) && (Works::is_standard_rules(work)))
|
|
|
|
paraphrase = I"the Standard Rules";
|
|
|
|
else if ((work) && (Works::is_basic_inform(work)))
|
|
|
|
paraphrase = I"Basic Inform";
|
|
|
|
else
|
|
|
|
paraphrase = file;
|
|
|
|
}
|
|
|
|
return paraphrase;
|
|
|
|
}
|
|
|
|
|
|
|
|
@
|
|
|
|
|
|
|
|
@d GLOSS_EXTENSION_SOURCE_FILE_PROBLEMS_CALLBACK SourceText::gloss_extension
|
|
|
|
|
|
|
|
=
|
|
|
|
void SourceText::gloss_extension(text_stream *OUT, source_file *referred) {
|
|
|
|
inform_extension *E = Extensions::corresponding_to(referred);
|
|
|
|
if (E) WRITE(" in the extension %X", E->as_copy->edition->work);
|
|
|
|
}
|
|
|
|
|
2020-05-06 14:55:04 +03:00
|
|
|
@h Bridge to the syntax analyser.
|
|
|
|
Similarly, //supervisor// sits on top of the //syntax// module, which forms
|
|
|
|
up the stream of words from the lexer into syntax trees. This too produces
|
|
|
|
potential errors, and these will also convert into copy errors, but now we
|
|
|
|
have a more elegant way to keep track of the copy; //syntax// can be passed
|
|
|
|
a sort of "your ref" pointer to it.
|
2020-02-18 01:50:21 +02:00
|
|
|
|
2020-05-06 17:31:53 +03:00
|
|
|
@d PROBLEM_REF_SYNTAX_TYPE struct inbuild_copy /* the "your ref" is a pointer to this type */
|
|
|
|
@d PROJECT_REF_SYNTAX_TYPE struct inform_project /* similarly but for the "project ref" */
|
|
|
|
@d PROBLEM_SYNTAX_CALLBACK SourceText::syntax_problem_handler
|
2020-02-18 01:50:21 +02:00
|
|
|
|
|
|
|
=
|
2020-05-06 14:55:04 +03:00
|
|
|
void SourceText::syntax_problem_handler(int err_no, wording W,
|
2020-05-06 17:31:53 +03:00
|
|
|
PROBLEM_REF_SYNTAX_TYPE *C, int k) {
|
2020-05-06 14:55:04 +03:00
|
|
|
copy_error *CE = CopyErrors::new_N(SYNTAX_CE, err_no, k);
|
|
|
|
CopyErrors::supply_wording(CE, W);
|
|
|
|
Copies::attach_error(C, CE);
|
2020-02-18 01:50:21 +02:00
|
|
|
}
|
2020-03-03 02:59:42 +02:00
|
|
|
|
2020-05-06 17:31:53 +03:00
|
|
|
@ And in fact we will be producing a number of syntax errors of our own, to
|
|
|
|
add to those generated in //syntax//.
|
|
|
|
|
|
|
|
@e ExtMultipleBeginsHere_SYNERROR
|
|
|
|
@e ExtBeginsAfterEndsHere_SYNERROR
|
|
|
|
@e ExtEndsWithoutBegins_SYNERROR
|
|
|
|
@e ExtMultipleEndsHere_SYNERROR
|
|
|
|
@e UseElementWithdrawn_SYNERROR
|
2020-05-07 01:57:17 +03:00
|
|
|
@e UnknownLanguageElement_SYNERROR
|
|
|
|
@e UnknownVirtualMachine_SYNERROR
|
2020-05-07 18:44:07 +03:00
|
|
|
@e HeadingInPlaceOfUnincluded_SYNERROR
|
|
|
|
@e UnequalHeadingInPlaceOf_SYNERROR
|
|
|
|
@e HeadingInPlaceOfSubordinate_SYNERROR
|
|
|
|
@e HeadingInPlaceOfUnknown_SYNERROR
|
|
|
|
@e IncludeExtQuoted_SYNERROR
|
|
|
|
@e BogusExtension_SYNERROR
|
|
|
|
@e ExtVersionTooLow_SYNERROR
|
|
|
|
@e ExtVersionMalformed_SYNERROR
|
|
|
|
@e ExtInadequateVM_SYNERROR
|
|
|
|
@e ExtMisidentifiedEnds_SYNERROR
|
2022-06-23 19:37:16 +03:00
|
|
|
@e UnavailableLOS_SYNERROR
|
2022-09-01 15:04:08 +03:00
|
|
|
@e DialogueOnSectionsOnly_SYNERROR
|
2020-05-06 17:31:53 +03:00
|
|
|
|
2020-05-06 14:55:04 +03:00
|
|
|
@ The next tweak to //syntax// is to give it some node metadata. //syntax//
|
|
|
|
itself places nodes of a small number of basic types into the syntax tree;
|
|
|
|
we want to expand on those. (And the //core// module will expand on them still
|
2020-08-27 17:50:24 +03:00
|
|
|
further, so this still isn't everything: see //core: Inform-Only Nodes and Annotations//.)
|
2020-05-06 14:55:04 +03:00
|
|
|
|
|
|
|
The node types we're adding are for the "structural sentences" which we will
|
2020-05-06 17:31:53 +03:00
|
|
|
look for below. (The asterisk notation for |TRACE_NT| isn't known to most
|
|
|
|
Inform users: it increases output to the debugging log.)
|
2020-05-06 14:55:04 +03:00
|
|
|
|
2020-05-11 17:21:29 +03:00
|
|
|
@d NODE_METADATA_SETUP_SYNTAX_CALLBACK SourceText::node_metadata
|
2020-05-06 14:55:04 +03:00
|
|
|
|
|
|
|
@e BIBLIOGRAPHIC_NT /* For the initial title sentence */
|
2021-03-24 02:20:56 +02:00
|
|
|
@e IMPERATIVE_NT /* "Instead of taking something, ..." */
|
2020-05-06 14:55:04 +03:00
|
|
|
@e INFORM6CODE_NT /* "Include (- ... -) */
|
|
|
|
@e TABLE_NT /* "Table 1 - Counties of England" */
|
|
|
|
@e EQUATION_NT /* "Equation 2 - Newton's Second Law" */
|
|
|
|
@e TRACE_NT /* A sentence consisting of an asterisk and optional quoted text */
|
|
|
|
|
2021-03-24 02:20:56 +02:00
|
|
|
@d list_node_type IMPERATIVE_NT
|
2020-08-27 17:50:24 +03:00
|
|
|
@d list_entry_node_type UNKNOWN_NT
|
2020-05-06 14:55:04 +03:00
|
|
|
|
|
|
|
=
|
|
|
|
void SourceText::node_metadata(void) {
|
2020-05-11 17:21:29 +03:00
|
|
|
NodeType::new(BIBLIOGRAPHIC_NT, I"BIBLIOGRAPHIC_NT", 0, 0, L2_NCAT, 0);
|
2021-03-24 02:20:56 +02:00
|
|
|
NodeType::new(IMPERATIVE_NT, I"IMPERATIVE_NT", 0, INFTY, L2_NCAT, 0);
|
2020-05-11 17:21:29 +03:00
|
|
|
NodeType::new(INFORM6CODE_NT, I"INFORM6CODE_NT", 0, 0, L2_NCAT, 0);
|
|
|
|
NodeType::new(TABLE_NT, I"TABLE_NT", 0, 0, L2_NCAT, TABBED_NFLAG);
|
|
|
|
NodeType::new(EQUATION_NT, I"EQUATION_NT", 0, 0, L2_NCAT, 0);
|
|
|
|
NodeType::new(TRACE_NT, I"TRACE_NT", 0, 0, L2_NCAT, 0);
|
2020-03-03 13:02:46 +02:00
|
|
|
}
|
2020-03-03 02:59:42 +02:00
|
|
|
|
|
|
|
@ Sentences in the source text are of five categories: dividing sentences,
|
|
|
|
which divide up the source into segments; structural sentences, which split
|
|
|
|
the source into different forms (standard text, tables, equations, I6 matter,
|
|
|
|
and so on); nonstructural sentences, which make grammatical definitions and
|
|
|
|
give Inform other more or less direct instructions; rule declarations; and
|
|
|
|
regular sentences, those which use the standard verbs. Examples:
|
|
|
|
|
|
|
|
>> Volume II [dividing]
|
|
|
|
>> Include Locksmith by Emily Short [structural]
|
|
|
|
>> Release along with a website [nonstructural]
|
|
|
|
>> Instead of looking [rule]
|
|
|
|
>> The cushion is on the wooden chair [regular]
|
|
|
|
|
|
|
|
Dividing sentences are always read, whereas the others may be skipped in
|
2020-05-06 17:31:53 +03:00
|
|
|
sections of source not being included for one reason or another.
|
2020-03-03 02:59:42 +02:00
|
|
|
|
2020-05-06 17:31:53 +03:00
|
|
|
//syntax// requires us to define the nonterminal |<dividing-sentence>|,
|
|
|
|
and here goes:
|
2020-03-03 02:59:42 +02:00
|
|
|
|
|
|
|
=
|
|
|
|
<dividing-sentence> ::=
|
2020-07-28 12:43:16 +03:00
|
|
|
<if-start-of-paragraph> <heading> | ==> { pass 2 }
|
|
|
|
<extension-end-marker-sentence> ==> { pass 1 }
|
2020-03-03 02:59:42 +02:00
|
|
|
|
|
|
|
<heading> ::=
|
2020-07-28 11:57:58 +03:00
|
|
|
volume ... | ==> { 1, - }
|
|
|
|
book ... | ==> { 2, - }
|
|
|
|
part ... | ==> { 3, - }
|
|
|
|
chapter ... | ==> { 4, - }
|
2022-09-01 15:04:08 +03:00
|
|
|
section ... ( dialog ) | ==> { 6, - }
|
|
|
|
section ... ( dialogue ) | ==> { 6, - }
|
2020-07-28 11:57:58 +03:00
|
|
|
section ... ==> { 5, - }
|
2020-03-03 02:59:42 +02:00
|
|
|
|
|
|
|
<extension-end-marker-sentence> ::=
|
2020-07-28 17:49:03 +03:00
|
|
|
... begin/begins here | ==> { -1, - }; @<Check we can begin an extension here@>;
|
|
|
|
... end/ends here ==> { -2, - }; @<Check we can end an extension here@>;
|
2020-05-06 17:31:53 +03:00
|
|
|
|
|
|
|
@ Note that the extension end markers are only read in extensions, so they can
|
|
|
|
never accidentally match in the main source text.
|
2020-03-03 02:59:42 +02:00
|
|
|
|
|
|
|
@<Check we can begin an extension here@> =
|
2020-05-06 17:31:53 +03:00
|
|
|
switch (sfsm->ext_pos) {
|
|
|
|
case 1: sfsm->ext_pos++; break;
|
|
|
|
case 2: PROBLEM_SYNTAX_CALLBACK(ExtMultipleBeginsHere_SYNERROR, W, sfsm->ref, 0); break;
|
|
|
|
case 3: PROBLEM_SYNTAX_CALLBACK(ExtBeginsAfterEndsHere_SYNERROR, W, sfsm->ref, 0); break;
|
2020-03-03 02:59:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@<Check we can end an extension here@> =
|
2020-05-06 17:31:53 +03:00
|
|
|
switch (sfsm->ext_pos) {
|
|
|
|
case 1: PROBLEM_SYNTAX_CALLBACK(ExtEndsWithoutBegins_SYNERROR, W, sfsm->ref, 0); break;
|
|
|
|
case 2: sfsm->ext_pos++; break;
|
|
|
|
case 3: PROBLEM_SYNTAX_CALLBACK(ExtMultipleEndsHere_SYNERROR, W, sfsm->ref, 0); break;
|
2020-03-03 02:59:42 +02:00
|
|
|
}
|
|
|
|
|
2020-05-06 17:31:53 +03:00
|
|
|
@ //syntax// also requires this definition:
|
2020-03-03 02:59:42 +02:00
|
|
|
|
|
|
|
=
|
|
|
|
<structural-sentence> ::=
|
2020-07-28 17:49:03 +03:00
|
|
|
<if-start-of-source-text> <quoted-text> | ==> { 0, - }; sfsm->nt = BIBLIOGRAPHIC_NT;
|
|
|
|
<if-start-of-source-text> <quoted-text> ... | ==> { 0, - }; sfsm->nt = BIBLIOGRAPHIC_NT;
|
2020-07-28 12:43:16 +03:00
|
|
|
<language-modifying-sentence> | ==> { pass 1 }
|
2020-07-28 17:49:03 +03:00
|
|
|
* | ==> { 0, - }; sfsm->nt = TRACE_NT;
|
|
|
|
* <quoted-text-without-subs> | ==> { 0, - }; sfsm->nt = TRACE_NT;
|
|
|
|
<if-start-of-paragraph> table ... | ==> { 0, - }; sfsm->nt = TABLE_NT;
|
|
|
|
<if-start-of-paragraph> equation ... | ==> { 0, - }; sfsm->nt = EQUATION_NT;
|
|
|
|
include the ... by ... | ==> { 0, - }; sfsm->nt = INCLUDE_NT;
|
|
|
|
include ... by ... | ==> { 0, - }; sfsm->nt = INCLUDE_NT;
|
|
|
|
include (- ... ==> { 0, - }; sfsm->nt = INFORM6CODE_NT;
|
2020-03-03 02:59:42 +02:00
|
|
|
|
2020-05-11 21:14:00 +03:00
|
|
|
@ Rules are ordinarily detected by their colon, which divides the header from the
|
|
|
|
rest: colons are not otherwise legal in Inform. But there's an exception. If the
|
|
|
|
sentence consists of text matching the following grammar, followed by comma,
|
|
|
|
followed by more text, then the comma is read as if it's a colon and the
|
|
|
|
sentence becomes a rule. For example:
|
|
|
|
|
|
|
|
>> Instead of going north, try entering the cage
|
|
|
|
|
|
|
|
=
|
|
|
|
<comma-divisible-sentence> ::=
|
|
|
|
instead of ... |
|
|
|
|
every turn *** |
|
|
|
|
before ... |
|
|
|
|
after ... |
|
|
|
|
when ...
|
|
|
|
|
2020-03-03 02:59:42 +02:00
|
|
|
@ Properly speaking, despite the definition above, language modifying sentences
|
|
|
|
are nonstructural. So what are they doing here? The answer is that we need to
|
|
|
|
read them early on, because they affect the way that they parse all other
|
|
|
|
sentences. Whereas other nonstructural sentences can wait, these can't.
|
|
|
|
|
|
|
|
=
|
|
|
|
<language-modifying-sentence> ::=
|
2020-07-28 17:49:03 +03:00
|
|
|
include (- ### in the preform grammar | ==> { -2, - }; sfsm->nt = INFORM6CODE_NT;
|
2020-07-28 12:43:16 +03:00
|
|
|
use ... language element/elements ==> { -1, - }
|
2020-03-08 13:33:57 +02:00
|
|
|
|
2020-05-06 17:31:53 +03:00
|
|
|
@ The following callback function is called by //syntax// when it breaks a
|
|
|
|
sentence of type |BEGINHERE_NT| or |ENDHERE_NT| -- i.e., the beginning or end
|
|
|
|
of an extension.
|
2020-03-08 13:33:57 +02:00
|
|
|
|
2020-05-06 17:31:53 +03:00
|
|
|
@d BEGIN_OR_END_HERE_SYNTAX_CALLBACK SourceText::new_beginend
|
2020-03-08 13:33:57 +02:00
|
|
|
|
|
|
|
=
|
2020-05-06 17:31:53 +03:00
|
|
|
void SourceText::new_beginend(parse_node *pn, inbuild_copy *C) {
|
2022-12-08 01:28:26 +02:00
|
|
|
inform_extension *E = Extensions::from_copy(C);
|
2020-05-11 17:21:29 +03:00
|
|
|
if (Node::get_type(pn) == BEGINHERE_NT) Inclusions::check_begins_here(pn, E);
|
|
|
|
if (Node::get_type(pn) == ENDHERE_NT) Inclusions::check_ends_here(pn, E);
|
2020-03-08 13:33:57 +02:00
|
|
|
}
|
|
|
|
|
2022-09-17 21:49:46 +03:00
|
|
|
@ This callback is called by //syntax// when it first reaches a dialogue line
|
|
|
|
or beat.
|
|
|
|
|
|
|
|
@d DIALOGUE_WARNING_SYNTAX_CALLBACK Projects::dialogue_present
|
|
|
|
|
2020-05-06 17:31:53 +03:00
|
|
|
@ Lastly, this callback is called by //syntax// when it hits a sentence like:
|
2020-03-08 13:33:57 +02:00
|
|
|
|
2020-05-06 17:31:53 +03:00
|
|
|
>> Use interactive fiction language element.
|
2020-03-08 13:33:57 +02:00
|
|
|
|
2020-05-06 17:31:53 +03:00
|
|
|
This feature of Inform has been withdrawn (it has moved lower down the software
|
|
|
|
stack into the new world of kits), so we issue a syntax error.
|
|
|
|
|
|
|
|
@d LANGUAGE_ELEMENT_SYNTAX_CALLBACK SourceText::new_language
|
2020-03-08 13:33:57 +02:00
|
|
|
|
|
|
|
=
|
|
|
|
void SourceText::new_language(wording W) {
|
2020-03-29 19:39:17 +03:00
|
|
|
copy_error *CE = CopyErrors::new(SYNTAX_CE, UseElementWithdrawn_SYNERROR);
|
|
|
|
CopyErrors::supply_node(CE, current_sentence);
|
2020-05-06 17:31:53 +03:00
|
|
|
Copies::attach_error(sfsm->ref, CE);
|
2020-03-08 13:33:57 +02:00
|
|
|
}
|