To specify standard verb-phrase nodes in the parse tree.


§1. This section lays out a sort of specification for what we ultimately 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:

enum L3_NCAT
enum VERB_NT                              "is"
enum UNPARSED_NOUN_NT                 "arfle barfle gloop"
enum PRONOUN_NT                       "them"
enum DEFECTIVE_NOUN_NT                    "there"
enum COMMON_NOUN_NT                   "a container"
enum PROPER_NOUN_NT                   "the red handkerchief"
enum RELATIONSHIP_NT                  "on"
enum CALLED_NT                        "On the table is a container called the box"
enum WITH_NT                          "The footstool is a supporter with capacity 2"
enum AND_NT                           "whisky and soda"
enum KIND_NT                          "A woman is a kind of person"
enum PROPERTY_LIST_NT                 "capacity 2"
enum X_OF_Y_NT                        "description of the painting"

§2. These nodes are annotated with the following:

enum verbal_certainty_ANNOT         int: certainty level if known
enum sentence_is_existential_ANNOT  int: such as "there is a man"
enum linguistic_error_here_ANNOT    int: one of the errors occurred here
enum verb_ANNOT                     verb_usage: what's being done here
enum noun_ANNOT                     noun_usage: what's being done here
enum article_ANNOT                  article_usage: what's being done here
enum pronoun_ANNOT                  pronoun_usage: what's being done here
enum preposition_ANNOT              preposition: which preposition, if any, qualifies it
enum second_preposition_ANNOT       preposition: which further preposition, if any, qualifies it
enum special_meaning_ANNOT          special_meaning_holder: to give a verb a non-standard meaning
enum occurrence_ANNOT               time_period: any stipulation on occurrence
enum 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)

§3.

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);
}

§4. The linguistic_error_here_ANNOT annotation is for any errors we find:

enum TwoLikelihoods_LINERROR from 1

§5. Two callbacks are needed so that the syntax module will create the above nodes and annotations correctly:

define EVEN_MORE_NODE_METADATA_SETUP_SYNTAX_CALLBACK Diagrams::setup
define EVEN_MORE_PARENTAGE_PERMISSIONS_SYNTAX_CALLBACK Diagrams::parentage_permission
define 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);
}

§6. 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;
}

§7. 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

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);
}