mirror of
https://github.com/ganelson/inform.git
synced 2024-07-01 06:24:58 +03:00
Removed need to declare SENTENCE_NODE when using syntax module
This commit is contained in:
parent
9aa6176dc0
commit
3c59521ab7
|
@ -1,7 +1,7 @@
|
||||||
[Main::] Main.
|
[Main::] Main.
|
||||||
|
|
||||||
The top level, which decides what is to be done and then carries
|
A command-line interface for Inbuild functions which are not part of the
|
||||||
this plan out.
|
normal operation of the Inform compiler.
|
||||||
|
|
||||||
@h Main routine.
|
@h Main routine.
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@ int main(int argc, char **argv) {
|
||||||
InbuildModule::start();
|
InbuildModule::start();
|
||||||
targets = NEW_LINKED_LIST(inbuild_copy);
|
targets = NEW_LINKED_LIST(inbuild_copy);
|
||||||
@<Read the command line@>;
|
@<Read the command line@>;
|
||||||
|
@<Manage Inbuild@>;
|
||||||
|
|
||||||
if (Str::len(unit_test) > 0) dry_run_mode = TRUE;
|
if (Str::len(unit_test) > 0) dry_run_mode = TRUE;
|
||||||
int use = SHELL_METHODOLOGY;
|
int use = SHELL_METHODOLOGY;
|
||||||
|
@ -97,7 +98,64 @@ int main(int argc, char **argv) {
|
||||||
return 0;
|
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 BUILD_CLSW
|
||||||
@e REBUILD_CLSW
|
@e REBUILD_CLSW
|
||||||
|
@ -156,38 +214,9 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
CommandLine::read(argc, argv, NULL, &Main::option, &Main::bareword);
|
CommandLine::read(argc, argv, NULL, &Main::option, &Main::bareword);
|
||||||
|
|
||||||
if (LinkedLists::len(unsorted_nest_list) == 0)
|
@ Here we handle those options not handled by the |inbuild| module.
|
||||||
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::option(int id, int val, text_stream *arg, void *state) {
|
void Main::option(int id, int val, text_stream *arg, void *state) {
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case BUILD_CLSW: inbuild_task = BUILD_TTASK; break;
|
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);
|
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) {
|
void Main::bareword(int id, text_stream *arg, void *state) {
|
||||||
Main::load_one(arg, TRUE);
|
Main::load_one(arg, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Main::load_many(pathname *P) {
|
@h Interface to Words module.
|
||||||
scan_directory *D = Directories::open(P);
|
Since we want to include the |words| module, we have to define the following
|
||||||
TEMPORARY_TEXT(LEAFNAME);
|
structure and initialiser. The type |vocabulary_meaning| is expected to hold
|
||||||
while (Directories::next(D, LEAFNAME)) {
|
meanings associated with a given word; when |inform7| uses |word| it is rich
|
||||||
TEMPORARY_TEXT(FILENAME);
|
and full of significance, but for us it does nothing. We give it a meaningless
|
||||||
WRITE_TO(FILENAME, "%p%c%S", P, FOLDER_SEPARATOR, LEAFNAME);
|
integer as its content, since in C it isn't legal to have an empty |struct|.
|
||||||
Main::load_one(FILENAME, FALSE);
|
|
||||||
DISCARD_TEXT(FILENAME);
|
|
||||||
}
|
|
||||||
DISCARD_TEXT(LEAFNAME);
|
|
||||||
Directories::close(D);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Main::load_one(text_stream *arg, int throwing_error) {
|
@d VOCABULARY_MEANING_INITIALISER Main::create_meaningless_vm
|
||||||
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
|
|
||||||
|
|
||||||
=
|
=
|
||||||
typedef struct vocabulary_meaning {
|
typedef struct vocabulary_meaning {
|
||||||
int enigmatic_number;
|
int enigmatic_number;
|
||||||
} vocabulary_meaning;
|
} vocabulary_meaning;
|
||||||
|
|
||||||
@
|
vocabulary_meaning Main::create_meaningless_vm(vocabulary_entry *ve) {
|
||||||
|
|
||||||
=
|
|
||||||
vocabulary_meaning Main::ignore(vocabulary_entry *ve) {
|
|
||||||
vocabulary_meaning vm;
|
vocabulary_meaning vm;
|
||||||
vm.enigmatic_number = 90125;
|
vm.enigmatic_number = 90125;
|
||||||
return vm;
|
return vm;
|
||||||
|
@ -268,7 +280,7 @@ vocabulary_meaning Main::ignore(vocabulary_entry *ve) {
|
||||||
|
|
||||||
@d PREFORM_LANGUAGE_TYPE void
|
@d PREFORM_LANGUAGE_TYPE void
|
||||||
@d PARSE_TREE_TRAVERSE_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
|
@d PARSE_TREE_METADATA_SETUP SourceText::node_metadata
|
||||||
|
|
||||||
=
|
=
|
||||||
|
|
|
@ -910,7 +910,7 @@ void ParseTree::traverse_from(parse_node *pn, void (*visitor)(parse_node *)) {
|
||||||
for (; pn; pn = pn->next) {
|
for (; pn; pn = pn->next) {
|
||||||
if (ParseTree::top_level(pn->node_type)) ParseTree::traverse_from(pn->down, visitor);
|
if (ParseTree::top_level(pn->node_type)) ParseTree::traverse_from(pn->down, visitor);
|
||||||
if (ParseTree::visitable(pn->node_type)) {
|
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);
|
(*visitor)(pn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -923,7 +923,7 @@ void ParseTree::traverse_dfirst_from(parse_node *pn, void (*visitor)(parse_node
|
||||||
parse_node *SCS = current_sentence;
|
parse_node *SCS = current_sentence;
|
||||||
for (; pn; pn = pn->next) {
|
for (; pn; pn = pn->next) {
|
||||||
ParseTree::traverse_dfirst_from(pn->down, visitor);
|
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);
|
(*visitor)(pn);
|
||||||
}
|
}
|
||||||
current_sentence = SCS;
|
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 *)) {
|
void ParseTree::traverse_wfirst_from(parse_node *pn, void (*visitor)(parse_node *)) {
|
||||||
parse_node *SCS = current_sentence;
|
parse_node *SCS = current_sentence;
|
||||||
for (; pn; pn = pn->next) {
|
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);
|
ParseTree::traverse_wfirst_from(pn->down, visitor);
|
||||||
(*visitor)(pn);
|
(*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))
|
if (ParseTree::top_level(pn->node_type))
|
||||||
ParseTree::traverse_from_with_stream(OUT, pn->down, visitor);
|
ParseTree::traverse_from_with_stream(OUT, pn->down, visitor);
|
||||||
if (ParseTree::visitable(pn->node_type)) {
|
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);
|
(*visitor)(OUT, pn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -963,7 +963,7 @@ void ParseTree::traverse_from_int(parse_node *pn, void (*visitor)(parse_node *,
|
||||||
for (; pn; pn = pn->next) {
|
for (; pn; pn = pn->next) {
|
||||||
if (ParseTree::top_level(pn->node_type)) ParseTree::traverse_from_int(pn->down, visitor, X);
|
if (ParseTree::top_level(pn->node_type)) ParseTree::traverse_from_int(pn->down, visitor, X);
|
||||||
if (ParseTree::visitable(pn->node_type)) {
|
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);
|
(*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) {
|
for (; pn; pn = pn->next) {
|
||||||
if (ParseTree::top_level(pn->node_type)) ParseTree::traverse_from_int_int(pn->down, visitor, X, Y);
|
if (ParseTree::top_level(pn->node_type)) ParseTree::traverse_from_int_int(pn->down, visitor, X, Y);
|
||||||
if (ParseTree::visitable(pn->node_type)) {
|
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);
|
(*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) {
|
for (; pn; pn = pn->next) {
|
||||||
if (ParseTree::top_level(pn->node_type)) ParseTree::traverse_from_ppn(pn->down, visitor, X);
|
if (ParseTree::top_level(pn->node_type)) ParseTree::traverse_from_ppn(pn->down, visitor, X);
|
||||||
if (ParseTree::visitable(pn->node_type)) {
|
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);
|
(*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);
|
ParseTree::traverse_from_ppni(T, pn->down, visitor, H0, N);
|
||||||
}
|
}
|
||||||
if (ParseTree::visitable(pn->node_type)) {
|
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);
|
(*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 (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);
|
(*visitor)(pn, X);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1055,6 +1055,18 @@ int ParseTree::traverse_from_ppn_nocs(parse_node *pn, int (*visitor)(parse_node
|
||||||
return FALSE;
|
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.
|
@h Verify integrity.
|
||||||
The first duty of a tree is to contain no loops, and the following checks
|
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
|
that (rejecting even undirected loops). In addition, it checks that each
|
||||||
|
|
|
@ -150,10 +150,3 @@ void Basics::preform_problem_handler(word_assemblage base_text, nonterminal *nt,
|
||||||
@
|
@
|
||||||
|
|
||||||
@d PARSE_TREE_TRAVERSE_TYPE void
|
@d PARSE_TREE_TRAVERSE_TYPE void
|
||||||
@d SENTENCE_NODE Basics::sentence_level
|
|
||||||
|
|
||||||
=
|
|
||||||
int Basics::sentence_level(node_type_t t) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -155,15 +155,6 @@ void Basics::preform_problem_handler(word_assemblage base_text, nonterminal *nt,
|
||||||
@
|
@
|
||||||
|
|
||||||
@d PARSE_TREE_TRAVERSE_TYPE void
|
@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 ADJECTIVE_MEANING_TYPE void
|
||||||
@d VERB_MEANING_EQUALITY vc_be
|
@d VERB_MEANING_EQUALITY vc_be
|
||||||
@d VERB_MEANING_POSSESSION vc_have
|
@d VERB_MEANING_POSSESSION vc_have
|
||||||
|
|
|
@ -156,15 +156,6 @@ void Basics::preform_problem_handler(word_assemblage base_text, nonterminal *nt,
|
||||||
@
|
@
|
||||||
|
|
||||||
@d PARSE_TREE_TRAVERSE_TYPE void
|
@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 ADJECTIVE_MEANING_TYPE void
|
||||||
@d VERB_MEANING_EQUALITY vc_be
|
@d VERB_MEANING_EQUALITY vc_be
|
||||||
@d VERB_MEANING_POSSESSION vc_have
|
@d VERB_MEANING_POSSESSION vc_have
|
||||||
|
|
|
@ -150,15 +150,4 @@ void Basics::preform_problem_handler(word_assemblage base_text, nonterminal *nt,
|
||||||
@
|
@
|
||||||
|
|
||||||
@d PARSE_TREE_TRAVERSE_TYPE void
|
@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
|
@d NO_HEADING_LEVELS 10
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue