Edinburgh Speech Tools  2.1-release
ling_example.cc
Go to the documentation of this file.
1 /*************************************************************************/
2 /* */
3 /* Centre for Speech Technology Research */
4 /* University of Edinburgh, UK */
5 /* Copyright (c) 1996 */
6 /* All Rights Reserved. */
7 /* */
8 /* Permission is hereby granted, free of charge, to use and distribute */
9 /* this software and its documentation without restriction, including */
10 /* without limitation the rights to use, copy, modify, merge, publish, */
11 /* distribute, sublicense, and/or sell copies of this work, and to */
12 /* permit persons to whom this work is furnished to do so, subject to */
13 /* the following conditions: */
14 /* 1. The code must retain the above copyright notice, this list of */
15 /* conditions and the following disclaimer. */
16 /* 2. Any modifications must be clearly marked as such. */
17 /* 3. Original authors' names are not deleted. */
18 /* 4. The authors' names are not used to endorse or promote products */
19 /* derived from this software without specific prior written */
20 /* permission. */
21 /* */
22 /* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */
23 /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
24 /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
25 /* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */
26 /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
27 /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
28 /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
29 /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
30 /* THIS SOFTWARE. */
31 /* */
32 /*************************************************************************/
33 
34 #include "EST_unix.h"
35 #include "EST_ling_class.h"
36 
37 using namespace std;
38 
39 
40 int main(void)
41 {
42 
43  /*Adding basic information to an EST_Item */
44 
45  //@ code
46  EST_Item p;
47 
48  p.set("POS", "Noun");
49  p.set("NAME", "example");
50  p.set("FOCUS", "+");
51  p.set("DURATION", 2.76);
52  p.set("STRESS", 2);
53 
54  //@ endcode
55 
56  /* Accessing basic information in an Item */
57 
58  //@ code
59  cout << "Part of speech for p is " << p.S("POS") << endl;
60  cout << "Duration for p is " << p.F("DURATION") << endl;
61  cout << "Stress value for p is " << p.I("STRESS") << endl;
62  //@ endcode
63 
64  /* A optional default value can be given if a result
65  * is always desired */
66 
67  //@ code
68  cout << "Part of speech for p is "
69  << p.S("POS") << endl;
70  cout << "Syntactic Category for p is "
71  << p.S("CAT", "Noun") << endl; // noerror
72  //@ endcode
73 
74  /* Nested feature structures in items */
75 
76  //@ code
77 
78  p.set("NAME", "d");
79  p.set("VOICE", "+");
80  p.set("CONTINUANT", "-");
81  p.set("SONORANT", "-");
82 
83  EST_Features f;
84  p.set("PLACE OF ARTICULATION", f); // copy in empty feature set here
85 
86  p.A("PLACE OF ARTICULATION").set("CORONAL", "+");
87  p.A("PLACE OF ARTICULATION").set("ANTERIOR", "+");
88  //@ endcode
89 
90  /* or by filling the values in an EST_Features object and
91  * copying it in:
92  */
93 
94  //@ code
95  EST_Features f2;
96 
97  f2.set("CORONAL", "+");
98  f2.set("ANTERIOR", "+");
99 
100  p.set("PLACE OF ARTICULATION", f2);
101  //@ endcode
102 
103 
104  /* Nested features can be accessed by multiple calls to the
105  * accessing commands:
106  */
107 
108  //@ code
109  cout << "Anterior value is: " << p.A("PLACE OF ARTICULATION").S("ANTERIOR");
110  cout << "Coronal value is: " << p.A("PLACE OF ARTICULATION").S("CORONAL");
111  //@ endcode
112 
113  //@ code
114  cout << "Anterior value is: " << p.S("PLACE OF ARTICULATION.ANTERIOR");
115  cout << "Coronal value is: " << p.S("PLACE OF ARTICULATION.CORONAL");
116  //@ endcode
117 
118 
119  //@ code
120 
121  p.set("PLACE OF ARTICULATION.CORONAL", "+");
122  p.set("PLACE OF ARTICULATION.ANTERIOR", "+");
123  //@ endcode
124 
125  /* this is the easiest and most commonly used method. */
126 
127 
128  /* Utility functions for items */
129 
130  //@ code
131  cout << "This is true: " << p.f_present("PLACE OF ARTICULATION");
132  cout << "This is false: " << p.f_present("MANNER");
133  //@ endcode
134 
135  /* An attribute can be removed by <function>f_remove</function> */
136 
137  //@ code
138  p.f_remove("PLACE OF ARTICULATION");
139  //@ endcode
140 
141 
142  /* Building a linear list relation */
143 
144  //@ code
145  EST_Relation phones;
146  EST_Item *a;
147 
148  a = phones.append();
149 
150  a->set("NAME", "f");
151  a->set("TYPE", "consonant");
152 
153  a = phones.append();
154 
155  a->set("NAME", "o");
156  a->set("TYPE", "vowel");
157 
158  a = phones.append();
159 
160  a->set("NAME", "r");
161  a->set("TYPE", "consonant");
162  //@ endcode
163 
164 
165  //@ code
166  a = new EST_Item;
167  a->set("NAME", "m");
168  a->set("TYPE", "consonant");
169 
170  phones.append(a);
171 
172  a = new EST_Item;
173  a->set("NAME", "ei");
174  a->set("TYPE", "vowel");
175  //@ endcode
176 
177  /* Items can be prepended in exactly the same way: */
178  //@ code
179 
180  a = phones.prepend();
181 
182  a->set("NAME", "n");
183  a->set("TYPE", "consonant");
184 
185  a = phones.prepend();
186 
187  a->set("NAME", "i");
188  a->set("TYPE", "vowel");
189 
190  //@ endcode
191 
192 
193  /* Iterating through a linear list relation */
194 
195  //@ code
196  EST_Item *s;
197 
198  for (s = phones.head(); s != 0; s = s->next())
199  cout << s->S("NAME") << endl;
200  //@ endcode
201 
202  //@ code
203 
204  for (s = phones.tail(); s != 0; s = s->prev())
205  cout << s->S("NAME") << endl;
206 
207  //@ endcode
208 
209  //@ code
210  for (s = phones.head(); s; s = s->next())
211  cout << s->S("NAME") << endl;
212  //@ endcode
213 
214 
215  /* Building a tree relation */
216  //@{
217 
218  //@ code
219  //@example prog01
221  EST_Item *r, *np, *vp, *n;
222 
223  r = tree.append();
224  r->set("CAT", "S");
225 
226  np = append_daughter(r);
227  np->set("CAT", "NP");
228 
229  n = append_daughter(np);
230  n->set("CAT", "PRO");
231 
232  n = append_daughter(n);
233  n->set("NAME", "John");
234 
235  vp = append_daughter(r);
236  vp->set("CAT", "VP");
237 
238  n = append_daughter(vp);
239  n->set("CAT", "VERB");
240  n = append_daughter(n);
241  n->set("NAME", "loves");
242 
243  np = append_daughter(vp);
244  np->set("CAT", "NP");
245 
246  n = append_daughter(np);
247  n->set("CAT", "DET");
248  n = append_daughter(n);
249  n->set("NAME", "the");
250 
251  n = append_daughter(np);
252  n->set("CAT", "NOUN");
253  n = append_daughter(n);
254  n->set("NAME", "woman");
255 
256  cout << tree;
257  //@ endcode
258 
259 
260  /* Iterating through a tree relation */
261 
262  //@ code
263  n = tree.head(); // initialise iteration variable to head of tree
264  while (n)
265  {
266  if (daughter1(n) != 0) // if daughter exists, make n its daughter
267  n = daughter1(n);
268  else if (n->next() != 0)//otherwise visit its sisters
269  n = n->next();
270  else // if no sisters are left, go back up the tree
271  { // until a sister to a parent is found
272  bool found=FALSE;
273  for (EST_Item *pp = parent(n); pp != 0; pp = parent(pp))
274  if (pp->next())
275  {
276  n = pp->next();
277  found=TRUE;
278  break;
279  }
280  if (!found)
281  {
282  n = 0;
283  break;
284  }
285  }
286  cout << *n;
287  }
288  //@ endcode
289 
290  /* A special set of iterators are available for traversal of the leaf
291  * (terminal) nodes of a tree:
292  */
293 
294  //@ code
295  //@ example prog02
296  //@ title Leaf iteration
297 
298  for (s = first_leaf(tree.head()); s != last_leaf(tree.head());
299  s = next_leaf(s))
300  cout << s->S("NAME") << endl;
301  //@ endcode
302 
303 
304  /* Building a multi-linear relation */
305 
306  /* Iterating through a multi-linear relation */
307 
308 /* Relations in Utterances */
309 
310  //@ code
311  EST_Utterance utt;
312 
313  utt.create_relation("Word");
314  utt.create_relation("Syntax");
315  //@ endcode
316 
317  /* EST_Relations can be accessed though the utterance object either
318  * directly or by use of a temporary EST_Relation pointer:
319  */
320 
321  //@ code
322  EST_Relation *word, *syntax;
323 
324  word = utt.relation("Word");
325  syntax = utt.relation("Syntax");
326  //@ endcode
327 
328  /* The contents of the relation can be filled by the methods described
329  * above.
330  */
331 
332 
333  /* Adding items into multiple relations */
334 
335  //@ code
336  //@example prog03
337  //@title adding existing items to a new relation
338  word = utt.relation("Word");
339  syntax = utt.relation("Syntax");
340 
341  for (s = first_leaf(syntax->head()); s != last_leaf(syntax->head());
342  s = next_leaf(s))
343  word->append(s);
344 
345  //@ endcode
346 
347  /*
348  * Thus the terminal nodes in the syntax relation are now stored as a
349  * linear list in the word relation.
350  *
351  * Hence
352  */
353 
354  //@ code
355  cout << *utt.relation("Syntax") << "\n";
356  //@ endcode
357 
358  //@ code
359  cout << *utt.relation("Word") << "\n";
360  //@ endcode
361 
362 
363  /*Changing the relation an item is in as_relation, in relation etc */
364 
365  /* Feature functions evaluate functions setting functions */
366 
367  exit(0);
368 
369 }
370 
371 
372 /** @page ling-example Example code for Linguistic Classes
373  @tableofcontents
374  @brief Some examples of usage of linguistic classes
375  @dontinclude ling_example.cc
376 
377  @section addingtoestitem Adding basic information to an EST_Item
378 
379  An item such as:
380 
381 \f[
382 \left [
383 \begin{array}{ll}
384 \mbox{POS} & \mbox{\emph{Noun}} \\
385 \mbox{NAME} & \mbox{\emph{example}} \\
386 \mbox{FOCUS} & \mbox{+} \\
387 \end{array} \right ]
388 \f]
389 
390  is constructed as follows: (note that
391  the attributes are in capitals by linguistic convention only:
392  attribute names are case sensitive and can be upper or lower case).
393 
394  @skipline //@ code
395  @until //@ endcode
396 
397  The type of the values in features is a EST_Val class,
398  which is a union which can
399  store ints, floats, EST_Strings, void pointers, and
400  EST_Features. The overloaded function
401  facility of C++ means that the EST_Item::set() can be
402  used for all of these.
403 
404 
405  @section accessingitem Accessing basic information in an Item
406 
407  When accessing the features, the type must be
408  specified. This is done most easily by using of a series of
409  functions whose type is coded by a capital letter:
410 
411  - EST_Item::F() : return value as a float.
412  - EST_Item::I() : return value as an integer.
413  - EST_Item::S() : return value as a string.
414  - EST_Item::A() : return value as a EST_Features
415 
416  @skipline //@ code
417  @until //@ endcode
418 
419  @verbatim
420  Output:
421  "Noun"
422  2.75
423  1
424  @endverbatim
425 
426  A optional default value can be given if a result is always desired
427 
428  @skipline //@ code
429  @until //@ endcode
430 
431  @section nestedfeatures Nested feature structures in items
432 
433  Nested feature structures such as
434 
435 \f[
436 \left [
437 \begin{array}{ll}
438 \mbox{NAME} & \mbox{\emph{d}} \\
439 \mbox{PLACE OF ARTICULATION \boxed{1} } &
440  \left [ \begin{array}{ll}
441  \mbox{CORONAL} & \mbox{\emph{+}} \\
442  \mbox{ANTERIOR} & \mbox{\emph{+}} \\
443  \end{array} \right ] \\
444 \mbox{VOICE} & \mbox{\emph{+}} \\
445 \mbox{CONTINUANT} & \mbox{\emph{--}} \\
446 \mbox{SONORANT} & \mbox{\emph{--}} \\
447 \end{array} \right ]
448 \f]
449 
450  can be created in a number of ways:
451 
452  @skipline //@ code
453  @until //@ endcode
454 
455  or by filling the values in an EST_Features object and
456  copying it in:
457 
458  @skipline //@ code
459  @until //@ endcode
460 
461 
462  Nested features can be accessed by multiple calls to the
463  accessing commands:
464 
465  @skipline //@ code
466  @until //@ endcode
467 
468  The first command is EST_Item::A() because PLACE is a
469  feature structure, and the second command is
470  EST_Item::S() because it returns a string (the
471  value or ANTERIOR or CORONAL). A shorthand is provided to
472  extract the value in a single statement:
473 
474  @skipline //@ code
475  @until //@ endcode
476 
477  Again, as the last value to be returned is a string
478  EST_Item::S() must be used. This shorthand can also be used
479  to set the features:
480 
481  @skipline //@ code
482  @until //@ endcode
483 
484  this is the easiest and most commonly used method.
485 
486  @section utilityfunctions Utility functions for items
487 
488  The presence of a attribute can be checked using
489  EST_Item::f_present(), which returns true if the
490  attribute is in the item:
491 
492  @skipline //@ code
493  @until //@ endcode
494 
495  An attribute can be removed by EST_Item::f_remove.
496 
497  @skipline //@ code
498  @until //@ endcode
499 
500  @section buildlinearlist Building a linear list relation
501  <!-- *** UPDATE *** -->
502 
503  It is standard to store the phones for an utterance as a linear list
504  in a EST_Relation object. Each phone is represented by one
505  EST_Item, whereas the complete list is stored as a
506  EST_Relation.
507 
508  The easiest way to build a linear list is by using the
509  EST_Relation::append(), which when called
510  without arguments, makes a new empty EST_Item, adds it onto
511  the end of the relation and returns a pointer to it. The
512  information relevant to that phone can then be added to the
513  returned item.
514 
515  @skipline //@ code
516  @until //@ endcode
517 
518  Note that the -> operator is used because the EST_Item a is a
519  pointer here. The same pointer variable can be used multiple
520  times because every time EST_Relation::append() is
521  called it allocates a new item and returns a pointer to it.
522 
523  If you already have a EST_Item pointer and want to add it to a
524  relation, you can give it as an argument to
525  EST_Relation::append(), but this is generally
526  inadvisable as it involves some unnecessary copying, and also
527  you have to allocate the memory for the next EST_Item pointer
528  yourself every time (if you don't you will overwrite the
529  previous one):
530 
531 
532  @skipline //@ code
533  @until //@ endcode
534 
535  Items can be prepended in exactly the same way:
536 
537  @skipline //@ code
538  @until //@ endcode
539 
540  @section iteratingrelation Iterating through a linear list relation
541 
542  Iteration in lists is performed with EST_Relation::next()
543  and EST_Relation::prev(), and an EST_Item,
544  used as an iteration pointer.
545 
546  @skipline //@ code
547  @until //@ endcode
548 
549  Output:
550  @verbatim
551  name:i type:vowel
552  name:n type:consonant
553  name:f type:consonant
554  name:o type:vowel
555  name:r type:consonant
556  name:m type:consonant
557  @endverbatim
558 
559  @skipline //@ code
560  @until //@ endcode
561 
562  Output:
563 
564  @verbatim
565  name:m type:consonant
566  name:r type:consonant
567  name:o type:vowel
568  name:f type:consonant
569  name:n type:consonant
570  name:i type:vowel
571  @endverbatim
572 
573  EST_Relation::head() and EST_Relation::tail() return EST_Item
574  pointers to the start and end of the list. EST_Relation::next()
575  and EST_Relation::prev() returns the next or previous item in the
576  list, and returns `0` when the end or start of the list is
577  reached. Hence checking for `0` is a useful termination condition
578  of the iteration. Taking advantage of C shorthand allows us to write:
579 
580  @skipline //@ code
581  @until //@ endcode
582 
583  @section buildtreerelation Building a tree relation
584 
585  <!-- *** UPDATE *** -->
586  It is standard to store information such as syntax as a tree
587  in a EST_Relation object. Each tree node is represented by one
588  EST_Item, whereas the complete tree is stored as a
589  EST_Relation.
590 
591  The easiest way to build a tree is by using the
592  EST_Relation::append_daughter(), which when called
593  without arguments, makes a new empty EST_Item, adds it as a
594  daughter to an existing item and returns a pointer to it. The
595  information relevant to that node can then be added to the
596  returned item. The root node of the tree must be added
597  directly to the EST_Relation.
598 
599  @anchor ling-example-example01
600  @skipline //@ code
601  @until //@ endcode
602 
603  Output:
604 
605  @verbatim
606 (S
607  (NP
608  (N (John))
609  )
610  (VP
611  (V (loves))
612  (NP
613  (DET the)
614  (NOUN woman))
615  )
616 )
617  @endverbatim
618 
619 
620  Obviously, the use of recursive functions in building trees is more
621  efficient and would eliminate the need for the large number of
622  temporary variables used in the above example.
623 
624  @section iteratingtreerelation Iterating through a tree relation
625 
626  Iteration in trees is done with EST_Relation::daughter1()
627  EST_Relation::daughter2() EST_Relation::daughtern() and
628  EST_Relation::parent(). Pre-order traversal can be achieved
629  iteratively as follows:
630 
631  @skipline //@ code
632  @until //@ endcode
633 
634  A special set of iterators are available for traversal of the leaf
635  (terminal) nodes of a tree:
636 
637  @skipline //@ code
638  @until //@ endcode
639 
640  @section buildmultilinear Building a multi-linear relation
641  This is not yet fully implemented?
642 
643  @section iteratingmultilinear Iterating through a multi-linear relation
644  This is not yet fully implemented?
645 
646  @section relationsinutt Relations in Utterances
647 
648  The EST_Utterance class is used to store all
649  the items and relations relevant to a single utterance. (Here
650  utterance is used as a general linguistic entity - it doesn't have to
651  relate to a well formed complete linguistic unit such as a sentence or
652  phrase).
653 
654  Instead of storing relations separately, they are stored in
655  utterances:
656 
657  @skipline //@ code
658  @until //@ endcode
659 
660  EST_Relations can be accessed though the utterance object either
661  directly or by use of a temporary EST_Relation pointer:
662 
663  @skipline //@ code
664  @until //@ endcode
665 
666  The contents of the relation can be filled by the methods described
667  above.
668 
669 
670  @section additemsmultiplerelations Adding items into multiple relations
671 
672  A major aspect of this system is that an item can be in two relations
673  at once, as shown in \ref estling-figure-6-2 "Figure 6-2".
674 
675  In the following example, using the syntax relation as already created
676  in \ref ling-example-example01 "prog01",
677  shows how to put the terminal nodes of this
678  tree into a word relation:
679 
680  @skipline //@ code
681  @until //@ endcode
682 
683  Thus the terminal nodes in the syntax relation are now stored as a
684  linear list in the word relation.
685 
686  Hence
687 
688  @skipline //@ code
689  @until //@ endcode
690 
691  produces
692 
693  Output:
694  @verbatim
695 (S
696  (NP
697  (N (John))
698  )
699  (VP
700  (V (loves))
701  (NP
702  (DET the)
703  (NOUN woman))
704  )
705 )
706  @endverbatim
707 
708  whereas
709 
710  @skipline //@ code
711  @until //@ endcode
712 
713  produces
714 
715  Output
716  @verbatim
717 John
718 loves
719 the
720 woman
721  @endverbatim
722 
723  @section changingrelationwithitem Changing the relation an item is in
724 
725  Even if an item is in more than one relation, it always has the
726  idea of a "current" relation. If the traversal functions
727  (next, previous, parent etc) are called, traversal always occurs
728  with respect to the current relation. An item's current relation
729  can be changed as follows:
730 
731  \code{.cpp}
732 s = utt.relation("Word")->head(); // set p to first word
733 s = next(s); // get next word: s = parent(s) would throw an error as there
734  // is no parent to s in the word relation.
735 s = prev(s); // get previous word
736 s = s->as_relation("Syntax"); // change relation.
737 s = parent(s); // get parent of s in syntax relation
738 s = daughter1(s); // get first daughter of s: s = next(s) would throw an
739  // error as there is no next to s in the syntax relation.
740  \endcode
741 
742  while s is still the same item, the current relation is now "Syntax".
743  The current relation is returned by the EST_Item::relation() function:
744  \code{.cpp}
745  cout << "Name of current relation: " << s->relation()->name() << endl;
746  \endcode
747 
748  If you aren't sure whether an item is in a relation, you can check
749  with EST_Item::in_relation(). This will return true if an item is in
750  the requested relation regardless of what the current relation is.
751  \code{.cpp}
752  cout << "P is in the syntax relation: " << s->in_relation("Word") << endl;
753  cout << "Relations: " << s->relations() << endl;
754  \endcode
755 
756  @section featurefunctions Feature functions
757 
758  evaluate functions
759 
760  setting functions
761 
762 */
EST_Item * head() const
Definition: EST_Relation.h:121
EST_Item * first_leaf(const EST_Item *n)
return the first leaf (terminal node) which is dominated by n. Note that this is different from daugh...
EST_Item * append_daughter(EST_Item *n, EST_Item *p=0)
Definition: EST_Item.cc:594
int I(const EST_String &name) const
Definition: EST_Item.h:155
EST_Item * tail() const
Definition: EST_Relation.h:127
EST_Relation * create_relation(const EST_String &relname)
create a new relation called n.
void set(const EST_String &name, ssize_t ival)
Definition: EST_Item.h:185
void set(const EST_String &name, int ival)
Definition: EST_Features.h:186
EST_Item * prepend(EST_Item *si)
const EST_String S(const EST_String &path) const
Definition: EST_Features.h:158
EST_Item * prev() const
Definition: EST_Item.h:350
float F(const EST_String &name) const
Definition: EST_Item.h:135
#define FALSE
Definition: EST_bool.h:119
int main(void)
Definition: ling_example.cc:40
f
Definition: EST_item_aux.cc:48
EST_Features & A(const EST_String &name) const
Definition: EST_Item.h:164
EST_Item * next() const
Definition: EST_Item.h:348
EST_Item * last_leaf(const EST_Item *n)
const EST_String S(const EST_String &name) const
Definition: EST_Item.h:144
EST_Relation * relation(const char *name, int err_on_not_found=1) const
get relation by name
EST_Item * append(EST_Item *si)
Definition: EST_Relation.cc:88
int tree
Definition: rxp.c:21
EST_Item * next_leaf(const EST_Item *n)
void f_remove(const EST_String &name)
Definition: EST_Item.h:228
#define TRUE
Definition: EST_bool.h:118
EST_Item * parent(const EST_Item *n)
return parent of n
EST_Item * daughter1(const EST_Item *n)
return first daughter of n
int f_present(const EST_String &name) const
Definition: EST_Item.h:236