net.sf.jlinkgrammar

## Class Sentence

- java.lang.Object
- - net.sf.jlinkgrammar.Sentence

-     public class Sentence
      extends java.lang.Object

  Routines for creating and destroying processing Sentences. It contains several its own copy of objects such as Dictionary, ParseInfo, Linkage, LinkageInfo, ParseOptions, and Postprocessor. Much of the code still smacks of C rather than Java. For instance the critical ctable is not a collection object and ctable_length can be modified independently of the actual lenght of the table.

  There are other examples, many routines take ParseOptions as an argument and yet use this.opts for their use. If the programmer is not careful odd results may occur.

  One last note: Everything is reference via integer indexes into arrays rather than as objects. A natural object oriented approach would pass the Word object and the routine would use Word.id to find the offset in the array. This would improve type checking and overall program safety. - jlr

  The most important routine is sentence_parse()

  See Also:
    `sentence_parse(ParseOptions)`

- - ### Field Summary

    Fields
    Modifier and Type | Field and Description
    --- | ---
    `AndData` | `and_data` used to keep track of fat disjuncts
    `static int[]` | `and_element`
    `static int[]` | `and_element_sizes`
    `static int` | `CMS_SIZE`
    `static Cms[]` | `cms_table`
    `static TableConnector[]` | `ctable` The TableConnector table associated with this sentence instance object
    `static int` | `ctable_size` The size of this.ctable TODO - make this Java, not C, and use the collection object stuff! sp that ctable size can not be modified independently of ctable.
    `boolean[][]` | `deletable` deletable regions in a sentence with conjunction
    `Dictionary` | `dict` words are defined from this dictionary
    `int[][]` | `effective_dist` created by build_effective_dist()
    `static boolean[]` | `has_fat_down`
    `static ImageNode[]` | `image_array`
    `LinkageInfo[]` | `link_info` array of valid and invalid linkages (sorted)
    `static int` | `match_cost`
    `static MatchNode[][]` | `match_l_table`
    `static int[]` | `match_l_table_size`
    `static MatchNode[][]` | `match_r_table`
    `static int[]` | `match_r_table_size`
    `static int` | `N_and_elements`
    `static int` | `N_changed`
    `static int` | `N_outside_words`
    `int` | `null_count` number of null links in linkages
    `static boolean` | `null_links`
    `int` | `num_linkages_alloced` total number of linkages allocated.
    `int` | `num_linkages_found` total number linkages before postprocessing.
    `int` | `num_linkages_post_processed` The number of linkages that are actually put into the array that was alloced.
    `int` | `num_valid_linkages` number with no pp violations
    `static int[]` | `outside_word`
    `ParseInfo` | `parse_info` set of parses for the sentence
    `PatchElement[]` | `patch_array`
    `int[]` | `post_quote`
    `static int` | `power_cost`
    `static CList[][]` | `power_l_table`
    `static int[]` | `power_l_table_size`
    `static int` | `power_prune_mode`
    `static CList[][]` | `power_r_table`
    `static int[]` | `power_r_table_size`
    `boolean` | `q_pruned_rules` don't prune rules more than once in p.p.
    `static int` | `s_table_size`
    `static boolean` | `structure_violation`
    `static Connector[]` | `table`
    `static boolean[]` | `visited`
    `java.util.ArrayList<Word>` | `word` array of words after tokenization

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `Sentence(java.lang.String input_string, Dictionary dict, ParseOptions opts)`

  - ### Method Summary

    Methods
    Modifier and Type | Method and Description
    --- | ---
    `static Disjunct` | `add_one_connector(int label, int dir, java.lang.String cs, Disjunct d)` This adds one connector onto the beginning of the left (or right) connector list of d.
    `static MatchNode` | `add_to_left_table_list(MatchNode m, MatchNode l)` Adds the match node m to the sorted list of match nodes l.
    `static MatchNode` | `add_to_right_table_list(MatchNode m, MatchNode l)` Adds the match node m to the sorted list of match nodes l.
    `LinkageInfo` | `analyze_fat_linkage(ParseOptions opts, int analyze_pass)` This uses link_array.
    `LinkageInfo` | `analyze_thin_linkage(ParseOptions opts, int analyze_pass)` This uses link_array.
    `Disjunct` | `build_AND_disjunct_list(java.lang.String s)` Builds and returns a disjunct list for "and", "or" and "nor" for each disjunct in the label_table, we build three disjuncts this means that "Danny and Tycho and Billy" will be parsable in two ways.
    `AndList` | `build_andlist()` This function computes the "and cost", resulting from inequalities in the word.size() of and-list elements.
    `(package private) Disjunct` | `build_COMMA_disjunct_list()`
    `void` | `build_conjunction_tables()`
    `void` | `build_deletable(boolean has_conjunction)` Initialize the array deletable[i][j] to indicate if the words i+1...j-1 could be non existant in one of the multiple linkages.
    `Disjunct` | `build_disjuncts_for_XNode(ParseOptions opts, XNode x, int cost_cutoff)`
    `void` | `build_effective_dist(boolean has_conjunction)`
    `(package private) Disjunct` | `build_fat_link_substitutions(Disjunct d)`
    `void` | `build_image_array()`
    `boolean` | `build_parse_set(int cost, ParseOptions opts)` This is the top level call that computes the whole parse_set.
    `void` | `build_sentence_disjuncts(ParseOptions opts, int cost_cutoff)` We've already built the sentence expressions.
    `void` | `build_sentence_expressions(ParseOptions opts)` Corrects case of first word, fills in other proper nouns, and builds the expression lists for the resulting words.
    `void` | `clean_table(int size, CList[] t)` This runs through all the connectors in this table, and eliminates those who are obsolete.
    `void` | `clean_up_expressions(int w)` This removes the expressions that are empty from the list corresponding to word w of the sentence.
    `void` | `clean_up(int w)` Step three of the sentence_parse operation - pruning
    `int` | `cms_hash(java.lang.String s)`
    `void` | `compute_link_names()`
    `void` | `compute_matchers_for_a_label(int k)`
    `void` | `compute_pp_link_array_connectors(Sublinkage sublinkage)` This takes as input link_array[], sublinkage.link[].l and sublinkage.link[].r (and also has_fat_down[word], which has been computed in a prior call to is_canonical()), and from these computes sublinkage.link[].lc and .rc.
    `void` | `compute_pp_link_names(Sublinkage sublinkage)` This fills in the sublinkage.link[].name field.
    `boolean` | `conj_in_range(int lw, int rw)` Determin if there is a conjunction between the suppled right and left words.
    `void` | `conjunction_prune(ParseOptions opts)` We've already built the sentence disjuncts, and we've pruned them and power_pruned(GENTLE) them also.
    `void` | `connector_for_disjunct(Disjunct d, Connector c)`
    `static DTypeList` | `copy_d_type(DTypeList dtl)` Copy the named Domain Type List and return a copy
    `int` | `count_disjuncts_in_sentence()`
    `int` | `count(int lw, int rw, Connector le, Connector re, int cost, ParseOptions opts)`
    `int` | `delete_from_cms_table(java.lang.String str)`
    `void` | `delete_unmarked_disjuncts()`
    `(package private) Disjunct` | `explode_disjunct_list(Disjunct d)`
    `void` | `expression_prune(ParseOptions opts)`
    `void` | `extract_all_fat_links(Disjunct d)`
    `static int` | `fast_match_hash(Connector c)` This hash function only looks at the leading upper case letters of the connector string, and the label fields.
    `void` | `fill_patch_array_CON(CONNode cn, LinksToPatch ltp)`
    `void` | `fill_patch_array_DIS(DISNode dn, LinksToPatch ltp)` Patches up appropriate links in the patch_array for this DISNode and this patch list.
    `Disjunct` | `find_subdisjunct(Disjunct dis, int label)` Find the specific disjunct of in label_table[label] which corresponds to dis.
    `static MatchNode` | `form_match_list(int w, Connector lc, int lw, Connector rc, int rw)` Forms and returns a list of disjuncts that might match lc or rc or both.
    `void` | `free_AND_tables()`
    `void` | `free_HT()`
    `void` | `free_LT()`
    `void` | `free_parse_set()`
    `static void` | `free_S()`
    `void` | `free_sentence_disjuncts()`
    `(package private) static MatchNode` | `get_match_node()`
    `static Disjunct` | `glom_aux_connector(Disjunct d, int label, boolean necessary)` In this case the connector is to connect to the "either", "neither", "not", or some auxilliary d to the current which is a conjunction.
    `static Disjunct` | `glom_comma_connector(Disjunct d)` This file contains the functions for massaging disjuncts of the sentence in special ways having to do with conjunctions.
    `(package private) void` | `grow_LT()`
    `static int` | `hash_S(Connector c)` This hash function only looks at the leading upper case letters of the connector string, and the label fields.
    `static int` | `hash(int lw, int rw, Connector le, Connector re, int cost)`
    `void` | `init_cms_table()`
    `void` | `init_fast_matcher()`
    `void` | `init_HT()`
    `void` | `init_LT()`
    `void` | `init_power()` allocates and builds the initial power hash tables
    `void` | `init_table()` A piecewise exponential function determines the size of the hash table.
    `void` | `init_x_table()` A piecewise exponential function determines the size of the hash table.
    `void` | `initialize_conjunction_tables()`
    `void` | `insert_in_cms_table(java.lang.String str)`
    `static void` | `insert_S(Connector c)`
    `(package private) void` | `install_fat_connectors()`
    `void` | `install_special_conjunctive_connectors()`
    `static java.lang.String` | `intersect_strings(java.lang.String s, java.lang.String t)`
    `boolean` | `is_appropriate(Disjunct d)` returns true if the disjunct is appropriate to be made into fat links.
    `boolean` | `is_canonical_linkage()` uses link_array[], chosen_disjuncts[], has_fat_down[].
    `int` | `left_connector_count(Disjunct d)` returns the number of connectors in the left lists of the disjuncts.
    `int` | `left_connector_list_update(Connector c, int word_c, int w, boolean shallow)` take this connector list, and try to match it with the words w-1, w-2, w-3...Returns the word to which the first connector of the list could possibly be matched.
    `static int` | `left_disjunct_list_length(Disjunct d)`
    `boolean` | `left_table_search(int w, Connector c, boolean shallow, int word_c)`
    `Cms` | `lookup_in_cms_table(java.lang.String str)`
    `(package private) void` | `mark_region(int lw, int rw, Connector le, Connector re)`
    `boolean` | `match_in_cms_table(java.lang.String pp_match_name)`
    `boolean` | `matches_S(Connector c, int dir)` returns true if c can match anything in the set S because of the horrible kludge, prune match is assymetric, and direction is '-' if this is an l.r pass, and '+' if an r.l pass.
    `int` | `parse(int cost, ParseOptions opts)` Returns the number of null links the sentence can be parsed with the specified cost Assumes that the hash table this.ctable has already been initialized, and is freed later.
    `boolean` | `possible_connection(Connector lc, Connector rc, boolean lshallow, boolean rshallow, int lword, int rword)` this takes two connectors (and whether these are shallow or not) (and the two words that these came from) and returns true if it is possible for these two to match based on local considerations.
    `void` | `post_process_linkages(ParseOptions opts)` This is another top level call.
    `void` | `post_process_scan_linkage(Postprocessor pp, ParseOptions opts, Sublinkage sublinkage)` During a first pass (prior to actual post-processing of the linkages of a sentence), call this once for every generated linkage.
    `PPNode` | `post_process(Postprocessor pp, ParseOptions opts, Sublinkage sublinkage, boolean cleanup)` Takes a sublinkage and returns: .
    `int` | `power_hash(Connector c)` This hash function only looks at the leading upper case letters of the connector string, and the label fields.
    `int` | `power_prune(int mode, ParseOptions opts)` Here is what you've been waiting for: POWER-PRUNE
    `void` | `pp_and_power_prune(int mode, ParseOptions opts)`
    `int` | `pp_prune(ParseOptions opts)`
    `void` | `prepare_to_parse(ParseOptions opts)` assumes that the sentence expression lists have been generated this does all the necessary pruning and building of and structures.
    `void` | `print_AND_statistics(ParseOptions opts)`
    `void` | `print_disjunct_counts(ParseOptions opts)`
    `void` | `print_expression_sizes(ParseOptions opts)`
    `void` | `print_parse_statistics(ParseOptions opts)`
    `void` | `prune_irrelevant_rules(ParseOptions opts, Postprocessor pp)` call this (a) after having called post_process_scan_linkage() on all generated linkages, but (b) before calling post_process() on any particular linkage.
    `void` | `prune(ParseOptions opts)`
    `int` | `pseudocount(int lw, int rw, Connector le, Connector re, int cost)`
    `void` | `put_disjunct_into_table(Disjunct d)`
    `static void` | `put_into_match_table(int size, MatchNode[] t, Disjunct d, Connector c, int dir)` The disjunct d (whose left or right pointer points to c) is put into the appropriate hash table
    `void` | `put_into_power_table(int size, CList[] t, Connector c, boolean shal)` The disjunct d (whose left or right pointer points to c) is put into the appropriate hash table
    `int` | `region_valid(int lw, int rw, Connector le, Connector re)` CONJUNCTION PRUNING.
    `int` | `right_connector_count(Disjunct d)` returns the number of connectors in the right lists of the disjuncts.
    `int` | `right_connector_list_update(Connector c, int word_c, int w, boolean shallow)` take this connector list, and try to match it with the words w+1, w+2, w+3...Returns the word to which the first connector of the list could possibly be matched.
    `static int` | `right_disjunct_list_length(Disjunct d)` the number of disjuncts in the list that have non-null right connector lists
    `boolean` | `right_table_search(int w, Connector c, boolean shallow, int word_c)`
    `boolean` | `rule_satisfiable(PPLinkset ls)`
    `boolean` | `sentence_contains_conjunction()` We've already built the sentence expressions.
    `boolean` | `sentence_contains(java.lang.String s)`
    `int` | `sentence_disjunct_cost(int i)`
    `java.lang.String` | `sentence_get_word(int index)`
    `int` | `sentence_length()` get sentence word.size() in words
    `int` | `sentence_null_count()`
    `int` | `sentence_num_linkages_found()`
    `int` | `sentence_num_linkages_post_processed()`
    `int` | `sentence_num_valid_linkages()`
    `int` | `sentence_num_violations(int i)`
    `int` | `sentence_parse(ParseOptions opts)` Step three in parsing a sentence.
    `boolean` | `separate_sentence(java.lang.String s, ParseOptions opts)` The string s has just been read in from standard input.
    `int` | `set_dist_fields(Connector c, int w, int delta)`
    `boolean` | `set_has_fat_down()`
    `void` | `set_is_conjunction()` How is the is_conjunction table initialized? TODO - Remove English dependancy Also what about "yet", "however", "then", "else", "whence", "thus", ...
    `int` | `size_of_sentence_expressions()` Computes and returns the number of connectors in all of the expressions of the sentence.
    `int` | `size()`
    `static Disjunct` | `special_disjunct(int label, int dir, java.lang.String cs, java.lang.String ds)` Builds a new disjunct with one connector pointing in direction dir (which is '+' or '-').
    `void` | `stick_in_one_connector(java.lang.StringBuffer s, Connector c, int len)`
    `static boolean` | `strictly_smaller_name(java.lang.String s, java.lang.String t)`
    `boolean` | `strictly_smaller(java.lang.String s, java.lang.String t)`
    `static int` | `table_lookup(int lw, int rw, Connector le, Connector re, int cost)`
    `static TableConnector` | `table_pointer(int lw, int rw, Connector le, Connector re, int cost)`
    `static TableConnector` | `table_store(int lw, int rw, Connector le, Connector re, int cost, int count)` Stores the value in the table this.ctable.
    `(package private) void` | `table_update(int lw, int rw, Connector le, Connector re, int cost, int count)`
    `static void` | `zero_S()`

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Field Detail

    - #### dict

          public Dictionary dict

      words are defined from this dictionary

    - #### word

          public java.util.ArrayList<Word> word

      array of words after tokenization

    - #### deletable

          public boolean[][] deletable

      deletable regions in a sentence with conjunction

    - #### effective_dist

          public int[][] effective_dist

      created by build_effective_dist()
      See Also:
        `build_effective_dist(boolean)`

    - #### num_linkages_found

          public int num_linkages_found

      total number linkages before postprocessing. This is returned by the count() function

    - #### num_linkages_alloced

          public int num_linkages_alloced

      total number of linkages allocated. the number post-processed might be fewer because some are non-canonical

    - #### num_linkages_post_processed

          public int num_linkages_post_processed

      The number of linkages that are actually put into the array that was alloced. this is not the same as num alloced because some may be non-canonical.

    - #### num_valid_linkages

          public int num_valid_linkages

      number with no pp violations

    - #### null_count

          public int null_count

      number of null links in linkages

    - #### parse_info

          public ParseInfo parse_info

      set of parses for the sentence

    - #### link_info

          public LinkageInfo[] link_info

      array of valid and invalid linkages (sorted)

    - #### and_data

          public AndData and_data

      used to keep track of fat disjuncts

    - #### q_pruned_rules

          public boolean q_pruned_rules

      don't prune rules more than once in p.p.

    - #### post_quote

          public int[] post_quote

    - #### patch_array

          public PatchElement[] patch_array

    - #### null_links

          public static boolean null_links

    - #### ctable_size

          public static int ctable_size

      The size of this.ctable TODO - make this Java, not C, and use the collection object stuff! sp that ctable size can not be modified independently of ctable.

    - #### ctable

          public static TableConnector[] ctable

      The TableConnector table associated with this sentence instance object

    - #### match_cost

          public static int match_cost

    - #### match_l_table_size

          public static int[] match_l_table_size

    - #### match_r_table_size

          public static int[] match_r_table_size

    - #### match_l_table

          public static MatchNode[][] match_l_table

    - #### match_r_table

          public static MatchNode[][] match_r_table

    - #### structure_violation

          public static boolean structure_violation

    - #### visited

          public static boolean[] visited

    - #### and_element_sizes

          public static int[] and_element_sizes

    - #### and_element

          public static int[] and_element

    - #### N_and_elements

          public static int N_and_elements

    - #### outside_word

          public static int[] outside_word

    - #### N_outside_words

          public static int N_outside_words

    - #### has_fat_down

          public static boolean[] has_fat_down

    - #### image_array

          public static ImageNode[] image_array

    - #### s_table_size

          public static int s_table_size

    - #### table

          public static Connector[] table

    - #### power_cost

          public static int power_cost

    - #### power_prune_mode

          public static int power_prune_mode

    - #### N_changed

          public static int N_changed

    - #### power_l_table_size

          public static int[] power_l_table_size

    - #### power_r_table_size

          public static int[] power_r_table_size

    - #### power_l_table

          public static CList[][] power_l_table

    - #### power_r_table

          public static CList[][] power_r_table

    - #### CMS_SIZE

          public static final int CMS_SIZE

      See Also:
        Constant Field Values

    - #### cms_table

          public static Cms[] cms_table

  - ### Constructor Detail

    - #### Sentence

          public Sentence(java.lang.String input_string,
                  Dictionary dict,
                  ParseOptions opts)

  - ### Method Detail

    - #### separate_sentence

          public boolean separate_sentence(java.lang.String s,
                                  ParseOptions opts)

      The string s has just been read in from standard input. This function breaks it up into words and stores these words in the sent.word[] array. Quote marks are treated just like blanks.
      Parameters:
        `s` - sentence in String form
        `opts` - passes ParseOptions - In reality these are often kept in global variables. TODO - clean up code
      Returns:
        Returns true if all is well, false otherwise.
      See Also:
        `ParseOptions`

    - #### build_sentence_expressions

          public void build_sentence_expressions(ParseOptions opts)

      Corrects case of first word, fills in other proper nouns, and builds the expression lists for the resulting words.

      Algorithm:

      - Apply the following step to all words w:
      - if w is in the dictionary, use it.
      - else if w is upper case use PROPER_WORD disjuncts for w.
      - else if it's hyphenated, use HYPHENATED_WORD
      - else if it's a number, use NUMBER_WORD.
      - Now, we correct the first word, w.
      - if w is upper case, let w' be the lower case version of w.
      - if both w and w' are in the dict, concatenate these disjuncts.
      - else if w' is in dict, use disjuncts of w'
      - else leave the disjuncts alone

        Here's a summary of how subscripts are handled:

        Reading the dictionary:

        If the last "." in a string is followed by a non-digit character, then the "." and everything after it is considered to be the subscript of the word.

        The dictionary reader does not allow you to have two words that match according to the criterion below. (so you can't have "dog.n" and "dog")

        Quote marks are used to allow you to define words in the dictionary which would otherwise be considered part of the dictionary, as in

        ";": {@Xca-} & Xx- & (W+ or Qd+) & {Xx+}; "%" : (ND- & {DD-} & \ & (\ or B*x+)) or (ND- & (OD- or AN+));

        Rules for chopping words from the input sentence:

        First the prefix chars are stripped off of the word. These characters are "(" and "$" (and now "``")

        Now, repeat the following as long as necessary:

        Look up the word in the dictionary. If it's there, the process terminates.

        If it's not there and it ends in one of the right strippable strings (see "right_strip") then remove the strippable string and make it into a separate word.

        If there is no strippable string, then the process terminates.

        Rule for defining subscripts in input words:

        The subscript rule is followed just as when reading the dictionary.

        When does a word in the sentence match a word in the dictionary?

        Matching is done as follows: Two words with subscripts must match exactly. If neither has a subscript they must match exactly. If one does and one doesn't then they must match when the subscript is removed. Notice that this is symmetric.

        So, under this system, the dictonary could have the words "Ill" and also the word "Ill." It could also have the word "i.e.", which could be used in a sentence.

      Parameters:
        `opts` - - not used everything comes from GlobalBean. TODO - Fix or drop

    - #### size

          public int size()

    - #### initialize_conjunction_tables

          public void initialize_conjunction_tables()

      See Also:
        `AndData`

    - #### set_is_conjunction

          public void set_is_conjunction()

      How is the is_conjunction table initialized? TODO - Remove English dependancy Also what about "yet", "however", "then", "else", "whence", "thus", ... Word word.get(w) has a list of equivilent expressions that should be followed what is needed here is: if (isConjunct(word.get(w))||isDisjunct(word.get(w))||isAdjunct(word.get(w))) then is_conjunction[w] = true; where isConjunct(Word word) walks down the list of equivilent expressions

    - #### sentence_length

          public int sentence_length()

      get sentence word.size() in words
      Returns:
        int word.size()

    - #### prepare_to_parse

          public void prepare_to_parse(ParseOptions opts)

      assumes that the sentence expression lists have been generated this does all the necessary pruning and building of and structures.
      Parameters:
        `opts` - parsing options

    - #### conjunction_prune

          public void conjunction_prune(ParseOptions opts)

      We've already built the sentence disjuncts, and we've pruned them and power_pruned(GENTLE) them also. The sentence contains a conjunction. deletable[][] has been initialized to indicate the ranges which may be deleted in the final linkage. This routine deletes irrelevant disjuncts. It finds them by first marking them all as irrelevant, and then marking the ones that might be useable. Finally, the unmarked ones are removed.
      Parameters:
        `opts` - parsing options used to set tolerance for nulls

    - #### region_valid

          public int region_valid(int lw,
                         int rw,
                         Connector le,
                         Connector re)

      CONJUNCTION PRUNING. The basic idea is this. Before creating the fat disjuncts, we run a modified version of the exhaustive search procedure. Its purpose is to mark the disjuncts that can be used in any linkage. It's just like the normal exhaustive search, except that if a subrange of words are deletable, then we treat them as though they were not even there. So, if we call the function in the situation where the set of words between the left and right one are deletable, and the left and right connector pointers are null, then that range is considered to have a solution. There are actually two procedures to implement this. One is mark_region() and the other is region_valid(). The latter just checks to see if the given region can be completed (within it). The former actually marks those disjuncts that can be used in any valid linkage of the given region. As in the standard search procedure, we make use of the fast-match data structure (which requires power pruning to have been done), and we also use a hash table. The table is used differently in this case. The meaning of values stored in the table are as follows: -1 Nothing known (Actually, this is not stored. It's returned by table_lookup when nothing is known.) 0 This region can't be completed (marking is therefore irrelevant) 1 This region can be completed, but it's not yet marked 2 This region can be completed, and it's been marked.
      Parameters:
        `lw` - integer word number of left wall
        `rw` - integer word number of right wall
        `le` - left expression
        `re` - right expression
      Returns:
        Returns 0 if this range cannot be successfully filled in with links. Returns 1 if it can, and it's not been marked, and Returns 2 if it can and it has been marked.

    - #### form_match_list

          public static MatchNode form_match_list(int w,
                                  Connector lc,
                                  int lw,
                                  Connector rc,
                                  int rw)

      Forms and returns a list of disjuncts that might match lc or rc or both. lw and rw are the words from which lc and rc came respectively. The list is formed by the link pointers of MatchNodes. The list contains no duplicates. A quadratic algorithm is used to eliminate duplicates. In practice the match_cost is less than the parse_cost (and the loop is tiny), so there's no reason to bother to fix this.
      Parameters:
        `w` - array index of word to match
        `lc` - left Connector
        `lw` - index into word array of left word
        `rc` - right Connector
        `rw` - index into word array of right word
      Returns:
        the right match

    - #### get_match_node

          static MatchNode get_match_node()

    - #### table_update

          void table_update(int lw,
                          int rw,
                          Connector le,
                          Connector re,
                          int cost,
                          int count)

    - #### mark_region

          void mark_region(int lw,
                         int rw,
                         Connector le,
                         Connector re)

    - #### explode_disjunct_list

          Disjunct explode_disjunct_list(Disjunct d)

    - #### build_COMMA_disjunct_list

          Disjunct build_COMMA_disjunct_list()

    - #### install_fat_connectors

          void install_fat_connectors()

    - #### build_fat_link_substitutions

          Disjunct build_fat_link_substitutions(Disjunct d)

    - #### connector_for_disjunct

          public void connector_for_disjunct(Disjunct d,
                                    Connector c)

      Parameters:
        `d` -
        `c` -

    - #### build_AND_disjunct_list

          public Disjunct build_AND_disjunct_list(java.lang.String s)

      Builds and returns a disjunct list for "and", "or" and "nor" for each disjunct in the label_table, we build three disjuncts this means that "Danny and Tycho and Billy" will be parsable in two ways. I don't know an easy way to avoid this the string is either "and", or "or", or "nor" at the moment

      must accommodate "he and I are good", "Davy and I are good" "Danny and Davy are good", and reject all of these with "is" instead of "are".

      The SI connectors must also be modified to accommodate "are John and Dave here", but kill "is John and Dave here"

      Then we consider "a cat or a dog is here" vs "a cat or a dog are here" The first seems right, the second seems wrong. I'll stick with this. That is, "or" has the property that if both parts are the same in number, we use that but if they differ, we use plural.

      The connectors on "I" must be handled specially. We accept "I or the dogs are here" but reject "I or the dogs is here"

      TODO - the code here still does now work "right", rejecting "is John or I invited" and accepting "I or my friend know what happened" The more generous code for "nor" has been used instead

      It appears that the "nor" of two things can be either singular or plural.

      "neither she nor John likes dogs"

      "neither she nor John like dogs"

      Parameters:
        `s` -
      Returns:
        head of a disjunct list
      See Also:
        `Connector`

    - #### build_conjunction_tables

          public void build_conjunction_tables()

    - #### compute_matchers_for_a_label

          public void compute_matchers_for_a_label(int k)

      Parameters:
        `k` -

    - #### stick_in_one_connector

          public void stick_in_one_connector(java.lang.StringBuffer s,
                                    Connector c,
                                    int len)

      Parameters:
        `s` -
        `c` -
        `len` -

    - #### extract_all_fat_links

          public void extract_all_fat_links(Disjunct d)

      Parameters:
        `d` -

    - #### put_disjunct_into_table

          public void put_disjunct_into_table(Disjunct d)

      Parameters:
        `d` -

    - #### grow_LT

          void grow_LT()

    - #### is_appropriate

          public boolean is_appropriate(Disjunct d)

      returns true if the disjunct is appropriate to be made into fat links. Check here that the connectors are from some small set. This will disallow, for example "the and their dog ran".

      TODO: move to dict

      Parameters:
        `d` -
      Returns:
        true if the disjunct is appropriate to be made into fat links

    - #### init_HT

          public void init_HT()

    - #### init_LT

          public void init_LT()

    - #### print_AND_statistics

          public void print_AND_statistics(ParseOptions opts)

      Parameters:
        `opts` -

    - #### build_effective_dist

          public void build_effective_dist(boolean has_conjunction)

      Parameters:
        `has_conjunction` -

    - #### build_deletable

          public void build_deletable(boolean has_conjunction)

      Initialize the array deletable[i][j] to indicate if the words i+1...j-1 could be non existant in one of the multiple linkages. This array is used in conjunction_prune and power_prune. Regions of word.size() 0 are always deletable. A region of word.size() two with a conjunction at one end is always deletable. Another observation is that for the comma to form the right end of a deletable region, it must be the case that there is a conjunction to the right of the comma. Also, when considering deletable regions with a comma on their left sides, there must be a conjunction inside the region to be deleted. Finally, the words "either", "neither", "both", "not" and "not only" are all deletable.

      TODO - This is awfully ethnocentric. What about other languages, or words like thus, thence, whence etc. This should be a loadable array!

      Parameters:
        `has_conjunction` -

    - #### conj_in_range

          public boolean conj_in_range(int lw,
                              int rw)

      Determin if there is a conjunction between the suppled right and left words.
      Parameters:
        `lw` - integer index of left word
        `rw` - integer index of right word
      Returns:
        true if the range lw...rw inclusive contains a conjunction

    - #### sentence_parse

          public int sentence_parse(ParseOptions opts)

      Step three in parsing a sentence. First you must create a dictionary, then a sentence, then call this method to generate a parse tree. This is really the heart of the system. There are several things done when a sentence is parsed.
      - Word expressions are extracted from the dictionary and pruned
      - Disjuncts are built
      - Aseries of pruning operations are carried out.
      - The linkages having the minimum number of null links are counted.
      - A "parse set" of linkages is built.
      - The linkages are post processed
      The "parse set" is attached to the sentence, and this is one of the key reasons that the API is flexible and modular. All of the necessary information for building linkages is stored in the parse set. This means that other sentences can be parsed, possibly using different dictionaries, without disturbing the information obtained from a call to sentence_parse. If another call to sentence_parse is made on the same sentence, the parsing information for the previous call is deleted.

      O.K. that may be true of the C code version but in this code a lot of information from ParseOptions is held in GlobalBean.

      TODO - Make the dictionary and ParseInfo private to the sentence. Then add getter and setter methods.

      Parameters:
        `opts` -
      Returns:
        the number of valid linkages.
      See Also:
        `num_linkages_found`

    - #### parse

          public int parse(int cost,
                  ParseOptions opts)

      Returns the number of null links the sentence can be parsed with the specified cost Assumes that the hash table this.ctable has already been initialized, and is freed later.
      Parameters:
        `cost` -
        `opts` -
      Returns:
        the number of null links in this.ctable

    - #### count

          public int count(int lw,
                  int rw,
                  Connector le,
                  Connector re,
                  int cost,
                  ParseOptions opts)

      Parameters:
        `lw` -
        `rw` -
        `le` -
        `re` -
        `cost` -
        `opts` -
      Returns:
        the total number of links in a TableConnector this.ctable matching input parameters

    - #### pseudocount

          public int pseudocount(int lw,
                        int rw,
                        Connector le,
                        Connector re,
                        int cost)

      Parameters:
        `lw` -
        `rw` -
        `le` -
        `re` -
        `cost` -
      Returns:
        0 if and only if this entry is in the hash table with a count value of 0

    - #### init_x_table

          public void init_x_table()

      A piecewise exponential function determines the size of the hash table. Probably should make use of the actual number of disjuncts, rather than just the number of words

    - #### init_table

          public void init_table()

      A piecewise exponential function determines the size of the hash table. Probably should make use of the actual number of disjuncts, rather than just the number of words

    - #### table_lookup

          public static int table_lookup(int lw,
                         int rw,
                         Connector le,
                         Connector re,
                         int cost)

      Parameters:
        `lw` -
        `rw` -
        `le` -
        `re` -
        `cost` -
      Returns:
        the count for this quintuple if there, -1 otherwise
      See Also:
        `TableConnector.lw`, `TableConnector.rw`, `TableConnector.le`, `TableConnector.re`, `TableConnector.cost`

    - #### hash

          public static int hash(int lw,
                 int rw,
                 Connector le,
                 Connector re,
                 int cost)

      Parameters:
        `lw` -
        `rw` -
        `le` -
        `re` -
        `cost` -
      Returns:
        hash used in this.ctable
      See Also:
        `TableConnector.lw`, `TableConnector.rw`, `TableConnector.le`, `TableConnector.re`, `TableConnector.cost`

    - #### table_pointer

          public static TableConnector table_pointer(int lw,
                                     int rw,
                                     Connector le,
                                     Connector re,
                                     int cost)

      Parameters:
        `lw` -
        `rw` -
        `le` -
        `re` -
        `cost` -
      Returns:
        the pointer to this info, null if not there
      See Also:
        `TableConnector.lw`, `TableConnector.rw`, `TableConnector.le`, `TableConnector.re`, `TableConnector.cost`

    - #### table_store

          public static TableConnector table_store(int lw,
                                   int rw,
                                   Connector le,
                                   Connector re,
                                   int cost,
                                   int count)

      Stores the value in the table this.ctable. Assumes it's not already there
      Parameters:
        `lw` -
        `rw` -
        `le` -
        `re` -
        `cost` -
        `count` -
      Returns:
        a new TableConnector
      See Also:
        `TableConnector.lw`, `TableConnector.rw`, `TableConnector.le`, `TableConnector.re`, `TableConnector.cost`, `TableConnector.next`, `init_table()`

    - #### init_fast_matcher

          public void init_fast_matcher()

    - #### left_disjunct_list_length

          public static int left_disjunct_list_length(Disjunct d)

      Parameters:
        `d` -
      Returns:
        the number of disjuncts in the list that have non-null left connector lists

    - #### right_disjunct_list_length

          public static int right_disjunct_list_length(Disjunct d)

      the number of disjuncts in the list that have non-null right connector lists
      Parameters:
        `d` -
      Returns:
        the number of disjuncts in the list that have non-null right connector lists

    - #### put_into_match_table

          public static void put_into_match_table(int size,
                                  MatchNode[] t,
                                  Disjunct d,
                                  Connector c,
                                  int dir)

      The disjunct d (whose left or right pointer points to c) is put into the appropriate hash table

      dir = 1, we're putting this into a right table.

      dir = -1, we're putting this into a left table.

      Parameters:
        `size` -
        `t` -
        `d` -
        `c` -
        `dir` -

    - #### fast_match_hash

          public static int fast_match_hash(Connector c)

      This hash function only looks at the leading upper case letters of the connector string, and the label fields. This ensures that if two strings match (formally), then they must hash to the same place. The answer must be masked to the appropriate table size.
      Parameters:
        `c` -
      Returns:
        the index into the hash table

    - #### add_to_right_table_list

          public static MatchNode add_to_right_table_list(MatchNode m,
                                          MatchNode l)

      Adds the match node m to the sorted list of match nodes l. The parameter dir determines the order of the sorting to be used. Makes the list sorted from smallest to largest.
      Parameters:
        `m` - the node to add
        `l` - the node to which we are to add m on the right
      Returns:
        The matched node's right index

    - #### add_to_left_table_list

          public static MatchNode add_to_left_table_list(MatchNode m,
                                         MatchNode l)

      Adds the match node m to the sorted list of match nodes l. The parameter dir determines the order of the sorting to be used. Makes the list sorted from largest to smallest
      Parameters:
        `m` - the node to add
        `l` - the node to which we are to add m on the right
      Returns:
        The matched node's left index

    - #### build_parse_set

          public boolean build_parse_set(int cost,
                                ParseOptions opts)

      This is the top level call that computes the whole parse_set. It points whole_set at the result. It creates the necessary hash table (x_table) which will be freed at the same time the whole_set is freed.

      It also assumes that count() has been run, and that hash table is filled with the values thus computed. Therefore this function must be structured just like parse() (the main function for count()).

      If the number of linkages gets huge, then the counts can overflow. We check if this has happened when verifying the parse set. This routine returns true iff overflowed occurred.

      This method modifies this.loca-sent, this.parse_info

      Parameters:
        `cost` -
        `opts` -
      Returns:
        the result of ParseInfo.verify_set
      See Also:
        `ParseInfo.verify_set()`, `Word`, `parse_info`

    - #### build_sentence_disjuncts

          public void build_sentence_disjuncts(ParseOptions opts,
                                      int cost_cutoff)

      We've already built the sentence expressions. This turns them into disjuncts. The method modifies this.word by adding the disjuncts to word[index].d
      Parameters:
        `opts` - - refers to this.cost_cutoff that is set from ParseInfo pi at object creation. TODO - Fix where ParseInfo is kept.
        `cost_cutoff` -
      See Also:
        `word`, `Word.d`

    - #### build_disjuncts_for_XNode

          public Disjunct build_disjuncts_for_XNode(ParseOptions opts,
                                           XNode x,
                                           int cost_cutoff)

      Parameters:
        `opts` - unused - refers to this.cost_cutoff that is set from ParseInfo pi at object creation. TODO - Fix where ParseInfo is kept.
        `x` - is the Word expression list node
        `cost_cutoff` -
      Returns:
        a linked list of dijuncts for the named node
      See Also:
        `Word.x`

    - #### sentence_contains_conjunction

          public boolean sentence_contains_conjunction()

      We've already built the sentence expressions. This turns them into disjuncts. Assumes is_conjunction[] has been initialized.
      Returns:
        true if there are conjunctions

    - #### print_disjunct_counts

          public void print_disjunct_counts(ParseOptions opts)

      Parameters:
        `opts` -

    - #### post_process_linkages

          public void post_process_linkages(ParseOptions opts)

      This is another top level call. It is called by default when you create a new Linkage object. If you want another postprocessor this is the method to call.
      Parameters:
        `opts` -
      See Also:
        `Linkage.Linkage(int, Sentence, ParseOptions)`

    - #### fill_patch_array_DIS

          public void fill_patch_array_DIS(DISNode dn,
                                  LinksToPatch ltp)

      Patches up appropriate links in the patch_array for this DISNode and this patch list.
      Parameters:
        `dn` -
        `ltp` -

    - #### fill_patch_array_CON

          public void fill_patch_array_CON(CONNode cn,
                                  LinksToPatch ltp)

      Parameters:
        `cn` -
        `ltp` -

    - #### analyze_fat_linkage

          public LinkageInfo analyze_fat_linkage(ParseOptions opts,
                                        int analyze_pass)

      This uses link_array. It enumerates and post-processes all the linkages represented by this one. We know this contains at least one fat link.
      Parameters:
        `opts` -
        `analyze_pass` -
      Returns:
        a new LinkageInfo object based on this.parse_info
      See Also:
        `ParseInfo`

    - #### post_process_scan_linkage

          public void post_process_scan_linkage(Postprocessor pp,
                                       ParseOptions opts,
                                       Sublinkage sublinkage)

      During a first pass (prior to actual post-processing of the linkages of a sentence), call this once for every generated linkage. Here we simply maintain a set of "seen" link names for rule pruning later on
      Parameters:
        `pp` -
        `opts` -
        `sublinkage` -

    - #### prune_irrelevant_rules

          public void prune_irrelevant_rules(ParseOptions opts,
                                    Postprocessor pp)

      call this (a) after having called post_process_scan_linkage() on all generated linkages, but (b) before calling post_process() on any particular linkage. Here we mark all rules which we know (from having accumulated a set of link names appearing in *any* linkage) won't ever be needed.
      Parameters:
        `opts` -
        `pp` -

    - #### post_process

          public PPNode post_process(Postprocessor pp,
                            ParseOptions opts,
                            Sublinkage sublinkage,
                            boolean cleanup)

      Takes a sublinkage and returns:
      - . for each link, the domain structure of that link
      - . a list of the violation strings

      NB: sublinkage.link[i].l=-1 means that this connector is to be ignored

      Parameters:
        `pp` -
        `opts` -
        `sublinkage` -
        `cleanup` -
      Returns:
        a PPNode for the linkage in the given postprocessor or null if none or the postprocessor is not valid

    - #### compute_pp_link_array_connectors

          public void compute_pp_link_array_connectors(Sublinkage sublinkage)

      This takes as input link_array[], sublinkage.link[].l and sublinkage.link[].r (and also has_fat_down[word], which has been computed in a prior call to is_canonical()), and from these computes sublinkage.link[].lc and .rc. We assume these have been initialized with the values from link_array. We also assume that there are fat links.
      Parameters:
        `sublinkage` -

    - #### compute_pp_link_names

          public void compute_pp_link_names(Sublinkage sublinkage)

      This fills in the sublinkage.link[].name field. We assume that link_array[].name have already been filled in. As above, in the standard case, the name is just the GCD of the two end points. If pluralization has occurred, then we want to use the name already in link_array[].name. We detect this in two ways. If the endpoints don't match, then we know pluralization has occured. If they do, but the name in link_array[].name is *less* restrictive, then pluralization must have occured.
      Parameters:
        `sublinkage` -

    - #### copy_d_type

          public static DTypeList copy_d_type(DTypeList dtl)

      Copy the named Domain Type List and return a copy
      Parameters:
        `dtl` -
      Returns:
        head of the DTypeList

    - #### build_andlist

          public AndList build_andlist()

      This function computes the "and cost", resulting from inequalities in the word.size() of and-list elements. It also computes other information used to construct the "andlist" structure of linkage_info.
      Returns:
        list of conunctions
      See Also:
        `for a detailed explanation of And`

    - #### analyze_thin_linkage

          public LinkageInfo analyze_thin_linkage(ParseOptions opts,
                                         int analyze_pass)

      This uses link_array. It post-processes this linkage, and prints the appropriate thing. There are no fat links in it.

      The code can be used to generate the "islands" array. For this to work, however, you have to call "build_digraph" first (as in analyze_fat_linkage). and then "free_digraph". For some reason this causes a space leak.

      Parameters:
        `opts` -
        `analyze_pass` -
      Returns:
        a valid LinkageInfo

    - #### is_canonical_linkage

          public boolean is_canonical_linkage()

      uses link_array[], chosen_disjuncts[], has_fat_down[]. It assumes that there is a fat link in the current linkage. See AndData() for more information about how it works
      Returns:
        true if it is cannonical
      See Also:
        `AndData`

    - #### strictly_smaller

          public boolean strictly_smaller(java.lang.String s,
                                 java.lang.String t)

      Parameters:
        `s` -
        `t` -
      Returns:
        true if string s represents a strictly smaller match set than does t

    - #### find_subdisjunct

          public Disjunct find_subdisjunct(Disjunct dis,
                                  int label)

      Find the specific disjunct of in label_table[label] which corresponds to dis.
      Parameters:
        `dis` - a disjunct in the label_table
        `label` - lable_table containing a disjunct
      Returns:
        first disjunct

    - #### build_image_array

          public void build_image_array()

    - #### size_of_sentence_expressions

          public int size_of_sentence_expressions()

      Computes and returns the number of connectors in all of the expressions of the sentence.
      Returns:
        the number of connectors in all of the expressions

    - #### clean_up_expressions

          public void clean_up_expressions(int w)

      This removes the expressions that are empty from the list corresponding to word w of the sentence.
      Parameters:
        `w` -

    - #### expression_prune

          public void expression_prune(ParseOptions opts)

      Parameters:
        `opts` -

    - #### print_expression_sizes

          public void print_expression_sizes(ParseOptions opts)

      Parameters:
        `opts` -

    - #### zero_S

          public static void zero_S()

    - #### free_S

          public static void free_S()

    - #### insert_S

          public static void insert_S(Connector c)

      Parameters:
        `c` -

    - #### hash_S

          public static int hash_S(Connector c)

      This hash function only looks at the leading upper case letters of the connector string, and the label fields. This ensures that if two strings match (formally), then they must hash to the same place.
      Parameters:
        `c` -
      Returns:
        the hash of the connector

    - #### print_parse_statistics

          public void print_parse_statistics(ParseOptions opts)

      Parameters:
        `opts` -

    - #### matches_S

          public boolean matches_S(Connector c,
                          int dir)

      returns true if c can match anything in the set S because of the horrible kludge, prune match is assymetric, and direction is '-' if this is an l.r pass, and '+' if an r.l pass.
      Parameters:
        `c` -
        `dir` -
      Returns:
        returns true if c can match anything in the set S

    - #### sentence_get_word

          public java.lang.String sentence_get_word(int index)

      Parameters:
        `index` -
      Returns:
        the String form of the word at the named index in this.word
      See Also:
        `word`

    - #### sentence_null_count

          public int sentence_null_count()

      Returns:
        the number of null linkages?

    - #### sentence_num_linkages_found

          public int sentence_num_linkages_found()

      Returns:
        the number of linkages found

    - #### sentence_num_valid_linkages

          public int sentence_num_valid_linkages()

      Returns:
        the number of valid linkages

    - #### sentence_num_linkages_post_processed

          public int sentence_num_linkages_post_processed()

    - #### sentence_num_violations

          public int sentence_num_violations(int i)

    - #### sentence_disjunct_cost

          public int sentence_disjunct_cost(int i)

    - #### set_has_fat_down

          public boolean set_has_fat_down()

    - #### compute_link_names

          public void compute_link_names()

    - #### strictly_smaller_name

          public static boolean strictly_smaller_name(java.lang.String s,
                                      java.lang.String t)

    - #### intersect_strings

          public static java.lang.String intersect_strings(java.lang.String s,
                                           java.lang.String t)

    - #### free_sentence_disjuncts

          public void free_sentence_disjuncts()

    - #### free_HT

          public void free_HT()

    - #### free_LT

          public void free_LT()

    - #### free_AND_tables

          public void free_AND_tables()

    - #### free_parse_set

          public void free_parse_set()

    - #### install_special_conjunctive_connectors

          public void install_special_conjunctive_connectors()

    - #### sentence_contains

          public boolean sentence_contains(java.lang.String s)

    - #### glom_comma_connector

          public static Disjunct glom_comma_connector(Disjunct d)

      This file contains the functions for massaging disjuncts of the sentence in special ways having to do with conjunctions. The only function called from the outside world is install_special_conjunctive_connectors()

      It would be nice if this code was written more transparently. In other words, there should be some fairly general functions that manipulate disjuncts, and take words like "neither" etc as input parameters, so as to encapsulate the changes being made for special words. This would not be too hard to do, but it's not a high priority. -DS 3/98

      There's a problem with installing "...but...", "not only...but...", and "not...but...", which is that the current comma mechanism will allow a list separated by commas. "Not only John, Mary but Jim came" The best way to prevent this is to make it impossible for the comma to attach to the "but", via some sort of additional subscript on commas.

      I can't think of a good way to prevent this.

      The following functions all do slightly different variants of the following thing:

      Catenate to the disjunct list pointed to by d, a new disjunct list. The new list is formed by copying the old list, and adding the new connector somewhere in the old disjunct, for disjuncts that satisfy certain conditions

    - #### glom_aux_connector

          public static Disjunct glom_aux_connector(Disjunct d,
                                    int label,
                                    boolean necessary)

      In this case the connector is to connect to the "either", "neither", "not", or some auxilliary d to the current which is a conjunction. Only gets added next to a fat link, but before it (not after it) In the case of "nor", we don't create new disjuncts, we merely modify existing ones. This forces the fat link uses of "nor" to use a neither. (Not the case with "or".) If necessary=false, then duplication is done, otherwise it isn't

    - #### add_one_connector

          public static Disjunct add_one_connector(int label,
                                   int dir,
                                   java.lang.String cs,
                                   Disjunct d)

      This adds one connector onto the beginning of the left (or right) connector list of d. The label and string of the connector are specified

    - #### special_disjunct

          public static Disjunct special_disjunct(int label,
                                  int dir,
                                  java.lang.String cs,
                                  java.lang.String ds)

      Builds a new disjunct with one connector pointing in direction dir (which is '+' or '-'). The label and string of the connector are specified, as well as the string of the disjunct. The next pointer of the new disjunct set to null, so it can be regarded as a list.

    - #### pp_prune

          public int pp_prune(ParseOptions opts)

    - #### pp_and_power_prune

          public void pp_and_power_prune(int mode,
                                ParseOptions opts)

    - #### delete_unmarked_disjuncts

          public void delete_unmarked_disjuncts()

    - #### clean_up

          public void clean_up(int w)

      Step three of the sentence_parse operation - pruning

      The algorithms in this file prune disjuncts from the disjunct list of the sentence that can be elimininated by a simple checks. The first check works as follows:

      A series of passes are made through the sentence, alternating left-to-right and right-to-left. Consider the left-to-right pass (the other is symmetric). A set S of connectors is maintained (initialized to be empty). Now the disjuncts of the current word are processed. If a given disjunct's left pointing connectors have the property that at least one of them has no connector in S to which it can be matched, then that disjunct is deleted. Now the set S is augmented by the right connectors of the remaining disjuncts of that word. This completes one word. The process continues through the words from left to right. Alternate passes are made until no disjunct is deleted.

      It worries me a little that if there are some really huge disjuncts lists, then this process will probably do nothing. (This fear turns out to be unfounded.)

      Notes: Power pruning will not work if applied before generating the "and" disjuncts. This is because certain of it's tricks don't work. Think about this, and finish this note later.... Also, currently I use the standard connector match procedure instead of the pruning one, since I know power pruning will not be used before and generation. Replace this to allow power pruning to work before generating and disjuncts.

      Currently it seems that normal pruning, power pruning, and generation, pruning, and power pruning (after "and" generation) and parsing take about the same amount of time. This is why doing power pruning before "and" generation might be a very good idea.

      New idea: Suppose all the disjuncts of a word have a connector of type c pointing to the right. And further, suppose that there is exactly one word to its right containing that type of connector pointing to the left. Then all the other disjuncts on the latter word can be deleted. (This situation is created by the processing of "either...or", and by the extra disjuncts added to a "," neighboring a conjunction.)

      see AndData()

    - #### count_disjuncts_in_sentence

          public int count_disjuncts_in_sentence()

    - #### power_prune

          public int power_prune(int mode,
                        ParseOptions opts)

      Here is what you've been waiting for: POWER-PRUNE

      The kinds of constraints it checks for are the following:

      1) successive connectors on the same disjunct have to go to nearer and nearer words.

      2) two deep connectors cannot attach to eachother (A connectors is deep if it is not the first in its list, it is shallow if it is the first in its list, it is deepest if it is the last on its list.)

      3) on two adjacent words, a pair of connectors can be used only if they're the deepest ones on their disjuncts

      4) on two non-adjacent words, a pair of connectors can be used only if not [both of them are the deepest].

      The data structure consists of a pair of hash tables on every word. Each bucket of a hash table has a list of pointers to connectors. These nodes also store if the chosen connector is shallow.

      As with normal pruning, we make alternate left.right and right.left passes. In the R.L pass, when we're on a word w, we make use of all the left-pointing hash tables on the words to the right of w. After the pruning on this word, we build the left-pointing hash table this word. This guarantees idempotence of the pass -- after doing an L.R, doing another would change nothing.

      Each connector has an integer c_word field. This refers to the closest word that it could be connected to. These are initially determined by how deep the connector is. For example, a deepest connector can connect to the neighboring word, so its c_word field is w+1 (w-1 if this is a left pointing connector). It's neighboring shallow connector has a c_word value of w+2, etc.

      The pruning process adjusts these c_word values as it goes along, accumulating information about any way of linking this sentence. The pruning process stops only after no disjunct is deleted and no c_word values change.

      The difference between RUTHLESS and GENTLE power pruning is simply that GENTLE uses the deletable region array, and RUTHLESS does not. So we can get the effect of these two different methods simply by always unsuring that deletable[][] has been defined. With nothing deletable, this is equivalent to RUTHLESS. --DS, 7/97

    - #### clean_table

          public void clean_table(int size,
                         CList[] t)

      This runs through all the connectors in this table, and eliminates those who are obsolete. The word fields of an obsolete one has been set to BAD_WORD.

    - #### left_connector_list_update

          public int left_connector_list_update(Connector c,
                                       int word_c,
                                       int w,
                                       boolean shallow)

      take this connector list, and try to match it with the words w-1, w-2, w-3...Returns the word to which the first connector of the list could possibly be matched. If c is null, returns w. If there is no way to match this list, it returns a negative number. If it does find a way to match it, it updates the c.word fields correctly.

    - #### right_connector_list_update

          public int right_connector_list_update(Connector c,
                                        int word_c,
                                        int w,
                                        boolean shallow)

      take this connector list, and try to match it with the words w+1, w+2, w+3...Returns the word to which the first connector of the list could possibly be matched. If c is null, returns w. If there is no way to match this list, it returns a number greater than N_words-1 If it does find a way to match it, it updates the c.word fields correctly.

    - #### prune

          public void prune(ParseOptions opts)

    - #### set_dist_fields

          public int set_dist_fields(Connector c,
                            int w,
                            int delta)

    - #### possible_connection

          public boolean possible_connection(Connector lc,
                                    Connector rc,
                                    boolean lshallow,
                                    boolean rshallow,
                                    int lword,
                                    int rword)

      this takes two connectors (and whether these are shallow or not) (and the two words that these came from) and returns true if it is possible for these two to match based on local considerations.

    - #### right_table_search

          public boolean right_table_search(int w,
                                   Connector c,
                                   boolean shallow,
                                   int word_c)

    - #### left_table_search

          public boolean left_table_search(int w,
                                  Connector c,
                                  boolean shallow,
                                  int word_c)

    - #### init_power

          public void init_power()

      allocates and builds the initial power hash tables

    - #### left_connector_count

          public int left_connector_count(Disjunct d)

      returns the number of connectors in the left lists of the disjuncts.

    - #### right_connector_count

          public int right_connector_count(Disjunct d)

      returns the number of connectors in the right lists of the disjuncts.

    - #### power_hash

          public int power_hash(Connector c)

      This hash function only looks at the leading upper case letters of the connector string, and the label fields. This ensures that if two strings match (formally), then they must hash to the same place. The answer must be masked to the appropriate table size. This is exactly the same hash function used in fast-match.

    - #### put_into_power_table

          public void put_into_power_table(int size,
                                  CList[] t,
                                  Connector c,
                                  boolean shal)

      The disjunct d (whose left or right pointer points to c) is put into the appropriate hash table

    - #### init_cms_table

          public void init_cms_table()

    - #### cms_hash

          public int cms_hash(java.lang.String s)

    - #### match_in_cms_table

          public boolean match_in_cms_table(java.lang.String pp_match_name)

    - #### lookup_in_cms_table

          public Cms lookup_in_cms_table(java.lang.String str)

    - #### insert_in_cms_table

          public void insert_in_cms_table(java.lang.String str)

    - #### delete_from_cms_table

          public int delete_from_cms_table(java.lang.String str)

    - #### rule_satisfiable

          public boolean rule_satisfiable(PPLinkset ls)