1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-06-17 07:40:47 +03:00

Further dialogue beat parsing

This commit is contained in:
Graham Nelson 2022-09-07 23:51:43 +01:00
parent 0d6eba5bfd
commit 5003ba316d
23 changed files with 341 additions and 20 deletions

View file

@ -1,6 +1,6 @@
# Inform 7
[Version](notes/versioning.md): 10.2.0-beta+6V52 'Krypton' (6 September 2022)
[Version](notes/versioning.md): 10.2.0-beta+6V53 'Krypton' (7 September 2022)
## About Inform

View file

@ -1,3 +1,3 @@
Prerelease: beta
Build Date: 6 September 2022
Build Number: 6V52
Build Date: 7 September 2022
Build Number: 6V53

View file

@ -523,11 +523,8 @@ on //WorldModelKit//, through the if-this-then-that mechanism.
inform_language *L = project->language_of_play;
if (L) Languages::add_kit_dependencies_to_project(L, project);
else internal_error("no language of play");
if ((no_word_from_JSON) && (forcible_basic_mode == FALSE)) {
if ((no_word_from_JSON) && (forcible_basic_mode == FALSE))
Projects::add_kit_dependency(project, I"CommandParserKit", NULL, NULL, NULL);
if (project->syntax_tree->contains_dialogue)
Projects::add_kit_dependency(project, I"DialogueKit", NULL, NULL, NULL);
}
@ We perform this first with |parity| being |TRUE|, then |FALSE|.
@ -712,6 +709,8 @@ void Projects::construct_graph(inform_project *proj) {
if (proj->chosen_build_target == NULL) {
Projects::finalise_kit_dependencies(proj);
Copies::get_source_text(proj->as_copy);
if (proj->syntax_tree->contains_dialogue)
Projects::add_kit_dependency(proj, I"DialogueKit", NULL, NULL, NULL);
build_vertex *V = proj->as_copy->vertex;
@<Construct the graph upstream of V@>;
@<Construct the graph downstream of V@>;

View file

@ -2,7 +2,7 @@
"is": {
"type": "kit",
"title": "BasicInformExtrasKit",
"version": "10.2.0-beta+6V52"
"version": "10.2.0-beta+6V53"
},
"kit-details": {
"has-priority": 1

View file

@ -2,7 +2,7 @@
"is": {
"type": "kit",
"title": "BasicInformKit",
"version": "10.2.0-beta+6V52"
"version": "10.2.0-beta+6V53"
},
"needs": [ {
"unless": {

View file

@ -2,7 +2,7 @@
"is": {
"type": "kit",
"title": "CommandParserKit",
"version": "10.2.0-beta+6V52"
"version": "10.2.0-beta+6V53"
},
"needs": [ {
"need": {

View file

@ -2,7 +2,7 @@
"is": {
"type": "kit",
"title": "EnglishLanguageKit",
"version": "10.2.0-beta+6V52"
"version": "10.2.0-beta+6V53"
},
"needs": [ {
"need": {

View file

@ -2,7 +2,7 @@
"is": {
"type": "kit",
"title": "WorldModelKit",
"version": "10.2.0-beta+6V52"
"version": "10.2.0-beta+6V53"
},
"needs": [ {
"need": {

View file

@ -0,0 +1,17 @@
PM_NotABeat
PM_UnrecognisedBeat
PM_DoubleImmediateBeat
PM_NoPreviousBeat
PM_LineNamedTwice
PM_BeatNamedTwice
PM_LineWithoutBeat
PM_OrphanLine
PM_OvernestedLine
PM_IndentedBeat
PM_MisbracketedDialogueClause
PM_EmptyDialogueClause
PM_UnquotedDialogue
PM_UnexpectedDialogue
PM_DialogueOnSectionsOnly
PM_NotAnAboutTopic
PM_UnrecognisedAboutTopic

View file

@ -0,0 +1,11 @@
Elsinore is a room.
Section 1 - Meeting (dialogue)
(This is the okay beat.)
Marcellus: "OK."
(Next, immediately after the okay beat.)
Marcellus: "What, has this thing appear'd again to-night?"

View file

@ -0,0 +1,13 @@
Elsinore is a room.
Section 1 - Meeting (dialogue)
(Later.)
Marcellus: "What, has this thing appear'd again to-night?"
Section 2 - Meeting Again (dialogue)
(Next.)
Marcellus: "What, has this thing appear'd again to-night?"

View file

@ -0,0 +1,19 @@
Elsinore is a room.
Section 1 - Meeting (dialogue)
(This is the okay beat.)
Marcellus: "OK."
(After the okay beat.)
Marcellus: "What, has this thing appear'd again to-night?"
(After a dialogue beat.)
Marcellus: "What, has this thing appear'd again to-night?"
(After 456.)
Marcellus: "What, has this thing appear'd again to-night?"

View file

@ -0,0 +1,7 @@
Elsinore is a room.
Section 1 - Meeting (dialogue)
(About "fish".)
Marcellus: "OK."

View file

@ -0,0 +1,7 @@
Elsinore is a room.
Section 1 - Meeting (dialogue)
(About total nonsense.)
Marcellus: "OK."

View file

@ -0,0 +1,19 @@
Elsinore is a room.
Section 1 - Meeting (dialogue)
(This is the okay beat.)
Marcellus: "OK."
(After the okay beat.)
Marcellus: "What, has this thing appear'd again to-night?"
(After a dialogue beat.)
Marcellus: "What, has this thing appear'd again to-night?"
(After sdfgsfgsfg sdfgsfgs.)
Marcellus: "What, has this thing appear'd again to-night?"

View file

@ -0,0 +1,11 @@
Inform 7 v10.2.0 has started.
I've now read your source text, which is 30 words long.
I've also read Basic Inform by Graham Nelson, which is 7691 words long.
I've also read English Language by Graham Nelson, which is 2328 words long.
I've also read Standard Rules by Graham Nelson, which is 32187 words long.
Problem__ PM_DoubleImmediateBeat
In Section 1 - Meeting:
>--> You wrote '(Next, immediately after the okay beat .)' (source text, line 9):
but this dialogue beat asks to be immediately after two or more other
beats, either with 'next' or 'immediately after'. It can only give one.
Inform 7 has finished.

View file

@ -0,0 +1,15 @@
Inform 7 v10.2.0 has started.
I've now read your source text, which is 33 words long.
I've also read Basic Inform by Graham Nelson, which is 7691 words long.
I've also read English Language by Graham Nelson, which is 2328 words long.
I've also read Standard Rules by Graham Nelson, which is 32187 words long.
Problem__ PM_NoPreviousBeat
In Section 1 - Meeting:
>--> You wrote '(Later .)' (source text, line 5): but this dialogue beat asks
to be performed after the previous one, but in this dialogue section, there
is no previous one.
Problem__ PM_NoPreviousBeat
In Section 2 - Meeting Again:
>--> You wrote '(Next .)' (source text, line 11): again, this dialogue beat
asks to be performed after the previous one.
Inform 7 has finished.

View file

@ -0,0 +1,10 @@
Inform 7 v10.2.0 has started.
I've now read your source text, which is 50 words long.
I've also read Basic Inform by Graham Nelson, which is 7691 words long.
I've also read English Language by Graham Nelson, which is 2328 words long.
I've also read Standard Rules by Graham Nelson, which is 32187 words long.
Problem__ PM_NotABeat
In Section 1 - Meeting:
>--> The dialogue beat '(After 456 .)' (source text, line 17) refers to
another beat with '456', but that seems to describe a number.
Inform 7 has finished.

View file

@ -0,0 +1,11 @@
Inform 7 v10.2.0 has started.
I've now read your source text, which is 13 words long.
I've also read Basic Inform by Graham Nelson, which is 7691 words long.
I've also read English Language by Graham Nelson, which is 2328 words long.
I've also read Standard Rules by Graham Nelson, which is 32187 words long.
Problem__ PM_NotAnAboutTopic
In Section 1 - Meeting:
>--> The dialogue beat '(About "fish" .)' (source text, line 5) is apparently
about '"fish"', but that seems to be a text. (Dialogue can only be about
objects: people, things, rooms, that sort of stuff.)
Inform 7 has finished.

View file

@ -0,0 +1,12 @@
Inform 7 v10.2.0 has started.
I've now read your source text, which is 14 words long.
I've also read Basic Inform by Graham Nelson, which is 7691 words long.
I've also read English Language by Graham Nelson, which is 2328 words long.
I've also read Standard Rules by Graham Nelson, which is 32187 words long.
Problem__ PM_UnrecognisedAboutTopic
In Section 1 - Meeting:
>--> The dialogue beat '(About total nonsense .)' (source text, line 5) is
apparently about 'total nonsense', but that isn't something I recognise as
an object. (Dialogue can only be about objects: people, things, rooms, that
sort of stuff.)
Inform 7 has finished.

View file

@ -0,0 +1,11 @@
Inform 7 v10.2.0 has started.
I've now read your source text, which is 51 words long.
I've also read Basic Inform by Graham Nelson, which is 7691 words long.
I've also read English Language by Graham Nelson, which is 2328 words long.
I've also read Standard Rules by Graham Nelson, which is 32187 words long.
Problem__ PM_UnrecognisedBeat
In Section 1 - Meeting:
>--> The dialogue beat '(After sdfgsfgsfg sdfgsfgs .)' (source text, line 17)
refers to another beat with 'sdfgsfgsfg sdfgsfgs', but that isn't something
I recognise as a description.
Inform 7 has finished.

View file

@ -2,7 +2,7 @@
To manage dialogue beats and lines.
@
@ See the test group |:dialogue|.
@d MAX_DIALOGUE_LINE_NESTING 25
@ -30,10 +30,12 @@ typedef struct dialogue_beat {
struct parse_node *cue_at;
struct heading *under_heading;
struct instance *as_instance;
struct scene *as_scene;
struct dialogue_beat *immediately_after;
struct linked_list *some_time_after; /* of |dialogue_beat| */
struct linked_list *some_time_before; /* of |dialogue_beat| */
struct parse_node *immediately_after;
struct linked_list *some_time_after; /* of |parse_node| */
struct linked_list *some_time_before; /* of |parse_node| */
struct linked_list *about_list; /* of |parse_node| */
struct dialogue_line *opening_line;
struct dialogue_beat_compilation_data compilation_data;
@ -72,10 +74,12 @@ dialogue_beat *Dialogue::create_cue(parse_node *PN) {
db->cue_at = PN;
db->under_heading = dialogue_section_being_scanned;
db->immediately_after = NULL;
db->some_time_after = NEW_LINKED_LIST(dialogue_beat);
db->some_time_before = NEW_LINKED_LIST(dialogue_beat);
db->some_time_after = NEW_LINKED_LIST(parse_node);
db->some_time_before = NEW_LINKED_LIST(parse_node);
db->about_list = NEW_LINKED_LIST(parse_node);
db->opening_line = NULL;
db->compilation_data = RTDialogue::new_beat(PN, db);
db->as_scene = NULL;
previous_dialogue_beat = current_dialogue_beat;
current_dialogue_beat = db;
for (int i=0; i<MAX_DIALOGUE_LINE_NESTING; i++)
@ -188,9 +192,162 @@ void Dialogue::write_dbc(OUTPUT_STREAM, int c) {
... beat |
... scene
@
=
void Dialogue::decide_cue_sequencing(void) {
dialogue_beat *db, *previous = NULL;
LOOP_OVER(db, dialogue_beat) {
current_sentence = db->cue_at;
int iac = 0;
for (parse_node *clause = db->cue_at->down; clause; clause = clause->next) {
wording CW = Node::get_text(clause);
switch (Annotations::read_int(clause, dialogue_beat_clause_ANNOT)) {
case NEXT_DBC:
if ((previous) && (previous->under_heading == db->under_heading)) {
iac++;
db->immediately_after = Rvalues::from_dialogue_beat(previous);
} else @<Issue PM_NoPreviousBeat problem@>;
break;
case IMMEDIATELY_AFTER_DBC: {
<dialogue-beat-clause>(CW);
wording B = GET_RW(<dialogue-beat-clause>, 1);
parse_node *desc = Dialogue::parse_beat_name(B);
if (desc) {
iac++;
db->immediately_after = desc;
}
break;
}
case LATER_DBC:
if ((previous) && (previous->under_heading == db->under_heading)) {
parse_node *desc = Rvalues::from_dialogue_beat(previous);
ADD_TO_LINKED_LIST(desc, parse_node, db->some_time_after);
} else @<Issue PM_NoPreviousBeat problem@>;
break;
case AFTER_DBC: {
<dialogue-beat-clause>(CW);
wording B = GET_RW(<dialogue-beat-clause>, 1);
parse_node *desc = Dialogue::parse_beat_name(B);
if (desc) ADD_TO_LINKED_LIST(desc, parse_node, db->some_time_after);
break;
}
case BEFORE_DBC: {
<dialogue-beat-clause>(CW);
wording B = GET_RW(<dialogue-beat-clause>, 1);
parse_node *desc = Dialogue::parse_beat_name(B);
if (desc) ADD_TO_LINKED_LIST(desc, parse_node, db->some_time_before);
break;
}
}
}
if (Wordings::nonempty(db->scene_name)) {
pcalc_prop *prop = Propositions::Abstract::to_create_something(K_scene, db->scene_name);
Assert::true(prop, CERTAIN_CE);
db->as_scene = Scenes::from_named_constant(Instances::latest());
}
previous = db;
if (iac > 1)
StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_DoubleImmediateBeat),
"this dialogue beat asks to be immediately after two or more other beats",
"either with 'next' or 'immediately after'. It can only give one.");
}
}
@<Issue PM_NoPreviousBeat problem@> =
StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_NoPreviousBeat),
"this dialogue beat asks to be performed after the previous one",
"but in this dialogue section, there is no previous one.");
@ =
parse_node *Dialogue::parse_beat_name(wording CW) {
if (<s-type-expression-uncached>(CW)) {
parse_node *desc = <<rp>>;
kind *K = Specifications::to_kind(desc);
if (Kinds::ne(K, K_dialogue_beat)) {
Problems::quote_source(1, current_sentence);
Problems::quote_wording(2, CW);
Problems::quote_kind(3, K);
StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_NotABeat));
Problems::issue_problem_segment(
"The dialogue beat %1 refers to another beat with '%2', but that "
"seems to describe %3.");
Problems::issue_problem_end();
return NULL;
}
return desc;
} else {
Problems::quote_source(1, current_sentence);
Problems::quote_wording(2, CW);
StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_UnrecognisedBeat));
Problems::issue_problem_segment(
"The dialogue beat %1 refers to another beat with '%2', but that "
"isn't something I recognise as a description.");
Problems::issue_problem_end();
return NULL;
}
}
@
=
void Dialogue::decide_cue_topics(void) {
dialogue_beat *db;
LOOP_OVER(db, dialogue_beat) {
current_sentence = db->cue_at;
for (parse_node *clause = db->cue_at->down; clause; clause = clause->next) {
wording CW = Node::get_text(clause);
switch (Annotations::read_int(clause, dialogue_beat_clause_ANNOT)) {
case ABOUT_DBC: {
<dialogue-beat-clause>(CW);
wording A = GET_RW(<dialogue-beat-clause>, 1);
<np-articled-list>(A);
parse_node *AL = <<rp>>;
Dialogue::parse_topic(db->about_list, AL);
break;
}
}
}
}
}
void Dialogue::parse_topic(linked_list *about_list, parse_node *AL) {
if (Node::is(AL, AND_NT)) {
Dialogue::parse_topic(about_list, AL->down);
Dialogue::parse_topic(about_list, AL->down->next);
} else if (Node::is(AL, UNPARSED_NOUN_NT)) {
wording A = Node::get_text(AL);
LOG("Text: %W\n", A);
if (<s-constant-value>(A)) {
parse_node *desc = <<rp>>;
kind *K = Specifications::to_kind(desc);
if (Kinds::Behaviour::is_subkind_of_object(K)) {
ADD_TO_LINKED_LIST(desc, parse_node, about_list);
} else {
Problems::quote_source(1, current_sentence);
Problems::quote_wording(2, A);
Problems::quote_kind(3, K);
StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_NotAnAboutTopic));
Problems::issue_problem_segment(
"The dialogue beat %1 is apparently about '%2', but that "
"seems to be %3. (Dialogue can only be about objects: "
"people, things, rooms, that sort of stuff.)");
Problems::issue_problem_end();
}
} else {
Problems::quote_source(1, current_sentence);
Problems::quote_wording(2, A);
StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_UnrecognisedAboutTopic));
Problems::issue_problem_segment(
"The dialogue beat %1 is apparently about '%2', but that "
"isn't something I recognise as an object. (Dialogue can "
"only be about objects: people, things, rooms, that sort of stuff.)");
Problems::issue_problem_end();
}
}
}
@<Add a scene name to the beat@> =
current_dialogue_beat->beat_name = WR[1];
@

View file

@ -140,9 +140,11 @@ so on. Those absolute basics are made here.
2, debugging, sequence_timer);
BENCH(MajorNodes::pass_1)
BENCH(Tables::traverse_to_stock)
BENCH(Dialogue::decide_cue_sequencing)
Task::advance_stage_to(ASSERTIONS_PASS_2_CSEQ, I"Second pass through major nodes",
-1, debugging, sequence_timer);
BENCH(MajorNodes::pass_2)
BENCH(Dialogue::decide_cue_topics)
@<Make the model world@> =
Task::advance_stage_to(MODEL_CSEQ, I"Making the model world",