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