mirror of
https://github.com/ganelson/inform.git
synced 2024-06-17 07:40:47 +03:00
Moved simple tangler out of Inter
This commit is contained in:
parent
30544466f0
commit
6595b35b32
|
@ -1,6 +1,6 @@
|
|||
# Inform 7
|
||||
|
||||
v10.1.0-alpha.1+6T84 'Krypton' (26 November 2021)
|
||||
v10.1.0-alpha.1+6T85 'Krypton' (28 November 2021)
|
||||
|
||||
## About Inform 7
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
Prerelease: alpha.1
|
||||
Build Date: 26 November 2021
|
||||
Build Number: 6T84
|
||||
Build Date: 28 November 2021
|
||||
Build Number: 6T85
|
||||
|
|
|
@ -78,10 +78,9 @@ int InterSkill::build_kit_internally(build_skill *skill, build_step *S,
|
|||
inter_pipeline *SS =
|
||||
ParsingPipelines::from_file(pipeline_as_file, pipeline_vars, search_list);
|
||||
if (SS) {
|
||||
linked_list *inter_paths = NEW_LINKED_LIST(pathname);
|
||||
ADD_TO_LINKED_LIST(S->associated_copy->location_if_path, pathname, inter_paths);
|
||||
linked_list *requirements_list = NEW_LINKED_LIST(attachment_instruction);
|
||||
RunningPipelines::run(NULL, SS, NULL, inter_paths, requirements_list, S->for_vm);
|
||||
RunningPipelines::run(NULL, SS, NULL, S->associated_copy->location_if_path,
|
||||
requirements_list, S->for_vm);
|
||||
return TRUE;
|
||||
} else {
|
||||
Errors::nowhere("build-kit pipeline could not be parsed");
|
||||
|
@ -141,8 +140,7 @@ int InterSkill::code_generate_internally(build_skill *skill, build_step *S,
|
|||
Errors::nowhere("inter pipeline file could not be parsed");
|
||||
return FALSE;
|
||||
}
|
||||
RunningPipelines::run(Filenames::up(S->vertex->as_file),
|
||||
pipeline, Emit::tree(), Kits::inter_paths(Projects::nest_list(project)),
|
||||
RunningPipelines::run(Filenames::up(S->vertex->as_file), pipeline, Emit::tree(), NULL,
|
||||
Projects::list_of_attachment_instructions(project), S->for_vm);
|
||||
LOG("Back end elapsed time: %dcs\n",
|
||||
((int) (clock() - back_end)) / (CLOCKS_PER_SEC/100));
|
||||
|
|
|
@ -92,15 +92,13 @@ form, which would be written to |*outt|.
|
|||
Errors::fatal("-pipeline-text and -pipeline-file cannot be combined with inter files");
|
||||
if ((pipeline_as_file) && (pipeline_as_text))
|
||||
Errors::fatal("-pipeline-text and -pipeline-file are mutually exclusive");
|
||||
linked_list *inter_paths = NEW_LINKED_LIST(pathname);
|
||||
if (kit_to_build) ADD_TO_LINKED_LIST(kit_to_build, pathname, inter_paths);
|
||||
inter_pipeline *SS;
|
||||
if (pipeline_as_file)
|
||||
SS = ParsingPipelines::from_file(pipeline_as_file, pipeline_vars, NULL);
|
||||
else
|
||||
SS = ParsingPipelines::from_text(pipeline_as_text, pipeline_vars);
|
||||
linked_list *requirements_list = NEW_LINKED_LIST(attachment_instruction);
|
||||
if (SS) RunningPipelines::run(domain_path, SS, NULL, inter_paths, requirements_list, NULL);
|
||||
if (SS) RunningPipelines::run(domain_path, SS, NULL, kit_to_build, requirements_list, NULL);
|
||||
else Errors::fatal("pipeline could not be parsed");
|
||||
|
||||
@<Read the list of inter files, and perhaps transcode them@> =
|
||||
|
|
|
@ -20,7 +20,7 @@ void RunningPipelines::clean_pipeline(inter_pipeline *pl) {
|
|||
@ =
|
||||
typedef struct pipeline_step_ephemera {
|
||||
struct filename *parsed_filename;
|
||||
struct linked_list *the_PP; /* of |pathname| */
|
||||
struct pathname *the_kit; /* if one is involved */
|
||||
int to_debugging_log;
|
||||
int from_memory;
|
||||
struct text_stream *to_stream;
|
||||
|
@ -38,7 +38,7 @@ void RunningPipelines::clean_step(pipeline_step *step) {
|
|||
step->ephemera.to_stream = NULL;
|
||||
step->ephemera.to_debugging_log = FALSE;
|
||||
step->ephemera.from_memory = FALSE;
|
||||
step->ephemera.the_PP = NULL;
|
||||
step->ephemera.the_kit = NULL;
|
||||
step->ephemera.repository = NULL;
|
||||
step->ephemera.pipeline = NULL;
|
||||
step->ephemera.requirements_list = NEW_LINKED_LIST(attachment_instruction);
|
||||
|
@ -57,7 +57,7 @@ steps in turn, timing how long each one took us.
|
|||
pipeline_step *currently_running_pipeline_step = NULL;
|
||||
|
||||
void RunningPipelines::run(pathname *P, inter_pipeline *S, inter_tree *I,
|
||||
linked_list *PP, linked_list *requirements_list, target_vm *VM) {
|
||||
pathname *the_kit, linked_list *requirements_list, target_vm *VM) {
|
||||
if (S == NULL) return;
|
||||
if (I) S->ephemera.memory_repository = I;
|
||||
stopwatch_timer *within = NULL;
|
||||
|
@ -97,7 +97,7 @@ void RunningPipelines::run(pathname *P, inter_pipeline *S, inter_tree *I,
|
|||
|
||||
@<Prepare ephemeral data for this step@> =
|
||||
RunningPipelines::clean_step(step);
|
||||
step->ephemera.the_PP = PP;
|
||||
step->ephemera.the_kit = the_kit;
|
||||
if (S->ephemera.repositories[step->repository_argument] == NULL)
|
||||
S->ephemera.repositories[step->repository_argument] = InterTree::new();
|
||||
inter_tree *I = S->ephemera.repositories[step->repository_argument];
|
||||
|
|
|
@ -4,8 +4,7 @@ Two stages which accept raw I6-syntax material in the parse tree, either from
|
|||
imsertions made using Inform 7's low-level features, or after reading the
|
||||
source code for a kit.
|
||||
|
||||
@h The two stages.
|
||||
These stages have more in common than they first appear. Both convert I6T-syntax
|
||||
@ These stages have more in common than first appears. Both convert I6T-syntax
|
||||
source code into a series of |SPLAT_IST| nodes in the Inter tree, with one
|
||||
such node for each different directive in the I6T source.
|
||||
|
||||
|
@ -33,7 +32,7 @@ int ParsingStages::run_load_kit_source(pipeline_step *step) {
|
|||
if (main_package) @<Create a module to hold the Inter read in from this kit@>;
|
||||
simple_tangle_docket docket;
|
||||
@<Make a suitable simple tangler docket@>;
|
||||
SimpleTangler::tangle(&docket, NULL, I"all");
|
||||
SimpleTangler::tangle_web(&docket);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -80,14 +79,12 @@ void ParsingStages::visit_insertions(inter_tree *I, inter_tree_node *P, void *st
|
|||
current_sentence = (parse_node *) Inode::ID_to_ref(P, P->W.data[REF_LINK_IFLD]);
|
||||
#endif
|
||||
simple_tangle_docket *docket = (simple_tangle_docket *) state;
|
||||
SimpleTangler::tangle(docket, insertion, NULL);
|
||||
SimpleTangler::tangle_text(docket, insertion);
|
||||
}
|
||||
|
||||
@ So, then, both of those stages rely on (i) making something called an simple tangler docket,
|
||||
then (ii) calling //SimpleTangler::tangle//.
|
||||
|
||||
Here's where we make the docket, which is really just a collection of settings for
|
||||
the simple tangler. That comes down to:
|
||||
@ So, then, both of those stages rely on making something called an simple
|
||||
tangler docket, which is really just a collection of settings for the
|
||||
simple tangler. That comes down to:
|
||||
|
||||
(a) the place to put any nodes generated,
|
||||
(b) what to do with I6 source code, or with commands embedded in it, or errors
|
||||
|
@ -103,15 +100,12 @@ in |K/Sections|.
|
|||
RunningPipelines::get_symbol(step, plain_ptype_RPSYM));
|
||||
inter_bookmark assimilation_point =
|
||||
Inter::Bookmarks::at_end_of_this_package(assimilation_package);
|
||||
linked_list *L = NEW_LINKED_LIST(pathname);
|
||||
pathname *P;
|
||||
LOOP_OVER_LINKED_LIST(P, pathname, step->ephemera.the_PP)
|
||||
ADD_TO_LINKED_LIST(Pathnames::down(P, I"Sections"), pathname, L);
|
||||
docket = SimpleTangler::new_docket(
|
||||
&(ParsingStages::receive_raw),
|
||||
&(ParsingStages::receive_command),
|
||||
&(ParsingStages::receive_bplus),
|
||||
&(PipelineErrors::kit_error),
|
||||
L, &assimilation_point);
|
||||
step->ephemera.the_kit, &assimilation_point);
|
||||
|
||||
@ Once the I6T reader has unpacked the literate-programming notation, it will
|
||||
reduce the I6T code to pure Inform 6 source together with (perhaps) a handful of
|
||||
|
@ -158,6 +152,15 @@ void ParsingStages::receive_command(OUTPUT_STREAM, text_stream *command,
|
|||
}
|
||||
}
|
||||
|
||||
@ We have similarly withdrawn the ability to write |(+| ... |+)| material
|
||||
in kit files:
|
||||
|
||||
=
|
||||
void ParsingStages::receive_bplus(text_stream *material, simple_tangle_docket *docket) {
|
||||
(*(docket->error_callback))(
|
||||
"use of (+ ... +) in kit source has been withdrawn: '%S'", material);
|
||||
}
|
||||
|
||||
@ We very much do not ignore the raw I6 code read in, though. When the reader
|
||||
gives us a chunk of this, we parse through it with a simple finite-state machine.
|
||||
This can be summarised as "divide the code up at |;| boundaries, sending each
|
||||
|
|
|
@ -1,355 +0,0 @@
|
|||
[SimpleTangler::] Simple Tangler.
|
||||
|
||||
Unravelling (a simple version of) Inweb's literate programming notation to
|
||||
access the tangled content.
|
||||
|
||||
@h The I6T Reader.
|
||||
The rest of this section, then, is a general-purpose reader of I6T-syntax code.
|
||||
Although it is only used for one purpose in the Inform code base, it once had
|
||||
multiple uses, and so it's written quite flexibly. There seems no reason to
|
||||
get rid of that flexibility: perhaps we'll use it again some day.
|
||||
|
||||
So, then, this is the parcel of settings for controlling the I6T reader. The
|
||||
|state| here is not used by the reader itself, but instead allows the callback
|
||||
functions to have a shared state of their own.
|
||||
|
||||
=
|
||||
typedef struct simple_tangle_docket {
|
||||
void (*raw_callback)(struct text_stream *, struct simple_tangle_docket *);
|
||||
void (*command_callback)(struct text_stream *, struct text_stream *,
|
||||
struct text_stream *, struct simple_tangle_docket *);
|
||||
void (*error_callback)(char *, struct text_stream *);
|
||||
void *state;
|
||||
struct linked_list *search_paths; /* of |pathname| */
|
||||
} simple_tangle_docket;
|
||||
|
||||
@ =
|
||||
simple_tangle_docket SimpleTangler::new_docket(
|
||||
void (*A)(struct text_stream *, struct simple_tangle_docket *),
|
||||
void (*B)(struct text_stream *, struct text_stream *,
|
||||
struct text_stream *, struct simple_tangle_docket *),
|
||||
void (*C)(char *, struct text_stream *),
|
||||
linked_list *search_list, void *initial_state) {
|
||||
simple_tangle_docket docket;
|
||||
docket.raw_callback = A;
|
||||
docket.command_callback = B;
|
||||
docket.error_callback = C;
|
||||
docket.state = initial_state;
|
||||
docket.search_paths = search_list;
|
||||
return docket;
|
||||
}
|
||||
|
||||
@ I6T files use a literate programming notation which is, in effect, a much
|
||||
simplified version of Inweb's. (Note that Inweb can therefore read kits as
|
||||
if they were webs, and we use that to weave them for the source website.)
|
||||
|
||||
Many Inweb syntaxes are, however, not allowed in I6T: really, you should use
|
||||
only |@h| headings and the |=| sign to divide commentary from text. Macros and
|
||||
definitions, in particular, are not permitted; I6T is not really tangled as such.
|
||||
|
||||
The entire range of possibilities is shown here:
|
||||
= (text as Inweb)
|
||||
Circuses.
|
||||
|
||||
This hypothetical I6T file provides support for holding circuses.
|
||||
|
||||
@h Start.
|
||||
This routine is called when a big top must be raised. Note that the
|
||||
elephants must first be watered (see Livestock.i6t).
|
||||
|
||||
=
|
||||
[ RaiseBT c;
|
||||
...
|
||||
];
|
||||
=
|
||||
...and so on. As with Inweb, the commentary is removed when we read this
|
||||
code. While this doesn't allow for full-on literate programming, it does
|
||||
permit a generous amount of annotation.
|
||||
|
||||
@ One restriction. It actually doesn't matter if a template file contains
|
||||
lines longer than this, so long as they do not occur inside |{-lines:...}| and
|
||||
|{-endlines}|, and so long as no individual braced command |{-...}| exceeds
|
||||
this length.
|
||||
|
||||
@d MAX_I6T_LINE_LENGTH 1024
|
||||
|
||||
@ The I6T interpreter is then a single routine to implement the description
|
||||
above, though note that it can act on interventions as well. (But in modern
|
||||
Inform usage, often there won't be any, because templates for the Standard
|
||||
Rules and so forth are assimilated in stand-alone runs of the code generator,
|
||||
and therefore no interventions will have happened.)
|
||||
|
||||
=
|
||||
void SimpleTangler::tangle(simple_tangle_docket *docket, text_stream *insertion, text_stream *segment) {
|
||||
TEMPORARY_TEXT(T)
|
||||
SimpleTangler::tangle_L2(T, insertion, segment, -1, docket, NULL);
|
||||
(*(docket->raw_callback))(T, docket);
|
||||
DISCARD_TEXT(T)
|
||||
}
|
||||
|
||||
void SimpleTangler::tangle_L2(OUTPUT_STREAM, text_stream *sf,
|
||||
text_stream *segment_name, int N_escape, simple_tangle_docket *docket, filename *Input_Filename) {
|
||||
if (Str::eq(segment_name, I"all")) {
|
||||
pathname *K;
|
||||
LOOP_OVER_LINKED_LIST(K, pathname, docket->search_paths) {
|
||||
pathname *P = Pathnames::up(K);
|
||||
web_md *Wm = WebMetadata::get(P, NULL, V2_SYNTAX, NULL, FALSE, TRUE, NULL);
|
||||
chapter_md *Cm;
|
||||
LOOP_OVER_LINKED_LIST(Cm, chapter_md, Wm->chapters_md) {
|
||||
section_md *Sm;
|
||||
LOOP_OVER_LINKED_LIST(Sm, section_md, Cm->sections_md) {
|
||||
filename *SF = Sm->source_file_for_section;
|
||||
SimpleTangler::tangle_L3(OUT, sf, Sm->sect_title, N_escape, docket, SF);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
SimpleTangler::tangle_L3(OUT, sf, segment_name, N_escape, docket, Input_Filename);
|
||||
}
|
||||
|
||||
void SimpleTangler::tangle_L3(OUTPUT_STREAM, text_stream *sf,
|
||||
text_stream *segment_name, int N_escape, simple_tangle_docket *docket, filename *Input_Filename) {
|
||||
TEMPORARY_TEXT(heading_name)
|
||||
int skip_part = FALSE, comment = TRUE, extract = FALSE;
|
||||
int col = 1, cr, sfp = 0;
|
||||
|
||||
FILE *Input_File = NULL;
|
||||
if ((Str::len(segment_name) > 0) || (Input_Filename)) {
|
||||
@<Open the I6 template file@>;
|
||||
comment = TRUE;
|
||||
} else comment = FALSE;
|
||||
|
||||
@<Interpret the I6T file@>;
|
||||
|
||||
if (Input_File) { if (DL) STREAM_FLUSH(DL); fclose(Input_File); }
|
||||
|
||||
DISCARD_TEXT(heading_name)
|
||||
}
|
||||
|
||||
@ We look for the |.i6t| files in a list of possible locations supplied as
|
||||
part of the I6T docket.
|
||||
|
||||
@<Open the I6 template file@> =
|
||||
if (Input_Filename)
|
||||
Input_File = Filenames::fopen(Input_Filename, "r");
|
||||
pathname *P;
|
||||
LOOP_OVER_LINKED_LIST(P, pathname, docket->search_paths)
|
||||
if (Input_File == NULL)
|
||||
Input_File = Filenames::fopen(
|
||||
Filenames::in(P, segment_name), "r");
|
||||
if (Input_File == NULL)
|
||||
(*(docket->error_callback))("unable to open the template segment '%S'", segment_name);
|
||||
|
||||
@
|
||||
|
||||
@<Interpret the I6T file@> =
|
||||
TEMPORARY_TEXT(command)
|
||||
TEMPORARY_TEXT(argument)
|
||||
do {
|
||||
Str::clear(command);
|
||||
Str::clear(argument);
|
||||
@<Read next character from I6T stream@>;
|
||||
NewCharacter: if (cr == EOF) break;
|
||||
if (((cr == '@') || (cr == '=')) && (col == 1)) {
|
||||
int inweb_syntax = -1;
|
||||
if (cr == '=') @<Read the rest of line as an equals-heading@>
|
||||
else @<Read the rest of line as an at-heading@>;
|
||||
@<Act on the heading, going in or out of comment mode as appropriate@>;
|
||||
continue;
|
||||
}
|
||||
if (comment == FALSE) @<Deal with material which isn't commentary@>;
|
||||
} while (cr != EOF);
|
||||
DISCARD_TEXT(command)
|
||||
DISCARD_TEXT(argument)
|
||||
|
||||
|
||||
@ I6 template files are encoded as ISO Latin-1, not as Unicode UTF-8, so
|
||||
ordinary |fgetc| is used, and no BOM marker is parsed. Lines are assumed
|
||||
to be terminated with either |0x0a| or |0x0d|. (Since blank lines are
|
||||
harmless, we take no trouble over |0a0d| or |0d0a| combinations.) The
|
||||
built-in template files, almost always the only ones used, are line
|
||||
terminated |0x0a| in Unix fashion.
|
||||
|
||||
@<Read next character from I6T stream@> =
|
||||
if (Input_File) cr = fgetc(Input_File);
|
||||
else if (sf) {
|
||||
cr = Str::get_at(sf, sfp); if (cr == 0) cr = EOF; else sfp++;
|
||||
} else cr = EOF;
|
||||
col++; if ((cr == 10) || (cr == 13)) col = 0;
|
||||
|
||||
@ Anything following an at-character in the first column is looked at to see if
|
||||
it's a heading, that is, an Inweb syntax. We recognise both |@h| and |@p| as
|
||||
heading markers, in order to accommodate both old and new Inweb syntaxes.
|
||||
|
||||
@d INWEB_PARAGRAPH_SYNTAX 1
|
||||
@d INWEB_CODE_SYNTAX 2
|
||||
@d INWEB_DASH_SYNTAX 3
|
||||
@d INWEB_PURPOSE_SYNTAX 4
|
||||
@d INWEB_FIGURE_SYNTAX 5
|
||||
@d INWEB_EQUALS_SYNTAX 6
|
||||
@d INWEB_EXTRACT_SYNTAX 7
|
||||
|
||||
@<Read the rest of line as an at-heading@> =
|
||||
TEMPORARY_TEXT(I6T_buffer)
|
||||
int i = 0, committed = FALSE, unacceptable_character = FALSE;
|
||||
while (i<MAX_I6T_LINE_LENGTH) {
|
||||
@<Read next character from I6T stream@>;
|
||||
if ((committed == FALSE) && ((cr == 10) || (cr == 13) || (cr == ' '))) {
|
||||
if (Str::eq_wide_string(I6T_buffer, L"p"))
|
||||
inweb_syntax = INWEB_PARAGRAPH_SYNTAX;
|
||||
else if (Str::eq_wide_string(I6T_buffer, L"h"))
|
||||
inweb_syntax = INWEB_PARAGRAPH_SYNTAX;
|
||||
else if (Str::eq_wide_string(I6T_buffer, L"c"))
|
||||
inweb_syntax = INWEB_CODE_SYNTAX;
|
||||
else if (Str::get_first_char(I6T_buffer) == '-')
|
||||
inweb_syntax = INWEB_DASH_SYNTAX;
|
||||
else if (Str::begins_with_wide_string(I6T_buffer, L"Purpose:"))
|
||||
inweb_syntax = INWEB_PURPOSE_SYNTAX;
|
||||
committed = TRUE;
|
||||
if (inweb_syntax == -1) {
|
||||
if (unacceptable_character == FALSE) {
|
||||
PUT_TO(OUT, '@');
|
||||
WRITE_TO(OUT, "%S", I6T_buffer);
|
||||
PUT_TO(OUT, cr);
|
||||
break;
|
||||
} else {
|
||||
LOG("heading begins: <%S>\n", I6T_buffer);
|
||||
(*(docket->error_callback))(
|
||||
"unknown '@...' marker at column 0 in template matter: '%S'", I6T_buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!(((cr >= 'A') && (cr <= 'Z')) || ((cr >= 'a') && (cr <= 'z'))
|
||||
|| ((cr >= '0') && (cr <= '9'))
|
||||
|| (cr == '-') || (cr == '>') || (cr == ':') || (cr == '_')))
|
||||
unacceptable_character = TRUE;
|
||||
if ((cr == 10) || (cr == 13)) break;
|
||||
PUT_TO(I6T_buffer, cr);
|
||||
}
|
||||
Str::copy(command, I6T_buffer);
|
||||
DISCARD_TEXT(I6T_buffer)
|
||||
|
||||
@<Read the rest of line as an equals-heading@> =
|
||||
TEMPORARY_TEXT(I6T_buffer)
|
||||
int i = 0;
|
||||
while (i<MAX_I6T_LINE_LENGTH) {
|
||||
@<Read next character from I6T stream@>;
|
||||
if ((cr == 10) || (cr == 13)) break;
|
||||
PUT_TO(I6T_buffer, cr);
|
||||
}
|
||||
DISCARD_TEXT(I6T_buffer)
|
||||
match_results mr = Regexp::create_mr();
|
||||
if (Regexp::match(&mr, I6T_buffer, L" %(text%c*%) *")) {
|
||||
inweb_syntax = INWEB_EXTRACT_SYNTAX;
|
||||
} else if (Regexp::match(&mr, I6T_buffer, L" %(figure%c*%) *")) {
|
||||
inweb_syntax = INWEB_FIGURE_SYNTAX;
|
||||
} else if (Regexp::match(&mr, I6T_buffer, L" %(%c*%) *")) {
|
||||
(*(docket->error_callback))(
|
||||
"unsupported '= (...)' marker at column 0 in template matter", NULL);
|
||||
} else {
|
||||
inweb_syntax = INWEB_EQUALS_SYNTAX;
|
||||
}
|
||||
Regexp::dispose_of(&mr);
|
||||
|
||||
@ As can be seen, only a small minority of Inweb syntaxes are allowed:
|
||||
in particular, no definitions| or angle-bracketed macros. This reader is not
|
||||
a full-fledged tangler.
|
||||
|
||||
@<Act on the heading, going in or out of comment mode as appropriate@> =
|
||||
switch (inweb_syntax) {
|
||||
case INWEB_PARAGRAPH_SYNTAX: {
|
||||
Str::copy_tail(heading_name, command, 2);
|
||||
int c;
|
||||
while (((c = Str::get_last_char(heading_name)) != 0) &&
|
||||
((c == ' ') || (c == '\t') || (c == '.')))
|
||||
Str::delete_last_character(heading_name);
|
||||
if (Str::len(heading_name) == 0)
|
||||
(*(docket->error_callback))("Empty heading name in I6 template file", NULL);
|
||||
extract = FALSE;
|
||||
comment = TRUE; skip_part = FALSE;
|
||||
break;
|
||||
}
|
||||
case INWEB_CODE_SYNTAX:
|
||||
extract = FALSE;
|
||||
if (skip_part == FALSE) comment = FALSE;
|
||||
break;
|
||||
case INWEB_EQUALS_SYNTAX:
|
||||
if (extract) {
|
||||
comment = TRUE; extract = FALSE;
|
||||
} else {
|
||||
if (skip_part == FALSE) comment = FALSE;
|
||||
}
|
||||
break;
|
||||
case INWEB_EXTRACT_SYNTAX:
|
||||
comment = TRUE; extract = TRUE;
|
||||
break;
|
||||
case INWEB_DASH_SYNTAX: break;
|
||||
case INWEB_PURPOSE_SYNTAX: break;
|
||||
case INWEB_FIGURE_SYNTAX: break;
|
||||
}
|
||||
|
||||
@<Deal with material which isn't commentary@> =
|
||||
if (cr == '{') {
|
||||
@<Read next character from I6T stream@>;
|
||||
if (cr == '-') {
|
||||
@<Read up to the next close brace as an I6T command and argument@>;
|
||||
if (Str::get_first_char(command) == '!') continue;
|
||||
(*(docket->command_callback))(OUT, command, argument, docket);
|
||||
continue;
|
||||
} else if ((cr == 'N') && (N_escape >= 0)) {
|
||||
@<Read next character from I6T stream@>;
|
||||
if (cr == '}') {
|
||||
WRITE("%d", N_escape);
|
||||
continue;
|
||||
}
|
||||
WRITE("{N");
|
||||
goto NewCharacter;
|
||||
} else { /* otherwise the open brace was a literal */
|
||||
PUT_TO(OUT, '{');
|
||||
goto NewCharacter;
|
||||
}
|
||||
}
|
||||
if (cr == '(') {
|
||||
@<Read next character from I6T stream@>;
|
||||
if (cr == '+') {
|
||||
@<Read up to the next plus close-bracket as an I7 expression@>;
|
||||
continue;
|
||||
} else { /* otherwise the open bracket was a literal */
|
||||
PUT_TO(OUT, '(');
|
||||
goto NewCharacter;
|
||||
}
|
||||
}
|
||||
PUT_TO(OUT, cr);
|
||||
|
||||
@ And here we read a normal command. The command name must not include |}|
|
||||
or |:|. If there is no |:| then the argument is left unset (so that it will
|
||||
be the empty string: see above). The argument must not include |}|.
|
||||
|
||||
@<Read up to the next close brace as an I6T command and argument@> =
|
||||
Str::clear(command);
|
||||
Str::clear(argument);
|
||||
int com_mode = TRUE;
|
||||
while (TRUE) {
|
||||
@<Read next character from I6T stream@>;
|
||||
if ((cr == '}') || (cr == EOF)) break;
|
||||
if ((cr == ':') && (com_mode)) { com_mode = FALSE; continue; }
|
||||
if (com_mode) PUT_TO(command, cr);
|
||||
else PUT_TO(argument, cr);
|
||||
}
|
||||
|
||||
@ And similarly, for the |(+| ... |+)| notation used to mark I7 material
|
||||
within I6:
|
||||
|
||||
@<Read up to the next plus close-bracket as an I7 expression@> =
|
||||
TEMPORARY_TEXT(i7_exp)
|
||||
while (TRUE) {
|
||||
@<Read next character from I6T stream@>;
|
||||
if (cr == EOF) break;
|
||||
if ((cr == ')') && (Str::get_last_char(i7_exp) == '+')) {
|
||||
Str::delete_last_character(i7_exp); break; }
|
||||
PUT_TO(i7_exp, cr);
|
||||
}
|
||||
DISCARD_TEXT(i7_exp)
|
||||
(*(docket->error_callback))(
|
||||
"use of (+ ... +) in the template has been withdrawn: '%S'", i7_exp);
|
|
@ -21,7 +21,6 @@ Chapter 3: Linking Stages
|
|||
Load Binary Kits Stage
|
||||
Parsing Stages
|
||||
Parse Linked Matter
|
||||
Simple Tangler
|
||||
Resolving Conditional Compilation
|
||||
Assimilate
|
||||
Resolve External Symbols
|
||||
|
|
Loading…
Reference in a new issue