home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_11_04 / 1104060a < prev    next >
Text File  |  1993-01-26  |  13KB  |  424 lines

  1. Listing 1 caption: A natural language processor<197><F105>NATURAL.C<F255D>
  2.  
  3.  
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <ctype.h>
  8.  
  9. #define  ING   73        /* Restriction for ING word */
  10.  
  11. void initialize(void);
  12. void reset_sentence(void);
  13. void get_record(char *);
  14. char *extract_word(void);
  15. int  match_record(char *, int);
  16. char *extract_root(void);
  17. void check_underlying(void);
  18. int  check_type(char *,int);
  19. void check_subject(void);
  20. void check_action(void);
  21. void check_place(void);
  22. void make_response(void);
  23. void make_answer(int);
  24. void get_verb_ing(void);
  25. int  match_verb_ing(void);
  26.  
  27. FILE *infile;
  28. char dic_record[80];
  29. int  sentence;
  30. int  word_ct;
  31. char word_array[10][15];
  32. char root_array[10][15];
  33. char prime_types[10][11];
  34. char phrases[10][11];
  35. char type_array[10][5][11];
  36. char subjects[20][15];
  37. char actions[20][15];
  38. char places[20][31];
  39. char response[80];
  40.  
  41.  
  42. void main()
  43. {
  44.     char  *cur_word;
  45.     char  in_sentence[80];
  46.  
  47.     initialize();
  48.     if ((infile = fopen("diction", "r+")) == NULL) {
  49.         printf ("\nError opening dictionary\n");
  50.         exit(0);
  51.     }
  52.     printf("\nSentence: ");
  53.  
  54.     while(gets(in_sentence)) {
  55.         if (in_sentence[0] == '\0') break;
  56.         reset_sentence();
  57.  
  58.         cur_word = strtok(in_sentence, " ");
  59.         while(cur_word != NULL) {
  60.             get_record(cur_word);
  61.             cur_word = strtok(NULL, " ");
  62.             if (++word_ct > 9) break;
  63.         }
  64.  
  65.         check_underlying();
  66.  
  67.         check_subject();
  68.         check_action();
  69.         check_place();
  70.  
  71.         make_response();
  72.         printf("Response: %s\n\nSentence: ", response);
  73.  
  74.         if (++sentence > 19) break;
  75.     }   /*  end while  */
  76.  
  77.     fclose(infile);
  78.     return;
  79. }
  80.  
  81. /*****************************************************/
  82. /* Initialize variables (subjects, actions and       */
  83. /* places arrays contain entries for 20 sentences).  */
  84. /*****************************************************/
  85. void initialize()
  86. {
  87.     int i;
  88.     for (i=0; i<20; i++) {
  89.         subjects[i][0]    = '\0';
  90.         actions[i][0]     = '\0';
  91.         places[i][0]      = '\0';
  92.     }
  93.     sentence              = 0;
  94.     return;
  95. }
  96.  
  97. /*****************************************************/
  98. /* These variables are initialized for each new      */
  99. /* input sentence (each of the 10 word entries for   */
  100. /* the input sentence has 5 type_array entries).     */
  101. /*****************************************************/
  102. void reset_sentence()
  103. {
  104.     int i,j;
  105.     word_ct                     = 0;
  106.     for (i=0; i<10; i++) {
  107.         word_array[i][0]        = '\0';
  108.         root_array[i][0]        = '\0';
  109.         prime_types[i][0]       = '\0';
  110.         phrases[i][0]           = '\0';
  111.         for (j=0; j<5; j++)
  112.             type_array[i][j][0] = '\0';
  113.     }
  114.     return;
  115. }
  116.  
  117. /*****************************************************/
  118. /* Get all the records from the dictionary. If the   */
  119. /* passed word is not in the dictionary, then the    */
  120. /* word could be a name.                             */
  121. /*****************************************************/
  122. void get_record(char *pass_word)
  123. {
  124.     int types = 0;
  125.     rewind (infile);
  126.     fgets(dic_record, 80, infile);
  127.     while (! feof(infile)) {
  128.         if (match_record(pass_word, types) == 0)
  129.             types++;
  130.         fgets(dic_record, 80, infile);
  131.     }
  132.     if (types == 0) {
  133.         if (isupper( (int) pass_word[0]))
  134.             strcpy(type_array[word_ct][types], "NAME");
  135.         else
  136.             strcpy(type_array[word_ct][types],
  137.                    "NOTFOUND");
  138.     }
  139.     strcpy(word_array[word_ct], pass_word);
  140.     return;
  141. }
  142.  
  143. /*****************************************************/
  144. /* Compare the passed word with the word in the      */
  145. /* current dictionary record. If they are the same,  */
  146. /* then extract the type (NOUN, VERB, etc.). If the  */
  147. /* type is a VERB, then also extract the root and    */
  148. /* and copy it to the root array.                    */
  149. /*****************************************************/
  150. int  match_record(char *pass_word, int types)
  151. {
  152.     int i, j;
  153.     char *root;
  154.     char *dic_word;
  155.     dic_word = extract_word();
  156.     /* Check if passed word equals dictionary word   */
  157.     if (strcmpi(pass_word, dic_word) != 0) return(1);
  158.  
  159.     /* Word found, get the type                      */
  160.     for (i=14,j=0; i<20; i++) {
  161.        if (isspace(dic_record[i])) break;
  162.        type_array[word_ct][types][j++] = dic_record[i];
  163.     }
  164.     /* Trim the type                                 */
  165.     type_array[word_ct][types][j] = '\0';
  166.  
  167.     if (strcmp(type_array[word_ct][types],
  168.                 "VERB") == 0) {
  169.         root = extract_root();
  170.         strcpy(root_array[word_ct], root);
  171.     }
  172.  
  173.     return(0);
  174. }
  175.  
  176. /*****************************************************/
  177. /* Extract the word from the dictionary. The word is */
  178. /* 14 characters in length and starts in column 1.   */
  179. /*****************************************************/
  180. char *extract_word()
  181. {
  182.     int i, j;
  183.     char dic_word[15];
  184.     for (i=0,j=0; i<14; i++) {
  185.         if (isspace(dic_record[i])) break;
  186.         dic_word[j++] = dic_record[i];
  187.     }
  188.     /* Trim the dictionary word                      */
  189.     dic_word[j] = '\0';
  190.     return(dic_word);
  191. }
  192.  
  193. /*****************************************************/
  194. /* Extract the root from the dictionary. It          */
  195. /* identifies a group of similar words (the root for */
  196. /* run, ran, runs and running is run). It is 14      */
  197. /* characters in length and starts in column 35.     */
  198. /*****************************************************/
  199. char *extract_root()
  200. {
  201.     int i, j;
  202.     char root[15];
  203.     for (i=34,j=0; i<48; i++) {
  204.         if (isspace(dic_record[i])) break;
  205.         root[j++] = dic_record[i];
  206.     }
  207.     /* Trim the root                                 */
  208.     root[j] = '\0';
  209.     return(root);
  210. }
  211.  
  212. /*****************************************************/
  213. /* Determine if the input sentence contains a known, */
  214. /* underlying structure. If it does, then assign the */
  215. /* correct types and phrases for the words.          */
  216. /*****************************************************/
  217. void check_underlying()
  218. {
  219.     int i;
  220.  
  221.     /* Structure WH-AUX-NAME-VERB                    */
  222.     i = 0;
  223.     if ( (check_type("WH",     i) == 0) &&
  224.          (check_type("AUX",  i+1) == 0) &&
  225.          (check_type("NAME", i+2) == 0) &&
  226.          (check_type("VERB", i+3) == 0) ) {
  227.         strcpy(prime_types[i],   "WH");
  228.         strcpy(prime_types[i+1], "AUX");
  229.         strcpy(prime_types[i+2], "NAME");
  230.         strcpy(prime_types[i+3], "VERB");
  231.         strcpy(phrases[i],   "WHQUESTION");
  232.         strcpy(phrases[i+1], "VERBPHRASE");
  233.         strcpy(phrases[i+2], "NOUNPHRASE");
  234.         strcpy(phrases[i+3], "VERBPHRASE");
  235.         return;
  236.     }
  237.  
  238.     /* Structure NAME-AUX-VERB-PREP-DET-NOUN         */
  239.     if ( (check_type("NAME",   i) == 0) &&
  240.          (check_type("AUX",  i+1) == 0) &&
  241.          (check_type("VERB", i+2) == 0) &&
  242.          (check_type("PREP", i+3) == 0) &&
  243.          (check_type("DET",  i+4) == 0) &&
  244.          (check_type("NOUN", i+5) == 0) ) {
  245.         strcpy(prime_types[i],   "NAME");
  246.         strcpy(prime_types[i+1], "AUX");
  247.         strcpy(prime_types[i+2], "VERB");
  248.         strcpy(prime_types[i+3], "PREP");
  249.         strcpy(prime_types[i+4], "DET");
  250.         strcpy(prime_types[i+5], "NOUN");
  251.         strcpy(phrases[i],   "NOUNPHRASE");
  252.         strcpy(phrases[i+1], "VERBPHRASE");
  253.         strcpy(phrases[i+2], "VERBPHRASE");
  254.         strcpy(phrases[i+3], "PREPPHRASE");
  255.         strcpy(phrases[i+4], "PREPPHRASE");
  256.         strcpy(phrases[i+5], "PREPPHRASE");
  257.         return;
  258.     }
  259.  
  260.     return;
  261. }
  262.  
  263. /*****************************************************/
  264. /* Compare the passed type with all the types for    */
  265. /* this word in the type_array. If the type is       */
  266. /* found, then return 0. The pass_number parameter   */
  267. /* identifies the word in the input sentence.        */
  268. /*****************************************************/
  269. int check_type(char *pass_type, int pass_number)
  270. {
  271.     int i;
  272.     for (i=0; type_array[pass_number][i][0]; i++) {
  273.         if (strcmp(type_array[pass_number][i],
  274.                     pass_type) == 0)
  275.             /*  Passed type is found in array        */
  276.             return(0);
  277.     }
  278.     /*  Passed type is not found in array            */
  279.     return(1);
  280. }
  281.  
  282. /*****************************************************/
  283. /* If the correct type is "NAME", then the word      */
  284. /* refers to a subject so copy the word to the       */
  285. /* subjects array.                                   */
  286. /*****************************************************/
  287. void check_subject()
  288. {
  289.     int i;
  290.     for (i=0; i<word_ct; i++) {
  291.         if (strcmp(prime_types[i], "NAME") == 0) {
  292.             strcpy(subjects[sentence], word_array[i]);
  293.             break;
  294.         }
  295.     }
  296.     return;
  297. }
  298.  
  299. /*****************************************************/
  300. /* If the correct type is "VERB", then the word      */
  301. /* refers to an action so copy the word's root from  */
  302. /* the root array to the actions array.              */
  303. /*****************************************************/
  304. void check_action()
  305. {
  306.     int i;
  307.     for (i=0; i<word_ct; i++) {
  308.         if (strcmp(prime_types[i], "VERB") == 0) {
  309.             strcpy(actions[sentence], root_array[i]);
  310.             break;
  311.         }
  312.     }
  313.     return;
  314. }
  315.  
  316. /*****************************************************/
  317. /* If the phrase is a "PREPPHRASE", then all the     */
  318. /* words in the phrase refer to a place. Concatenate */
  319. /* these words to the places array.                  */
  320. /*****************************************************/
  321. void check_place()
  322. {
  323.     int i;
  324.     for (i=0; i<word_ct; i++) {
  325.         if (strcmp(phrases[i], "PREPPHRASE") == 0) {
  326.             strcat(places[sentence], " ");
  327.             strcat(places[sentence], word_array[i]);
  328.         }
  329.     }
  330.     return;
  331. }
  332.  
  333. /*****************************************************/
  334. /* Determine the kind of response to generate. If    */
  335. /* the input sentence is a where-question and the    */
  336. /* subject and action is found in a previous array   */
  337. /* entry, then the response can state the location   */
  338. /* of where the subject and action occured.          */
  339. /*****************************************************/
  340. void make_response()
  341. {
  342.     int i;
  343.  
  344.     /* Last input sentence is not a where-question   */
  345.     if (strcmpi(word_array[0],"where") != 0) {
  346.         strcpy(response, "Ok");
  347.         return;
  348.     }
  349.  
  350.     /* Last input sentence is a where-question       */
  351.     for (i=sentence-1; i >= 0; i--) {
  352.         if ( (strcmp(subjects[i],
  353.                       subjects[sentence]) == 0) &&
  354.              (strcmp(actions[i],
  355.                       actions[sentence])  == 0) &&
  356.              (strlen(places[i])           != 0) ) {
  357.             make_answer(i);
  358.             return;
  359.         }
  360.     }
  361.  
  362.     /* Not enough information in actions and         */
  363.     /* subjects arrays.                              */
  364.     strcpy(response, "I don't know");
  365.     return;
  366. }
  367.  
  368. /*****************************************************/
  369. /* Generate a response that states the location of   */
  370. /* where the subject and action occured.             */
  371. /*****************************************************/
  372. void make_answer(int prev_sentence)
  373. {
  374.     strcpy(response, subjects[prev_sentence]);
  375.     strcat(response, " ");
  376.     strcat(response, "was ");
  377.     get_verb_ing();
  378.     strcat(response, places[prev_sentence]);
  379.     return;
  380. }
  381.  
  382. /*****************************************************/
  383. /* Retrieve the ING version of the word from the     */
  384. /* dictionary (the ING version of run is running).   */
  385. /*****************************************************/
  386. void get_verb_ing()
  387. {
  388.     rewind (infile);
  389.     fgets(dic_record, 80, infile);
  390.     while (! feof(infile)) {
  391.         if (match_verb_ing() == 0) break;
  392.         fgets(dic_record, 80, infile);
  393.     }
  394.     return;
  395. }
  396.  
  397. /*****************************************************/
  398. /* If the root in the current dictionary record      */
  399. /* matches the root in the actions array, and the    */
  400. /* current dictionary record has an ING restriction, */
  401. /* then extract the dictionary word and return 0.    */
  402. /*****************************************************/
  403. int  match_verb_ing()
  404. {
  405.     int i;
  406.     char *root;
  407.     char *dic_word;
  408.  
  409.     root = extract_root();
  410.     if (strcmp(actions[sentence],root) == 0) {
  411.         /* Root found, look for ING restriction      */
  412.         for (i=24; i<33; i++) {
  413.             if (isspace(dic_record[i])) break;
  414.             if (dic_record[i] == ING) {
  415.                 dic_word = extract_word();
  416.                 strcat(response, dic_word);
  417.                 return(0);
  418.             }
  419.         }
  420.     }
  421.     return(1);
  422. }
  423.  
  424.