home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / ausay / phoneme.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  6.4 KB  |  325 lines

  1. #include <stdio.h>
  2. #include <ctype.h>
  3.  
  4. #define FALSE (0)
  5. #define TRUE (!0)
  6.  
  7. /*
  8.  * *    English to Phoneme translation. *
  9.  * 
  10.  *    Rules are made up of four parts: *
  11.  * 
  12.  *        The left context. *        The text to match. *
  13.  * he right context. *        The phonemes to substitute for the matched
  14.  * text. *
  15.  * 
  16.  *    Procedure: *
  17.  * 
  18.  *        Seperate each block of letters (apostrophes included) *
  19.  * nd add a space on each side.  For each unmatched *        letter in the
  20.  * word, look through the rules where the *        text to match starts
  21.  * with the letter in the word.  If *        the text to match is found
  22.  * and the right and left *        context patterns also match, output
  23.  * the phonemes for *        that rule and skip to the next unmatched
  24.  * letter. *
  25.  * 
  26.  *
  27.  *    Special Context Symbols: *
  28.  * 
  29.  *        #    One or more vowels *        :    Zero or more
  30.  * consonants *        ^    One consonant. *        .    One
  31.  * of B, D, V, G, J, L, M, N, R, W or Z (voiced *
  32.  * ants) *        %    One of ER, E, ES, ED, ING, ELY (a suffix) *
  33.  * Right context only) *        +    One of E, I or Y (a "front"
  34.  * vowel)
  35.  */
  36.  
  37. typedef char   *Rule[4];    /* A rule is four character pointers */
  38.  
  39. extern Rule    *Rules[];    /* An array of pointers to rules */
  40.  
  41. int 
  42. isvowel(chr)
  43.     char            chr;
  44. {
  45.     return (chr == 'A' || chr == 'E' || chr == 'I' ||
  46.         chr == 'O' || chr == 'U');
  47. }
  48.  
  49. int 
  50. isconsonant(chr)
  51.     char            chr;
  52. {
  53.     return (isupper(chr) && !isvowel(chr));
  54. }
  55.  
  56. xlate_word(word)
  57.     char            word[];
  58. {
  59.     int             index;    /* Current position in word */
  60.     int             type;    /* First letter of match part */
  61.  
  62.     index = 1;        /* Skip the initial blank */
  63.     do
  64.     {
  65.         if (isupper(word[index]))
  66.             type = word[index] - 'A' + 1;
  67.         else
  68.             type = 0;
  69.  
  70.         index = find_rule(word, index, Rules[type]);
  71.     }
  72.     while (word[index] != '\0');
  73. }
  74.  
  75. find_rule(word, index, rules)
  76.     char            word[];
  77.     int             index;
  78.     Rule           *rules;
  79. {
  80.     Rule           *rule;
  81.     char           *left, *match, *right, *output;
  82.     int             remainder;
  83.  
  84.     for (;;)        /* Search for the rule */
  85.     {
  86.         rule = rules++;
  87.         match = (*rule)[1];
  88.  
  89.         if (match == 0)    /* bad symbol! */
  90.         {
  91.             fprintf(stderr,
  92.                 "Error: Can't find rule for: '%c' in \"%s\"\n", word[index], word);
  93.             return index + 1;    /* Skip it! */
  94.         }
  95.  
  96.         for (remainder = index; *match != '\0'; match++, remainder++)
  97.         {
  98.             if (*match != word[remainder])
  99.                 break;
  100.         }
  101.  
  102.         if (*match != '\0')    /* found missmatch */
  103.             continue;
  104.         /*
  105.          * printf("\nWord: \"%s\", Index:%4d, Trying: \"%s/%s/%s\" =
  106.          * \"%s\"\n", word, index, (*rule)[0], (*rule)[1],
  107.          * (*rule)[2], (*rule)[3]);
  108.          */
  109.         left = (*rule)[0];
  110.         right = (*rule)[2];
  111.  
  112.         if (!leftmatch(left, &word[index - 1]))
  113.             continue;
  114.         /*
  115.          * printf("leftmatch(\"%s\",\"...%c\") succeded!\n", left,
  116.          * word[index-1]);
  117.          */
  118.         if (!rightmatch(right, &word[remainder]))
  119.             continue;
  120.         /*
  121.          * printf("rightmatch(\"%s\",\"%s\") succeded!\n", right,
  122.          * &word[remainder]);
  123.          */
  124.         output = (*rule)[3];
  125.         /*
  126.          * printf("Success: ");
  127.          */
  128.         outstring(output);
  129.         return remainder;
  130.     }
  131. }
  132.  
  133.  
  134. leftmatch(pattern, context)
  135.     char           *pattern;/* first char of pattern to match in text */
  136.     char           *context;/* last char of text to be matched */
  137. {
  138.     char           *pat;
  139.     char           *text;
  140.     int             count;
  141.  
  142.     if (*pattern == '\0')    /* null string matches any context */
  143.     {
  144.         return TRUE;
  145.     }
  146.  
  147.     /* point to last character in pattern string */
  148.     count = strlen(pattern);
  149.     pat = pattern + (count - 1);
  150.  
  151.     text = context;
  152.  
  153.     for (; count > 0; pat--, count--)
  154.     {
  155.         /* First check for simple text or space */
  156.         if (isalpha(*pat) || *pat == '\'' || *pat == ' ')
  157.             if (*pat != *text)
  158.                 return FALSE;
  159.             else
  160.             {
  161.                 text--;
  162.                 continue;
  163.             }
  164.  
  165.         switch (*pat)
  166.         {
  167.         case '#':    /* One or more vowels */
  168.             if (!isvowel(*text))
  169.                 return FALSE;
  170.  
  171.             text--;
  172.  
  173.             while (isvowel(*text))
  174.                 text--;
  175.             break;
  176.  
  177.         case ':':    /* Zero or more consonants */
  178.             while (isconsonant(*text))
  179.                 text--;
  180.             break;
  181.  
  182.         case '^':    /* One consonant */
  183.             if (!isconsonant(*text))
  184.                 return FALSE;
  185.             text--;
  186.             break;
  187.  
  188.         case '.':    /* B, D, V, G, J, L, M, N, R, W, Z */
  189.             if (*text != 'B' && *text != 'D' && *text != 'V'
  190.                 && *text != 'G' && *text != 'J' && *text != 'L'
  191.                 && *text != 'M' && *text != 'N' && *text != 'R'
  192.                 && *text != 'W' && *text != 'Z')
  193.                 return FALSE;
  194.             text--;
  195.             break;
  196.  
  197.         case '+':    /* E, I or Y (front vowel) */
  198.             if (*text != 'E' && *text != 'I' && *text != 'Y')
  199.                 return FALSE;
  200.             text--;
  201.             break;
  202.  
  203.         case '%':
  204.         default:
  205.             fprintf(stderr, "Bad char in left rule: '%c'\n", *pat);
  206.             return FALSE;
  207.         }
  208.     }
  209.  
  210.     return TRUE;
  211. }
  212.  
  213.  
  214. rightmatch(pattern, context)
  215.     char           *pattern;/* first char of pattern to match in text */
  216.     char           *context;/* last char of text to be matched */
  217. {
  218.     char           *pat;
  219.     char           *text;
  220.  
  221.     if (*pattern == '\0')    /* null string matches any context */
  222.         return TRUE;
  223.  
  224.     pat = pattern;
  225.     text = context;
  226.  
  227.     for (pat = pattern; *pat != '\0'; pat++)
  228.     {
  229.         /* First check for simple text or space */
  230.         if (isalpha(*pat) || *pat == '\'' || *pat == ' ')
  231.             if (*pat != *text)
  232.                 return FALSE;
  233.             else
  234.             {
  235.                 text++;
  236.                 continue;
  237.             }
  238.  
  239.         switch (*pat)
  240.         {
  241.         case '#':    /* One or more vowels */
  242.             if (!isvowel(*text))
  243.                 return FALSE;
  244.  
  245.             text++;
  246.  
  247.             while (isvowel(*text))
  248.                 text++;
  249.             break;
  250.  
  251.         case ':':    /* Zero or more consonants */
  252.             while (isconsonant(*text))
  253.                 text++;
  254.             break;
  255.  
  256.         case '^':    /* One consonant */
  257.             if (!isconsonant(*text))
  258.                 return FALSE;
  259.             text++;
  260.             break;
  261.  
  262.         case '.':    /* B, D, V, G, J, L, M, N, R, W, Z */
  263.             if (*text != 'B' && *text != 'D' && *text != 'V'
  264.                 && *text != 'G' && *text != 'J' && *text != 'L'
  265.                 && *text != 'M' && *text != 'N' && *text != 'R'
  266.                 && *text != 'W' && *text != 'Z')
  267.                 return FALSE;
  268.             text++;
  269.             break;
  270.  
  271.         case '+':    /* E, I or Y (front vowel) */
  272.             if (*text != 'E' && *text != 'I' && *text != 'Y')
  273.                 return FALSE;
  274.             text++;
  275.             break;
  276.  
  277.         case '%':    /* ER, E, ES, ED, ING, ELY (a suffix) */
  278.             if (*text == 'E')
  279.             {
  280.                 text++;
  281.                 if (*text == 'L')
  282.                 {
  283.                     text++;
  284.                     if (*text == 'Y')
  285.                     {
  286.                         text++;
  287.                         break;
  288.                     }
  289.                     else
  290.                     {
  291.                         text--;    /* Don't gobble L */
  292.                         break;
  293.                     }
  294.                 }
  295.                 else if (*text == 'R' || *text == 'S'
  296.                      || *text == 'D')
  297.                     text++;
  298.                 break;
  299.             }
  300.             else if (*text == 'I')
  301.             {
  302.                 text++;
  303.                 if (*text == 'N')
  304.                 {
  305.                     text++;
  306.                     if (*text == 'G')
  307.                     {
  308.                         text++;
  309.                         break;
  310.                     }
  311.                 }
  312.                 return FALSE;
  313.             }
  314.             else
  315.                 return FALSE;
  316.  
  317.         default:
  318.             fprintf(stderr, "Bad char in right rule:'%c'\n", *pat);
  319.             return FALSE;
  320.         }
  321.     }
  322.  
  323.     return TRUE;
  324. }
  325.