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:
parent
9aa6176dc0
commit
3c59521ab7
|
@ -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
|
||||
|
||||
=
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue