1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-03 07:24:58 +03:00
inform7/services/linguistics-module/Chapter 1/Diagrams.w
2020-08-27 15:50:24 +01:00

311 lines
12 KiB
OpenEdge ABL

[Diagrams::] Diagrams.
To specify standard verb-phrase nodes in the parse tree.
@ This section lays out a sort of specification for what we ultinately want
to turn sentences into: i.e., little sentence diagrams made up of parse nodes.
We do that with the aid of the //syntax// module. So we must first set up
some new node types:
@e L3_NCAT
@e VERB_NT /* "is" */
@e UNPARSED_NOUN_NT /* "arfle barfle gloop" */
@e PRONOUN_NT /* "them" */
@e DEFECTIVE_NOUN_NT /* "there" */
@e COMMON_NOUN_NT /* "a container" */
@e PROPER_NOUN_NT /* "the red handkerchief" */
@e RELATIONSHIP_NT /* "on" */
@e CALLED_NT /* "On the table is a container called the box" */
@e WITH_NT /* "The footstool is a supporter with capacity 2" */
@e AND_NT /* "whisky and soda" */
@e KIND_NT /* "A woman is a kind of person" */
@e PROPERTY_LIST_NT /* "capacity 2" */
@e X_OF_Y_NT /* "description of the painting" */
@ These nodes are annotated with the following:
@e verbal_certainty_ANNOT /* |int|: certainty level if known */
@e sentence_is_existential_ANNOT /* |int|: such as "there is a man" */
@e linguistic_error_here_ANNOT /* |int|: one of the errors occurred here */
@e verb_ANNOT /* |verb_usage|: what's being done here */
@e noun_ANNOT /* |noun_usage|: what's being done here */
@e article_ANNOT /* |article_usage|: what's being done here */
@e pronoun_ANNOT /* |pronoun_usage|: what's being done here */
@e preposition_ANNOT /* |preposition|: which preposition, if any, qualifies it */
@e second_preposition_ANNOT /* |preposition|: which further preposition, if any, qualifies it */
@e special_meaning_ANNOT /* |special_meaning_holder|: to give a verb a non-standard meaning */
@e occurrence_ANNOT /* |time_period|: any stipulation on occurrence */
@e relationship_ANNOT /* |binary_predicate|: for RELATIONSHIP nodes */
=
DECLARE_ANNOTATION_FUNCTIONS(verb, verb_usage)
DECLARE_ANNOTATION_FUNCTIONS(noun, noun_usage)
DECLARE_ANNOTATION_FUNCTIONS(pronoun, pronoun_usage)
DECLARE_ANNOTATION_FUNCTIONS(article, article_usage)
DECLARE_ANNOTATION_FUNCTIONS(preposition, preposition)
DECLARE_ANNOTATION_FUNCTIONS(second_preposition, preposition)
DECLARE_ANNOTATION_FUNCTIONS(special_meaning, special_meaning_holder)
DECLARE_ANNOTATION_FUNCTIONS(occurrence, time_period)
MAKE_ANNOTATION_FUNCTIONS(verb, verb_usage)
MAKE_ANNOTATION_FUNCTIONS(noun, noun_usage)
MAKE_ANNOTATION_FUNCTIONS(pronoun, pronoun_usage)
MAKE_ANNOTATION_FUNCTIONS(article, article_usage)
MAKE_ANNOTATION_FUNCTIONS(preposition, preposition)
MAKE_ANNOTATION_FUNCTIONS(second_preposition, preposition)
MAKE_ANNOTATION_FUNCTIONS(special_meaning, special_meaning_holder)
MAKE_ANNOTATION_FUNCTIONS(occurrence, time_period)
@ =
void Diagrams::declare_annotations(void) {
Annotations::declare_type(verbal_certainty_ANNOT,
Diagrams::write_verbal_certainty_ANNOT);
Annotations::declare_type(sentence_is_existential_ANNOT,
Diagrams::write_sentence_is_existential_ANNOT);
Annotations::declare_type(linguistic_error_here_ANNOT,
Diagrams::write_linguistic_error_here_ANNOT);
Annotations::declare_type(verb_ANNOT,
Diagrams::write_verb_ANNOT);
Annotations::declare_type(noun_ANNOT,
Diagrams::write_noun_ANNOT);
Annotations::declare_type(article_ANNOT,
Diagrams::write_article_ANNOT);
Annotations::declare_type(pronoun_ANNOT,
Diagrams::write_pronoun_ANNOT);
Annotations::declare_type(preposition_ANNOT,
Diagrams::write_preposition_ANNOT);
Annotations::declare_type(second_preposition_ANNOT,
Diagrams::write_second_preposition_ANNOT);
Annotations::declare_type(special_meaning_ANNOT,
Diagrams::write_special_meaning_ANNOT);
Annotations::declare_type(occurrence_ANNOT,
Diagrams::write_occurrence_ANNOT);
Annotations::declare_type(relationship_ANNOT,
Diagrams::write_relationship_ANNOT);
}
void Diagrams::write_verbal_certainty_ANNOT(text_stream *OUT, parse_node *p) {
if (Annotations::read_int(p, verbal_certainty_ANNOT) != UNKNOWN_CE) {
WRITE(" {certainty:");
Certainty::write(OUT, Annotations::read_int(p, verbal_certainty_ANNOT));
WRITE("}");
}
}
void Diagrams::write_sentence_is_existential_ANNOT(text_stream *OUT, parse_node *p) {
if (Annotations::read_int(p, sentence_is_existential_ANNOT))
WRITE(" {existential}");
}
void Diagrams::write_linguistic_error_here_ANNOT(text_stream *OUT, parse_node *p) {
WRITE(" {error: ");
switch (Annotations::read_int(p, linguistic_error_here_ANNOT)) {
case TwoLikelihoods_LINERROR: WRITE(" two likelihoods"); break;
default: WRITE("unknown"); break;
}
WRITE("}");
}
void Diagrams::write_verb_ANNOT(text_stream *OUT, parse_node *p) {
if (Node::get_verb(p))
VerbUsages::write_usage(OUT, Node::get_verb(p));
}
void Diagrams::write_noun_ANNOT(text_stream *OUT, parse_node *p) {
if (Node::get_noun(p))
Nouns::write_usage(OUT, Node::get_noun(p));
}
void Diagrams::write_article_ANNOT(text_stream *OUT, parse_node *p) {
if (Node::get_article(p))
Articles::write_usage(OUT, Node::get_article(p));
}
void Diagrams::write_pronoun_ANNOT(text_stream *OUT, parse_node *p) {
if (Node::get_pronoun(p))
Pronouns::write_usage(OUT, Node::get_pronoun(p));
}
void Diagrams::write_preposition_ANNOT(text_stream *OUT, parse_node *p) {
if (Node::get_preposition(p)) {
WRITE(" {prep1: ");
Prepositions::log(OUT, Node::get_preposition(p));
WRITE("}");
}
}
void Diagrams::write_second_preposition_ANNOT(text_stream *OUT, parse_node *p) {
if (Node::get_second_preposition(p)) {
WRITE(" {prep2: ");
Prepositions::log(OUT, Node::get_second_preposition(p));
WRITE("}");
}
}
void Diagrams::write_special_meaning_ANNOT(text_stream *OUT, parse_node *p) {
if (Node::get_special_meaning(p))
WRITE(" {special meaning: %S}",
SpecialMeanings::get_name(Node::get_special_meaning(p)));
}
void Diagrams::write_occurrence_ANNOT(text_stream *OUT, parse_node *p) {
if (Node::get_occurrence(p)) {
WRITE(" {occurrence: ");
Occurrence::log(OUT, Node::get_occurrence(p));
WRITE("}");
}
}
void Diagrams::write_relationship_ANNOT(text_stream *OUT, parse_node *p) {
if (Node::get_relationship(p))
WRITE(" {meaning: %S}", Node::get_relationship(p)->debugging_log_name);
}
@ The |linguistic_error_here_ANNOT| annotation is for any errors we find:
@e TwoLikelihoods_LINERROR from 1
@ Two callbacks are needed so that the //syntax// module will create the above
nodes and annotations correctly:
@d EVEN_MORE_NODE_METADATA_SETUP_SYNTAX_CALLBACK Diagrams::setup
@d EVEN_MORE_PARENTAGE_PERMISSIONS_SYNTAX_CALLBACK Diagrams::parentage_permission
@d EVEN_MORE_ANNOTATION_PERMISSIONS_SYNTAX_CALLBACK Diagrams::permissions
=
void Diagrams::setup(void) {
NodeType::new(VERB_NT, I"VERB_NT", 0, 0, L3_NCAT, 0);
NodeType::new(RELATIONSHIP_NT, I"RELATIONSHIP_NT", 0, 2, L3_NCAT, ASSERT_NFLAG);
NodeType::new(CALLED_NT, I"CALLED_NT", 2, 2, L3_NCAT, 0);
NodeType::new(WITH_NT, I"WITH_NT", 2, 2, L3_NCAT, ASSERT_NFLAG);
NodeType::new(AND_NT, I"AND_NT", 2, 2, L3_NCAT, ASSERT_NFLAG);
NodeType::new(KIND_NT, I"KIND_NT", 0, 1, L3_NCAT, ASSERT_NFLAG);
NodeType::new(UNPARSED_NOUN_NT, I"UNPARSED_NOUN_NT", 0, 0, L3_NCAT, ASSERT_NFLAG);
NodeType::new(PRONOUN_NT, I"PRONOUN_NT", 0, 0, L3_NCAT, ASSERT_NFLAG);
NodeType::new(DEFECTIVE_NOUN_NT, I"DEFECTIVE_NOUN_NT", 0, 0, L3_NCAT, ASSERT_NFLAG);
NodeType::new(PROPER_NOUN_NT, I"PROPER_NOUN_NT", 0, 0, L3_NCAT, ASSERT_NFLAG);
NodeType::new(COMMON_NOUN_NT, I"COMMON_NOUN_NT", 0, INFTY, L3_NCAT, ASSERT_NFLAG);
NodeType::new(PROPERTY_LIST_NT, I"PROPERTY_LIST_NT", 0, INFTY, L3_NCAT, ASSERT_NFLAG);
NodeType::new(X_OF_Y_NT, I"X_OF_Y_NT", 2, 2, L3_NCAT, ASSERT_NFLAG);
}
void Diagrams::parentage_permission(void) {
NodeType::allow_parentage_for_categories(L2_NCAT, L3_NCAT);
NodeType::allow_parentage_for_categories(L3_NCAT, L3_NCAT);
}
void Diagrams::permissions(void) {
Annotations::allow(VERB_NT, verbal_certainty_ANNOT);
Annotations::allow(VERB_NT, sentence_is_existential_ANNOT);
Annotations::allow(VERB_NT, verb_ANNOT);
Annotations::allow(VERB_NT, preposition_ANNOT);
Annotations::allow(VERB_NT, second_preposition_ANNOT);
Annotations::allow(VERB_NT, special_meaning_ANNOT);
Annotations::allow(VERB_NT, occurrence_ANNOT);
Annotations::allow(UNPARSED_NOUN_NT, noun_ANNOT);
Annotations::allow(PRONOUN_NT, pronoun_ANNOT);
Annotations::allow(PROPER_NOUN_NT, noun_ANNOT);
Annotations::allow(COMMON_NOUN_NT, noun_ANNOT);
Annotations::allow(RELATIONSHIP_NT, preposition_ANNOT);
Annotations::allow(RELATIONSHIP_NT, relationship_ANNOT);
Annotations::allow_for_category(L3_NCAT, linguistic_error_here_ANNOT);
Annotations::allow_for_category(L3_NCAT, article_ANNOT);
}
@h Creation.
The following functions create leaves, or very minor twigs, used in sentence
diagrams.
=
parse_node *Diagrams::new_arity0(node_type_t t, wording W) {
parse_node *P = Node::new(t);
Node::set_text(P, W);
return P;
}
parse_node *Diagrams::new_arity1(node_type_t t, wording W, parse_node *A) {
parse_node *P = Node::new(t);
Node::set_text(P, W);
if (A == NULL) internal_error("no child of arity-1 node");
P->down = A;
return P;
}
parse_node *Diagrams::new_arity2(node_type_t t, wording W, parse_node *A, parse_node *B) {
parse_node *P = Node::new(t);
Node::set_text(P, W);
if (A == NULL) internal_error("no first child of arity-2 node");
if (B == NULL) internal_error("no second child of arity-2 node");
P->down = A; P->down->next = B;
return P;
}
@ And those are then used to make the following.
Note that if the variable |preform_lookahead_mode| is set, then all these
functions return |NULL|: this optimisation prevents us from creating millions
of useless nodes when all that's happening is that the sentence parser is
looking ahead speculatively.[1]
[1] At one time Inform used garbage collection to reclaim discarded nodes
instead, but it turned out to be more efficient not to make garbage in the
first place: a lesson there for all of us.
=
parse_node *Diagrams::new_UNPARSED_NOUN(wording W) {
if (preform_lookahead_mode) return NULL;
return Diagrams::new_arity0(UNPARSED_NOUN_NT, W);
}
parse_node *Diagrams::new_DEFECTIVE(wording W) {
if (preform_lookahead_mode) return NULL;
return Diagrams::new_arity0(DEFECTIVE_NOUN_NT, W);
}
parse_node *Diagrams::new_PROPER_NOUN(wording W) {
if (preform_lookahead_mode) return NULL;
return Diagrams::new_arity0(PROPER_NOUN_NT, W);
}
parse_node *Diagrams::new_PROPERTY_LIST(wording W) {
if (preform_lookahead_mode) return NULL;
return Diagrams::new_arity0(PROPERTY_LIST_NT, W);
}
parse_node *Diagrams::new_PRONOUN(wording W, pronoun_usage *pro) {
if (preform_lookahead_mode) return NULL;
parse_node *PN = Diagrams::new_arity0(PRONOUN_NT, W);
Node::set_pronoun(PN, pro);
return PN;
}
parse_node *Diagrams::new_KIND(wording W, parse_node *O) {
if (preform_lookahead_mode) return NULL;
if (O == NULL) return Diagrams::new_arity0(KIND_NT, W);
return Diagrams::new_arity1(KIND_NT, W, O);
}
parse_node *Diagrams::new_RELATIONSHIP(wording W, VERB_MEANING_LINGUISTICS_TYPE *R,
parse_node *O) {
if (preform_lookahead_mode) return NULL;
parse_node *P = Diagrams::new_arity1(RELATIONSHIP_NT, W, O);
Node::set_relationship(P, R);
return P;
}
int Diagrams::is_possessive_RELATIONSHIP(parse_node *py) {
if ((py) && (Node::get_type(py) == RELATIONSHIP_NT) &&
(Node::get_relationship(py)) &&
(VerbMeanings::reverse_VMT(Node::get_relationship(py)) == VERB_MEANING_POSSESSION))
return TRUE;
return FALSE;
}
parse_node *Diagrams::new_implied_RELATIONSHIP(wording W, VERB_MEANING_LINGUISTICS_TYPE *R) {
if (preform_lookahead_mode) return NULL;
return Diagrams::new_RELATIONSHIP(W, R, Diagrams::new_PRONOUN(W, Pronouns::get_implied()));
}
parse_node *Diagrams::new_AND(int wn, parse_node *X, parse_node *Y) {
if (preform_lookahead_mode) return NULL;
return Diagrams::new_arity2(AND_NT, Wordings::one_word(wn), X, Y);
}
parse_node *Diagrams::new_WITH(int wn, parse_node *X, parse_node *Y) {
if (preform_lookahead_mode) return NULL;
return Diagrams::new_arity2(WITH_NT, Wordings::one_word(wn), X, Y);
}
parse_node *Diagrams::new_CALLED(wording W, parse_node *X, parse_node *Y) {
if (preform_lookahead_mode) return NULL;
return Diagrams::new_arity2(CALLED_NT, W, X, Y);
}