1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-06-26 04:00:43 +03:00

Removed need to declare SENTENCE_NODE when using syntax module

This commit is contained in:
Graham Nelson 2020-03-26 09:59:32 +00:00
parent 9aa6176dc0
commit 3c59521ab7
6 changed files with 97 additions and 109 deletions

View file

@ -1,7 +1,7 @@
[Main::] Main.
The top level, which decides what is to be done and then carries
this plan out.
A command-line interface for Inbuild functions which are not part of the
normal operation of the Inform compiler.
@h Main routine.
@ -39,6 +39,7 @@ int main(int argc, char **argv) {
InbuildModule::start();
targets = NEW_LINKED_LIST(inbuild_copy);
@<Read the command line@>;
@<Manage Inbuild@>;
if (Str::len(unit_test) > 0) dry_run_mode = TRUE;
int use = SHELL_METHODOLOGY;
@ -97,7 +98,64 @@ int main(int argc, char **argv) {
return 0;
}
@ We use Foundation to read the command line:
@<Manage Inbuild@> =
if (LinkedLists::len(unsorted_nest_list) == 0)
Inbuild::add_nest(
Pathnames::from_text(I"inform7/Internal"), INTERNAL_NEST_TAG);
path_to_inbuild = Pathnames::installation_path("INBUILD_PATH", I"inbuild");
pathname *P = Pathnames::subfolder(path_to_inbuild, I"Tangled");
filename *S = Filenames::in_folder(P, I"Syntax.preform");
wording W = Preform::load_from_file(S);
Preform::parse_preform(W, FALSE);
CommandLine::play_back_log();
inbuild_copy *proj = NULL, *C;
LOOP_OVER_LINKED_LIST(C, inbuild_copy, targets)
if (C->edition->work->genre == project_bundle_genre) {
if (Str::len(project_bundle_request) > 0)
Errors::with_text("can only work on one project bundle at a time, so ignoring '%S'", C->edition->work->title);
else if (proj) Errors::with_text("can only work on one project bundle at a time, so ignoring '%S'", C->edition->work->title);
else proj = C;
}
proj = Inbuild::optioneering_complete(proj, FALSE);
if (proj) {
int found = FALSE;
LOOP_OVER_LINKED_LIST(C, inbuild_copy, targets)
if (C == proj)
found = TRUE;
if (found == FALSE) ADD_TO_LINKED_LIST(proj, inbuild_copy, targets);
}
inbuild_nest_list = Inbuild::nest_list();
Inbuild::go_operational();
@ =
void Main::load_many(pathname *P) {
scan_directory *D = Directories::open(P);
TEMPORARY_TEXT(LEAFNAME);
while (Directories::next(D, LEAFNAME)) {
TEMPORARY_TEXT(FILENAME);
WRITE_TO(FILENAME, "%p%c%S", P, FOLDER_SEPARATOR, LEAFNAME);
Main::load_one(FILENAME, FALSE);
DISCARD_TEXT(FILENAME);
}
DISCARD_TEXT(LEAFNAME);
Directories::close(D);
}
void Main::load_one(text_stream *arg, int throwing_error) {
inbuild_copy *C = Copies::claim(arg);
if (C == NULL) {
if (throwing_error) Errors::with_text("unable to identify '%S'", arg);
return;
}
ADD_TO_LINKED_LIST(C, inbuild_copy, targets);
}
@h Command line.
Note the call below to |Inbuild::declare_options|, which adds a whole lot of
other options to the selection defined here.
@e BUILD_CLSW
@e REBUILD_CLSW
@ -156,38 +214,9 @@ int main(int argc, char **argv) {
CommandLine::read(argc, argv, NULL, &Main::option, &Main::bareword);
if (LinkedLists::len(unsorted_nest_list) == 0)
Inbuild::add_nest(
Pathnames::from_text(I"inform7/Internal"), INTERNAL_NEST_TAG);
@ Here we handle those options not handled by the |inbuild| module.
path_to_inbuild = Pathnames::installation_path("INBUILD_PATH", I"inbuild");
pathname *P = Pathnames::subfolder(path_to_inbuild, I"Tangled");
filename *S = Filenames::in_folder(P, I"Syntax.preform");
wording W = Preform::load_from_file(S);
Preform::parse_preform(W, FALSE);
CommandLine::play_back_log();
inbuild_copy *proj = NULL, *C;
LOOP_OVER_LINKED_LIST(C, inbuild_copy, targets)
if (C->edition->work->genre == project_bundle_genre) {
if (Str::len(project_bundle_request) > 0)
Errors::with_text("can only work on one project bundle at a time, so ignoring '%S'", C->edition->work->title);
else if (proj) Errors::with_text("can only work on one project bundle at a time, so ignoring '%S'", C->edition->work->title);
else proj = C;
}
proj = Inbuild::optioneering_complete(proj, FALSE);
if (proj) {
int found = FALSE;
LOOP_OVER_LINKED_LIST(C, inbuild_copy, targets)
if (C == proj)
found = TRUE;
if (found == FALSE) ADD_TO_LINKED_LIST(proj, inbuild_copy, targets);
}
inbuild_nest_list = Inbuild::nest_list();
Inbuild::go_operational();
@ =
=
void Main::option(int id, int val, text_stream *arg, void *state) {
switch (id) {
case BUILD_CLSW: inbuild_task = BUILD_TTASK; break;
@ -219,46 +248,29 @@ void Main::option(int id, int val, text_stream *arg, void *state) {
Inbuild::option(id, val, arg, state);
}
@ This is called for a command-line argument which doesn't appear as
subordinate to any switch; we take it as the name of a copy.
=
void Main::bareword(int id, text_stream *arg, void *state) {
Main::load_one(arg, TRUE);
}
void Main::load_many(pathname *P) {
scan_directory *D = Directories::open(P);
TEMPORARY_TEXT(LEAFNAME);
while (Directories::next(D, LEAFNAME)) {
TEMPORARY_TEXT(FILENAME);
WRITE_TO(FILENAME, "%p%c%S", P, FOLDER_SEPARATOR, LEAFNAME);
Main::load_one(FILENAME, FALSE);
DISCARD_TEXT(FILENAME);
}
DISCARD_TEXT(LEAFNAME);
Directories::close(D);
}
@h Interface to Words module.
Since we want to include the |words| module, we have to define the following
structure and initialiser. The type |vocabulary_meaning| is expected to hold
meanings associated with a given word; when |inform7| uses |word| it is rich
and full of significance, but for us it does nothing. We give it a meaningless
integer as its content, since in C it isn't legal to have an empty |struct|.
void Main::load_one(text_stream *arg, int throwing_error) {
inbuild_copy *C = Copies::claim(arg);
if (C == NULL) {
if (throwing_error) Errors::with_text("unable to identify '%S'", arg);
return;
}
ADD_TO_LINKED_LIST(C, inbuild_copy, targets);
}
@ Since we want to include the words module, we have to define the following
structure and initialiser:
@d VOCABULARY_MEANING_INITIALISER Main::ignore
@d VOCABULARY_MEANING_INITIALISER Main::create_meaningless_vm
=
typedef struct vocabulary_meaning {
int enigmatic_number;
} vocabulary_meaning;
@
=
vocabulary_meaning Main::ignore(vocabulary_entry *ve) {
vocabulary_meaning Main::create_meaningless_vm(vocabulary_entry *ve) {
vocabulary_meaning vm;
vm.enigmatic_number = 90125;
return vm;
@ -268,7 +280,7 @@ vocabulary_meaning Main::ignore(vocabulary_entry *ve) {
@d PREFORM_LANGUAGE_TYPE void
@d PARSE_TREE_TRAVERSE_TYPE void
@d SENTENCE_NODE Main::sentence_level
@d CCCCSENTENCE_NODE Main::sentence_level
@d PARSE_TREE_METADATA_SETUP SourceText::node_metadata
=

View file

@ -910,7 +910,7 @@ void ParseTree::traverse_from(parse_node *pn, void (*visitor)(parse_node *)) {
for (; pn; pn = pn->next) {
if (ParseTree::top_level(pn->node_type)) ParseTree::traverse_from(pn->down, visitor);
if (ParseTree::visitable(pn->node_type)) {
if (SENTENCE_NODE(pn->node_type)) current_sentence = pn;
if (ParseTree::sentence_node(pn->node_type)) current_sentence = pn;
(*visitor)(pn);
}
}
@ -923,7 +923,7 @@ void ParseTree::traverse_dfirst_from(parse_node *pn, void (*visitor)(parse_node
parse_node *SCS = current_sentence;
for (; pn; pn = pn->next) {
ParseTree::traverse_dfirst_from(pn->down, visitor);
if (SENTENCE_NODE(pn->node_type)) current_sentence = pn;
if (ParseTree::sentence_node(pn->node_type)) current_sentence = pn;
(*visitor)(pn);
}
current_sentence = SCS;
@ -934,7 +934,7 @@ void ParseTree::traverse_wfirst(parse_node_tree *T, void (*visitor)(parse_node *
void ParseTree::traverse_wfirst_from(parse_node *pn, void (*visitor)(parse_node *)) {
parse_node *SCS = current_sentence;
for (; pn; pn = pn->next) {
if (SENTENCE_NODE(pn->node_type)) current_sentence = pn;
if (ParseTree::sentence_node(pn->node_type)) current_sentence = pn;
ParseTree::traverse_wfirst_from(pn->down, visitor);
(*visitor)(pn);
}
@ -949,7 +949,7 @@ void ParseTree::traverse_from_with_stream(text_stream *OUT, parse_node *pn, void
if (ParseTree::top_level(pn->node_type))
ParseTree::traverse_from_with_stream(OUT, pn->down, visitor);
if (ParseTree::visitable(pn->node_type)) {
if (SENTENCE_NODE(pn->node_type)) current_sentence = pn;
if (ParseTree::sentence_node(pn->node_type)) current_sentence = pn;
(*visitor)(OUT, pn);
}
}
@ -963,7 +963,7 @@ void ParseTree::traverse_from_int(parse_node *pn, void (*visitor)(parse_node *,
for (; pn; pn = pn->next) {
if (ParseTree::top_level(pn->node_type)) ParseTree::traverse_from_int(pn->down, visitor, X);
if (ParseTree::visitable(pn->node_type)) {
if (SENTENCE_NODE(pn->node_type)) current_sentence = pn;
if (ParseTree::sentence_node(pn->node_type)) current_sentence = pn;
(*visitor)(pn, X);
}
}
@ -977,7 +977,7 @@ void ParseTree::traverse_from_int_int(parse_node *pn, void (*visitor)(parse_node
for (; pn; pn = pn->next) {
if (ParseTree::top_level(pn->node_type)) ParseTree::traverse_from_int_int(pn->down, visitor, X, Y);
if (ParseTree::visitable(pn->node_type)) {
if (SENTENCE_NODE(pn->node_type)) current_sentence = pn;
if (ParseTree::sentence_node(pn->node_type)) current_sentence = pn;
(*visitor)(pn, X, Y);
}
}
@ -991,7 +991,7 @@ void ParseTree::traverse_from_ppn(parse_node *pn, void (*visitor)(parse_node *,
for (; pn; pn = pn->next) {
if (ParseTree::top_level(pn->node_type)) ParseTree::traverse_from_ppn(pn->down, visitor, X);
if (ParseTree::visitable(pn->node_type)) {
if (SENTENCE_NODE(pn->node_type)) current_sentence = pn;
if (ParseTree::sentence_node(pn->node_type)) current_sentence = pn;
(*visitor)(pn, X);
}
}
@ -1010,7 +1010,7 @@ void ParseTree::traverse_from_ppni(parse_node_tree *T, parse_node *pn, void (*vi
ParseTree::traverse_from_ppni(T, pn->down, visitor, H0, N);
}
if (ParseTree::visitable(pn->node_type)) {
if (SENTENCE_NODE(pn->node_type)) current_sentence = pn;
if (ParseTree::sentence_node(pn->node_type)) current_sentence = pn;
(*visitor)(T, pn, last_h0, N);
}
}
@ -1029,7 +1029,7 @@ int ParseTree::traverse_from_up_to_ip(parse_node *end, parse_node *pn, void (*vi
}
}
if (ParseTree::visitable(pn->node_type)) {
if (SENTENCE_NODE(pn->node_type)) current_sentence = pn;
if (ParseTree::sentence_node(pn->node_type)) current_sentence = pn;
(*visitor)(pn, X);
}
}
@ -1055,6 +1055,18 @@ int ParseTree::traverse_from_ppn_nocs(parse_node *pn, int (*visitor)(parse_node
return FALSE;
}
@ This provides a way for users of the module to indicate what's a sentence:
=
int ParseTree::sentence_node(node_type_t t) {
#ifdef SENTENCE_NODE
return SENTENCE_NODE(t);
#endif
#ifndef SENTENCE_NODE
return FALSE;
#endif
}
@h Verify integrity.
The first duty of a tree is to contain no loops, and the following checks
that (rejecting even undirected loops). In addition, it checks that each

View file

@ -150,10 +150,3 @@ void Basics::preform_problem_handler(word_assemblage base_text, nonterminal *nt,
@
@d PARSE_TREE_TRAVERSE_TYPE void
@d SENTENCE_NODE Basics::sentence_level
=
int Basics::sentence_level(node_type_t t) {
return FALSE;
}

View file

@ -155,15 +155,6 @@ void Basics::preform_problem_handler(word_assemblage base_text, nonterminal *nt,
@
@d PARSE_TREE_TRAVERSE_TYPE void
@d SENTENCE_NODE Basics::sentence_level
=
int Basics::sentence_level(node_type_t t) {
return FALSE;
}
@
@d ADJECTIVE_MEANING_TYPE void
@d VERB_MEANING_EQUALITY vc_be
@d VERB_MEANING_POSSESSION vc_have

View file

@ -156,15 +156,6 @@ void Basics::preform_problem_handler(word_assemblage base_text, nonterminal *nt,
@
@d PARSE_TREE_TRAVERSE_TYPE void
@d SENTENCE_NODE Basics::sentence_level
=
int Basics::sentence_level(node_type_t t) {
return FALSE;
}
@
@d ADJECTIVE_MEANING_TYPE void
@d VERB_MEANING_EQUALITY vc_be
@d VERB_MEANING_POSSESSION vc_have

View file

@ -150,15 +150,4 @@ void Basics::preform_problem_handler(word_assemblage base_text, nonterminal *nt,
@
@d PARSE_TREE_TRAVERSE_TYPE void
@d SENTENCE_NODE Basics::sentence_level
=
int Basics::sentence_level(node_type_t t) {
return FALSE;
}
@
@d NO_HEADING_LEVELS 10