File Coverage

blib/lib/Lingua/tlhInganHol/yIghun.pm
Criterion Covered Total %
statement 157 374 41.9
branch 47 218 21.5
condition 27 94 28.7
subroutine 34 73 46.5
pod 1 68 1.4
total 266 827 32.1


line stmt bran cond sub pod time code
1             package Lingua::tlhInganHol::yIghun;
2              
3 2     2   25003 use strict;
  2         4  
  2         77  
4 2     2   12 use warnings;
  2         3  
  2         71  
5              
6 2     2   13 use Carp;
  2         5  
  2         180  
7 2     2   2226 use Filter::Simple;
  2         82275  
  2         17  
8              
9             our $VERSION = '20090601';
10             my $DEBUG;
11             my $HONOURABLE = 1;
12              
13             $DB::single=1;
14              
15             my %numword = ( 0 => q{pagh},
16             1 => q{wa'},
17             2 => q{cha'},
18             3 => q{wej},
19             4 => q{loS},
20             5 => q{vagh},
21             6 => q{jav},
22             7 => q{Soch},
23             8 => q{chorgh},
24             9 => q{Hut},
25             10 => q{maH},
26             100 => q{vatlh},
27             1000 => q{SaD},
28             10000 => q{netlh},
29             100000 => q{bIp},
30             1000000 => q{'uy'},
31             );
32              
33             my %val = reverse %numword;
34              
35             my $numword = '(?='. join('|',values %numword) . ')';
36             $numword{unit} = '(?:'. join('|',@numword{0..9}) . ')';
37              
38             my $number = qr{ $numword
39             (?:($numword{unit})($numword{+1000000}))? [ ]*
40             (?:($numword{unit})($numword{+100000}))? [ ]*
41             (?:($numword{unit})($numword{+10000}))? [ ]*
42             (?:($numword{unit})($numword{+1000}))? [ ]*
43             (?:($numword{unit})($numword{+100}))? [ ]*
44             (?:($numword{unit})($numword{+10}))? [ ]*
45             (?:($numword{unit}?) (?!$numword))? [ ]*
46             ( DoD [ ]* (?:$numword{unit} [ ]+)+ )?
47             }xi;
48              
49             sub to_Terran
50             {
51 28 50   28 0 74 return "" unless $_[0];
52 28 50       473 my @bits = $_[0] =~ $number or return;
53 28 50 33     134 my @decimals = split /\s+/, ($bits[-1] && $bits[-1] =~ s/^DoD\s*// ? pop @bits : 'pagh');
54 28         47 my ($value,$unit,$order) = 0;
55 28   50     1772 $value += $val{$unit||$order&&"wa'"||"pagh"} * $val{$order||"wa'"}
      66        
      50        
      100        
56             while ($unit, $order) = splice @bits, 0, 2;
57 28         34 $order = 0.1;
58 28         43 foreach $unit (@decimals) {
59 28         47 $value += $val{$unit} * $order;
60 28         61 $order /= 10;
61             }
62 28         96 return $value;
63             }
64              
65             sub from_Terran
66             {
67 0     0 0 0 my ($number, $decimal) = split /[.]/, $_[0];
68 0 0       0 my @decimals = $decimal ? split(//, $decimal) : ();
69 0         0 my @bits = split //, $number;
70 0 0       0 return $numword{0} unless grep $_, @bits;
71 0         0 my $order = 1;
72 0         0 my @numwords;
73             my $last;
74 0         0 for (reverse @bits) {
75 0 0       0 next unless $_;
76 0         0 push @numwords, $numword{$_};
77 0 0       0 $numwords[-1] .= $numword{$order} if $order > 1;
78             }
79 0         0 continue { $order *= 10 }
80 0         0 @decimals = map($numword{$_}, @decimals);
81 0 0       0 unshift @decimals, 'DoD' if @decimals;
82 0         0 return join " ", reverse(@numwords), @decimals;
83             }
84              
85             sub print_honourably {
86 0 0   0 0 0 my $handle = ref($_[0]) eq 'GLOB' ? shift : undef;
87 0 0       0 @_ = $_ unless @_;
88 0 0       0 my $output = join "", map {defined($_) ? $_ : ""} @_;
  0         0  
89             # $output =~ s{(\d+)[.](\d+)}
90             # {from_Terran($1).' DoD '.map {from_Terran($_)} split '',$2}e;
91 0         0 $output =~ s{(\d+(.\d+)?)}{from_Terran($1)}e;
  0         0  
92 0 0       0 if ($handle) { print {$handle} $output }
  0         0  
  0         0  
93 0         0 else { print $output }
94             }
95              
96             sub readline_honourably {
97 0 0   0 0 0 my $handle = ref($_[0]) eq 'GLOB' ? shift : undef;
98 0         0 my $input;
99 0 0       0 if ($handle) { $input = readline $handle }
  0         0  
100 0         0 else { $input = readline }
101 0 0       0 return unless defined $input;
102 0         0 $input =~ s{($number)\s*DoD((\s*$number)+)}
  0         0  
103             {to_Terran($1) . '.' .
104 0         0 map {to_Terran($_)} grep /\S/, split /($number)/,$2}e;
105 0         0 $input =~ s{($number)}{to_Terran($1)}e;
  0         0  
106 0         0 return $input;
107             }
108              
109             my $EOW = qr/(?![a-zA-Z'])/;
110              
111             sub enqr {
112 50     50 0 154 my $pattern = join '|', @_;
113 50         2463 return qr/((?:$pattern)$EOW)/;
114             }
115              
116             sub inqr {
117 10     10 0 25 my $pattern = join '|', @_;
118 10         359 return qr/($pattern)/;
119             }
120              
121             my %n_decl = qw(
122             yoS package
123             );
124             my $n_decl = enqr keys %n_decl;
125             sub to_decl {
126 0     0 0 0 my ($name, $cmd) = @_;
127 0         0 return "$cmd->{trans} $name->{trans}";
128             }
129              
130             my %sub_decl = qw(
131             nab sub
132             );
133             my $sub_decl = enqr keys %sub_decl;
134             sub to_sub_decl {
135 0     0 0 0 my ($block, $name, $cmd) = @_;
136 0 0       0 return "$cmd->{trans} $name->{trans}" unless $block->{trans};
137 0 0       0 return "$cmd->{trans} $block->{trans}" unless $name->{trans};
138 0         0 return "$cmd->{trans} $name->{trans} $block->{trans}";
139             }
140              
141             my %v_usage = qw(
142             lo' use
143             lo'Qo' no
144             );
145             my $v_usage = enqr keys %v_usage;
146             sub to_usage {
147 2     2 0 5 my ($name, $cmd) = @_;
148 2         9 return "$cmd->{trans} $name->{trans}";
149             }
150              
151             my %v_go = qw(
152             jaH goto
153             yInargh last
154             yItaH next
155             yInIDqa' redo
156             );
157             my $v_go = enqr keys %v_go;
158             sub to_go {
159 0     0 0 0 my ($name, $cmd) = @_;
160 0   0     0 $name||={trans=>""};
161 0         0 return "$cmd->{trans} $name->{trans}";
162             }
163              
164             my %v_listop = qw(
165             mISHa' sort
166             wIv grep
167             choH map
168             );
169             my $v_listop = enqr keys %v_listop;
170             sub to_listop {
171 1     1 0 3 my ($block, @list) = @_;
172 1         3 my $op = pop @list;
173 1         10 return join " ", map("$_->{trans} ", $op, $block),
174             join ",", map $_->{trans}, @list;
175             }
176              
177              
178             my %v_blockop = qw(
179             chov eval
180             vang do
181             );
182             my $v_blockop = enqr keys %v_blockop;
183             sub to_blockop {
184 0     0 0 0 my ($block, $op) = @_;
185 0         0 return "$op->{trans} $block->{trans}";
186             }
187              
188             my %v_match = qw(
189             ghov m
190             );
191             my $v_match = enqr keys %v_match;
192             sub to_match {
193 0     0 0 0 my ($expr, $pattern, $op) = @_;
194 0         0 $pattern->{trans} =~ s/^qq?<|>$//g;
195 0         0 return "$expr->{trans} =~ $op->{trans}<$pattern->{trans}>";
196             }
197              
198             my %v_change = qw(
199             tam s
200             mugh tr
201             );
202             my $v_change = enqr keys %v_change;
203             sub to_change {
204 0     0 0 0 my ($expr, $becomes, $pattern, $op) = @_;
205 0         0 $pattern->{trans} =~ s/^qq?<|>$//g;
206 0         0 $becomes->{trans} =~ s/^qq?<|>$//g;
207 0         0 return "$expr->{trans} =~ $op->{trans}<$pattern->{trans}><$becomes->{trans}>";
208             }
209              
210             my %v_arg0 = qw (
211             laD readline
212             chaqpoDmoH chomp
213             poDmoH chop
214             HaD study
215             chImmoH undef
216             Say'moH reset
217             mIS rand
218             juv length
219             toq'a' defined
220             rIn'a' eof
221             ghomneH wantarray
222             mej exit
223             Hegh die
224             ghuHmoH warn
225             pa'Hegh Carp::croak
226             pa'ghuHmoH Carp::carp
227             pongwI' caller
228             buv ref
229             Del stat
230             ghum alarm
231             mol dump
232             bogh fork
233             Qong sleep
234             loS wait
235             mach lc
236             wa'Dichmach lcfirst
237             tIn uc
238             wa'DichtIn ucfirst
239             nargh quotemeta
240             );
241             my $v_arg0 = enqr keys %v_arg0;
242              
243             my %v_arg1 = qw (
244             tlhoch not
245             noD reverse
246             HaD study
247             ja' tell
248             Such each
249             lI'a' exists
250             pong keys
251             'ar abs
252             joqtaH sin
253             joqtaHHa' cos
254             poD int
255             maHghurtaH log
256             lo'Sar sqrt
257             mIS rand
258             mIScher srand
259             mach lc
260             wa'Dichmach lcfirst
261             tIn uc
262             wa'DichtIn ucfirst
263             nargh quotemeta
264             juv length
265             sIj split
266             toq'a' defined
267             mob scalar
268             lo'laH values
269             rIn'a' eof
270             chov eval
271             mej exit
272             Hegh die
273             ghuHmoH warn
274             pa'Hegh Carp::croak
275             pa'ghuHmoH Carp::carp
276             pongwI' caller
277             buv ref
278             bagh'a' tied
279             poQ require
280             ghomchoH chdir
281             Sach glob
282             teq unlink
283             ghomtagh mkdir
284             ghomteq rmdir
285             Del stat
286             ghum alarm
287             mol dump
288             tagh exec
289             Qong sleep
290             ra' system
291             loS wait
292             ghomneH wantarray
293             );
294             my $v_arg1 = enqr keys %v_arg1;
295             sub to_arg1 {
296 0     0 0 0 my ($arg, $func) = @_;
297 0   0     0 $arg ||= {trans=>""}; # handle optional args
298 0 0       0 return $arg->{trans}."->$func->{trans}()" if $arg->{object};
299 0         0 return $func->{trans}."($arg->{trans})";
300             }
301              
302             my %v_arg1_da = qw (
303             poS open
304             laD readline
305             bot flock
306             nup truncate
307             chaqpoDmoH chomp
308             poDmoH chop
309             chImmoH undef
310             Say'moH reset
311             woD pop
312             nIH shift
313             SoQmoH close
314             Qaw' delete
315             baghHa' untie
316             );
317             my $v_arg1_da = enqr keys %v_arg1_da;
318             sub to_arg1_da {
319 1     1 0 3 my ($arg, $func) = @_;
320 1   50     3 $arg ||= {trans=>""}; # handle optional args
321 1 50       4 return $arg->{trans}."->$func->{trans}()" if $arg->{object};
322 1 50       4 return "$func->{trans} $arg->{trans}" if $arg->{type} =~ /handle$/;
323 1         5 return $func->{trans}."($arg->{trans})";
324             }
325              
326             my %v_arg2 = qw (
327             qojHa' atan2
328             So' crypt
329             boSHa' unpack
330             Sam index
331             naw'choH chmod
332             pIn'a'choH chown
333             rar link
334             neq rename
335             );
336             my $v_arg2 = enqr keys %v_arg2;
337             sub to_arg2 {
338 0     0 0 0 my ($arg1, $arg2, $func) = @_;
339 0 0       0 return $arg1->{trans}."->$func->{trans}($arg2->{trans})"
340             if $arg1->{object};
341 0         0 return "$func->{trans}($arg1->{trans}, $arg2->{trans})";
342             }
343              
344             # my %v_arg2_i = qw (
345             # );
346             # my $v_arg2_i = enqr keys %v_arg2_i;
347             ## sub to_arg2_i {
348             # my ($arg1, $arg2, $func) = @_;
349             # return "$arg1->{trans} $func->{trans} $arg2->{trans}";
350             # }
351              
352             my %v_arg2_da = qw (
353             DoQ bless
354             bot flock
355             );
356             my $v_arg2_da = enqr keys %v_arg2_da;
357             sub to_arg2_da {
358 0     0 0 0 my ($arg1, $arg2, $func) = @_;
359 0 0       0 return $arg1->{trans}."->$func->{trans}($arg2->{trans})"
360             if $arg1->{object};
361 0 0       0 return "$func->{trans} $arg1->{trans} ($arg2->{trans})"
362             if $arg1->{type} =~ /handle$/;
363 0         0 return "$func->{trans}($arg1->{trans}, $arg2->{trans})";
364             }
365              
366             my %v_arg2_a = qw (
367             DIch [...]
368             DIchvo' [...]
369             DIchvaD [...]
370             Suq {...}
371             Suqvo' {...}
372             SuqvaD {...}
373             );
374             my $v_arg2_a = enqr keys %v_arg2_a;
375             sub to_arg2_a {
376 0     0 0 0 my ($arg1, $arg2, $func) = @_;
377 0         0 $arg1->{trans} =~ s/^(\$.*)/$1\->/;
378 0         0 $arg1->{trans} =~ s/^([%@])/\$/;
379 0 0 0     0 die "<> yIlo'Qo' <> yIlo' jay'" # Not "Suq"! "DIch"!
380             if substr($func->{raw},0,3) eq 'Suq' && $1 eq '@';
381 0 0 0     0 die "<> yIlo'Qo' <> yIlo' jay'" # Not "DIch"! "Suq"!
382             if substr($func->{raw},0,3) eq 'DIch' && $1 eq '%';
383 0         0 $func->{trans} =~ s/\Q.../$arg2->{trans}/;
384              
385 0         0 return "$arg1->{trans}$func->{trans}";
386             }
387              
388             my %v_args = qw (
389             noD reverse
390             boS pack
391             sIj split
392             muv join
393             tatlh return
394             Hegh die
395             ghuHmoH warn
396             pa'Hegh Carp::croak
397             pa'ghuHmoH Carp::carp
398             tagh exec
399             HoH kill
400             muH kill
401             chot kill
402             bach kill
403             Hiv kill
404             DIS kill
405             jey kill
406             );
407             my $v_args = enqr keys %v_args;
408             sub to_args {
409 0     0 0 0 my $func = pop @_;
410 0         0 my $arg1 = shift @_;
411 0         0 my $args = join(",",map $_->{trans}, @_);
412 0 0       0 return $arg1->{trans}."->$func->{trans}($args)"
413             if $arg1->{object};
414 0 0       0 $args = ",$args" if $args;
415 0         0 return "$func->{trans}($arg1->{trans}$args)";
416             }
417              
418             sub to_args_u {
419 3     3 0 7 my $func = pop @_;
420 3         6 my $arg1 = shift @_;
421 3         51 my $args = join(",",map $_->{trans}, @_);
422 3 50 33     24 return $arg1->{trans}."->$func->{trans}($args)"
423             if $arg1 && $arg1->{object};
424 3 100       12 $args = ",$args" if $args;
425 3 50       19 return "$func->{trans}($arg1->{trans}$args)" if $arg1;
426 0         0 return "$func->{trans}()";
427             }
428              
429             sub to_args_ur {
430 0     0 0 0 my $func = pop @_;
431 0         0 my $arg1 = shift @_;
432 0         0 my $args = join(",",map $_->{trans}, @_);
433 0 0 0     0 return $arg1->{trans}."->$func->{trans}($args)"
434             if $arg1 && $arg1->{object};
435 0 0       0 $args = ",$args" if $args;
436 0 0       0 return "$func->{trans}->($arg1->{trans}$args)" if $arg1;
437 0         0 return "$func->{trans}->()";
438             }
439              
440             my %v_args_da = qw (
441             ghItlh print
442             lagh substr
443             yuv push
444             DuQ splice
445             poS open
446             nej seek
447             bagh tie
448             jegh unshift
449             );
450             my $v_args_da = enqr keys %v_args_da;
451             sub to_args_da {
452 1     1 0 3 my $func = pop @_;
453 1         2 my $arg1 = shift @_;
454 1   33     4 $arg1 ||= tok("","","");
455 1         4 my $args = join(",",map $_->{trans}, @_);
456 1 50       5 return $arg1->{trans}."->$func->{trans}($args)"
457             if $arg1->{object};
458 1 50       7 return "$func->{trans} $arg1->{trans} ($args)"
459             if $arg1->{type} =~ /handle$/;
460 1 50       4 $args = ",$args" if $args;
461 1         5 return "$func->{trans}($arg1->{trans}$args)";
462             }
463              
464             my %v_unop = qw (
465             HUH -
466             );
467             my $v_unop = enqr keys %v_unop;
468             sub to_unop {
469 0     0 0 0 my ($arg, $op) = @_;
470 0         0 return "$op->{trans}$arg->{trans}";
471             }
472              
473             my %v_unop_dpre = qw (
474             ghur ++
475             nup --
476             );
477             my $v_unop_dpre = enqr keys %v_unop_dpre;
478             sub to_unop_dpre {
479 0     0 0 0 my ($arg, $op) = @_;
480 0         0 return "$op->{trans}$arg->{trans}";
481             }
482              
483             my %v_unop_dpost = qw (
484             ghurQav ++
485             nupQav --
486             );
487             my $v_unop_dpost = enqr keys %v_unop_dpost;
488             sub to_unop_dpost {
489 0     0 0 0 my ($arg, $op) = @_;
490 0         0 return "$arg->{trans}$op->{trans}";
491             }
492              
493             my %v_binop = qw (
494             'ov cmp
495             chel +
496             chelHa' -
497             wav /
498             HUH *
499             chen ..
500             chuv %
501             );
502             my $v_binop = enqr keys %v_binop;
503              
504             my %v_binop_np = qw (
505             logh x
506             je &&
507             joq ||
508             pIm'a' ne
509             rap'a' eq
510             mI'rap'a' ==
511             mI'pIm'a' !=
512             );
513             my $v_binop_np = enqr keys %v_binop_np;
514              
515             sub to_binop {
516 2     2 0 5 my ($left, $right, $op) = @_;
517 2         9 return "$left->{trans} $op->{trans} $right->{trans}";
518             }
519              
520             my %v_binop_d = qw (
521             nob =
522             );
523             my $v_binop_d = enqr keys %v_binop_d;
524             sub to_binop_d {
525 5     5 0 8 my ($left, $right, $op) = @_;
526 5         19 return "$left->{trans} $op->{trans} $right->{trans}";
527             }
528              
529             my %v_ternop = qw (
530             wuq ?:
531             );
532             my $v_ternop = enqr keys %v_ternop;
533             sub to_ternop {
534 0     0 0 0 my ($cond, $iftrue, $iffalse, $op) = @_;
535 0         0 return "$cond->{trans} ? $iftrue->{trans} : $iffalse->{trans}";
536             }
537              
538              
539             my %control = qw(
540             teHchugh if
541             teHchughbe' unless
542             teHtaHvIS while
543             teHtaHvISbe' until
544             tIqel for
545             );
546             my $control = enqr keys %control;
547             sub to_control {
548 1     1 0 3 my ($block, $condition, $control) = @_;
549 1         5 return "$control->{trans} ($condition->{trans}) $block->{trans}";
550             }
551              
552             my %s_decl = qw(
553             wIj my
554             meywIj my
555             pu'wI' my
556             maj our
557             meymaj our
558             pu'ma' our
559             vam local
560             meyvam local
561             pu'vam local
562             );
563             my $s_decl = inqr keys %s_decl;
564              
565             my %noun_dat = qw(
566             ghochna' STDOUT
567             luSpetna' STDERR
568             );
569             my $noun_dat = inqr keys %noun_dat;
570              
571             my %noun_acc = qw(
572             juH main
573             'oH $_
574             chevwI' $/
575             natlhwI' $|
576             bIH @_
577             );
578             my $noun_acc = inqr keys %noun_acc;
579              
580             my %noun_abl = qw(
581             mungna'vo' STDIN
582             De'Daqvo' DATA
583             );
584             my $noun_abl = inqr keys %noun_abl;
585              
586             my @stack;
587             sub tok {
588 86     86 0 91 my %tok;
589 86         300 @tok{qw(type raw trans)} = @_;
590 86         199 return \%tok;
591             }
592              
593             sub nostop {
594 19     19 0 41 my ($word) = @_;
595 19         44 $word =~ s/'/Z/g;
596 19         67 return $word;
597             }
598              
599             sub pushtok {
600 70     70 0 114 my ($type, $raw, $trans) = @_;
601 70 50       146 print STDERR qq{Treated "$raw" as $type meaning "$trans"\n} if $DEBUG;
602 70         70 my $object;
603 70 50       146 $object = $type = 'dat' if $type eq 'object';
604 70 50 100     384 if ($type eq 'acc' && @stack && $stack[-1]{type} eq 'noun_conj') {
      66        
605 0         0 my $conj = pop @stack;
606 0         0 my $left = pop @stack;
607 0         0 push @stack, tok('acc', "$left->{raw} $conj->{raw} $raw",
608             "$left->{trans} $conj->{trans} $trans");
609             }
610             else {
611 70         190 push @stack, tok($type, @_[1..$#_]);
612             }
613 70 50       148 object() if $object;
614             # use Data::Dumper 'Dumper';
615             # print STDERR Dumper [ \@stack ] if $DEBUG;
616 70         739 return $stack[-1];
617             }
618              
619             sub top {
620 60 100 100 60 0 371 return unless @stack and grep $_ eq $stack[-1]{type}, @_;
621 44         149 pop @stack;
622             }
623              
624             sub translate {
625 16 50   16 0 26 my $raw = join " ", map { ref $_ ? $_->{raw} : $_ } @_;
  45         147  
626 16         169 my $what = (caller(1))[3];
627 16         83 $what =~ s/.*:://;
628 2     2   11619 no strict 'refs';
  2         5  
  2         16633  
629 16         74 my $trans = "to_$what"->(@_);
630 16         172 return ($raw, $trans);
631             }
632              
633             sub decl {
634 0     0 0 0 my ($decl) = @_;
635 0 0       0 my $name = top('acc')
636             or die "$decl: pong Sambe'!\n" ; # missing name
637 0         0 $name->{trans} = nostop($name->{raw});
638 0         0 $decl = tok('adj',$decl,$n_decl{$decl});
639 0         0 pushtok('cmd', translate($name,$decl));
640             }
641              
642             sub sub_decl {
643 0     0 0 0 my ($decl) = @_;
644 0 0       0 die "$decl: pong ngoqghom joq Sambe'!\n" # missing name or block
645             unless @stack;
646 0         0 my $name = pop @stack;
647 0         0 my $block;
648 0 0       0 if ($name->{type} eq 'block') {
649 0         0 $block = $name;
650 0         0 $name = tok("","","");
651             }
652             else {
653 0   0     0 $block = top('block') || tok("","","");
654             }
655 0         0 $name->{trans} = nostop($name->{raw});
656 0         0 $decl = tok('verb',$decl,$sub_decl{$decl});
657 0 0       0 if ($name->{trans}) { pushtok('cmd', translate($block,$name,$decl)) }
  0         0  
658 0         0 else { pushtok('acc', translate($block,$name,$decl)) }
659             }
660              
661             sub usage {
662 2     2 0 5 my ($use) = @_;
663 2 50       7 my $name = top('acc')
664             or die "$use: pong Sambe'!\n"; # missing name
665 2         5 $name->{trans} = $name->{raw};
666 2         6 $use = tok('verb',$use,$v_usage{$use});
667 2         7 pushtok('cmd', translate($name,$use));
668             }
669              
670             sub go {
671 0     0 0 0 my ($go) = @_;
672 0         0 my $label = top('acc');
673 0         0 $label->{trans} = $label->{raw};
674 0         0 $go = tok('verb',$go,$v_go{$go});
675 0         0 pushtok('cmd', translate($label,$go));
676             }
677              
678             sub listop {
679 1     1 0 3 my ($op) = @_;
680 1         1 my @list;
681 1         5 while (@stack) {
682 2   50     5 unshift @list, top('acc','block')
683             || die "$op: ngoqghom Sambe'!\n"; # missing codegroup
684 2 100       43 last if $list[0]{type} eq 'block';
685             }
686 1         4 $op = tok('verb',$op,$v_listop{$op});
687 1         4 pushtok('acc', translate(@list,$op));
688             }
689              
690             sub blockop {
691 0     0 0 0 my ($op) = @_;
692 0 0       0 my $name = top('acc','block')
693             or die "$op: ngoqghom Sambe'!\n" ; # missing codegroup
694 0         0 $op = tok('verb',$op,$v_blockop{$op});
695 0         0 pushtok('acc', translate($name,$op));
696             }
697              
698             sub match {
699 0     0 0 0 my ($op) = @_;
700 0 0       0 my $pattern = top('acc')
701             or die "$op: nejwI' Sambe'!\n" ; # missing probe
702 0 0       0 my $expr = top('acc')
703             or die "$op: De' Sambe'!\n" ; # missing data
704 0         0 $op = tok('verb',$op,$v_match{$op});
705 0         0 pushtok('acc', translate($expr,$pattern,$op));
706             }
707              
708             sub change {
709 0     0 0 0 my ($op) = @_;
710 0 0       0 my $becomes = top('acc')
711             or die "$op: tamwI' Sambe'!\n" ; # missing substitution
712 0 0       0 my $pattern = top('acc')
713             or die "$op: nejwI' Sambe'!\n" ; # missing probe
714 0 0       0 my $expr = top('dat')
715             or die "$op: DoS Sambe'!\n" ; # missing data
716 0         0 $op = tok('verb',$op,$v_change{$op});
717 0         0 pushtok('acc', translate($expr,$becomes,$pattern,$op));
718             }
719              
720             sub arg1 {
721 0     0 0 0 my ($func) = @_;
722 0 0 0     0 my $arg = top('acc')
723             or $func->{raw} =~ /$v_arg0/
724             or die "$func: De' Sambe'!\n" ; # missing data
725 0         0 $func = tok('verb',$func,$v_arg1{$func});
726 0         0 pushtok('acc', translate($arg, $func));
727             }
728              
729             sub arg1_da {
730 1     1 0 2 my ($func) = @_;
731 1 50 33     4 my $arg = top('dat','abl','dat_handle','abl_handle')
732             or $func =~ /$v_arg0/
733             or die "$func: DoS ghap Hal Sambe'!\n" ;
734             # missing target or source
735 1         4 $func = tok('verb',$func,$v_arg1_da{$func});
736 1 50 33     21 if ($HONOURABLE && $func->{trans} =~ /print|readline/) {
737 0         0 $func->{trans} =
738             "Lingua::tlhInganHol::yIghun::$func->{trans}_honourably";
739 0 0 0     0 if ($arg && $arg->{type} =~ s/_handle$//) {
740 0         0 $arg->{trans} = '\\*'.$arg->{trans};
741             }
742             }
743 1         4 pushtok('acc', translate($arg, $func));
744             }
745              
746             sub arg2 {
747 0     0 0 0 my ($func) = @_;
748 0 0       0 my $arg2 = top('acc')
749             or die "$func: De' cha'DIch Sambe'!\n"; # missing second data
750 0 0       0 my $arg1 = top('acc')
751             or die "$func: De' wa'DIch Sambe'!\n"; # missing first data
752 0         0 $func = tok('verb',$func,$v_arg2{$func});
753 0         0 pushtok('acc', translate($arg1, $arg2, $func));
754             }
755              
756             sub arg2_da {
757 0     0 0 0 my ($func) = @_;
758 0 0       0 my $arg2 = top('acc')
759             or die "$func: De' Sambe'!\n"; # missing data
760 0 0       0 my $arg1 = top('dat','abl','dat_handle','abl_handle')
761             or die "$func: DoS ghap Hal Sambe'!\n";
762             # missing target or source
763 0         0 $func = tok('verb',$func,$v_arg2_da{$func});
764 0         0 pushtok('acc', translate($arg1, $arg2, $func));
765             }
766              
767             sub arg2_a { # pure *a*blative
768 0     0 0 0 my ($func) = @_;
769 0 0       0 my $arg2 = top('acc')
770             or die "$func: De' Sambe'!\n"; # missing data
771 0 0       0 my $arg1 = top('abl')
772             or die "$func: Hal Sambe'!\n"; # missing source
773 0         0 $func = tok('verb',$func,$v_arg2_a{$func});
774 0 0       0 pushtok($func->{raw} =~ /vaD$/ ? 'dat' :
    0          
775             $func->{raw} =~ /vo'$/ ? 'abl' : 'acc',
776             translate($arg1, $arg2, $func));
777             }
778              
779             sub unop {
780 0     0 0 0 my ($func) = @_;
781 0 0       0 my $arg1 = top('acc')
782             or die "$func: De' wa'DIch Sambe'!\n"; # missing first arg
783 0         0 $func = tok('verb',$func,$v_unop{$func});
784 0         0 pushtok('acc', translate($arg1, $func));
785             }
786              
787             sub unop_dpre {
788 0     0 0 0 my ($func) = @_;
789 0 0       0 my $arg1 = top('dat')
790             or die "$func: DoS Sambe'!\n"; # missing target
791 0         0 $func = tok('verb',$func,$v_unop_dpre{$func});
792 0         0 pushtok('dat', translate($arg1,$func));
793             }
794              
795             sub unop_dpost {
796 0     0 0 0 my ($func) = @_;
797 0 0       0 my $arg1 = top('dat')
798             or die "$func: DoS Sambe'!\n"; # missing target
799 0         0 $func = tok('verb',$func,$v_unop_dpost{$func});
800 0         0 pushtok('dat', translate($arg1,$func));
801             }
802              
803             sub binop {
804 2     2 0 5 my ($func) = @_;
805 2 50       5 my $arg2 = top('acc')
806             or die "$func: De' cha'DIch Sambe'!\n"; # missing second arg
807 2 50       4 my $arg1 = top('acc')
808             or die "$func: De' wa'DIch Sambe'!\n"; # missing first arg
809 2   33     25 $func = tok('verb',$func,$v_binop{$func}||$v_binop_np{$func});
810 2         6 pushtok('acc', translate($arg1, $arg2, $func));
811             }
812              
813             sub binop_d {
814 5     5 0 10 my ($func) = @_;
815 5 50       11 my $arg2 = top('acc','dat')
816             or die "$func: De' Sambe'!\n"; # missing data
817 5 50       9 my $arg1 = top('dat')
818             or die "$func: DoS Sambe'!\n"; # missing target
819 5         12 $func = tok('verb',$func,$v_binop_d{$func});
820 5         11 pushtok('dat', translate($arg1, $arg2, $func));
821             }
822              
823             sub ternop {
824 0     0 0 0 my ($func) = @_;
825 0 0       0 my $iffalse = top('acc')
826             or die "$func: vItvaD De' Sambe'!\n"; # missing truth data
827 0 0       0 my $iftrue = top('acc')
828             or die "$func: nepvaD De' Sambe'!\n"; # missing falsehood data
829 0 0       0 my $cond = top('acc')
830             or die "$func: wuqwI' Sambe'!\n"; # missing decider
831 0         0 $func = tok('verb',$func,$v_ternop{$func});
832 0         0 pushtok('acc', translate($cond, $iftrue, $iffalse, $func));
833             }
834              
835             sub args_da {
836 1     1 0 2 my ($func) = @_;
837 1         2 my @args;
838 1         3 my $first = 1;
839 1         1 while (1) {
840 2 50       15 my $arg = top('acc','dat','abl_handle','dat_handle') or last;
841 2         4 unshift @args, $arg;
842 2 100       8 last if $arg->{type} eq 'dat';
843 1 50 33     20 last if $first and $arg->{list};
844 1         2 $first=0;
845             }
846 1         4 $func = tok('verb',$func,$v_args_da{$func});
847 1 50 33     9 if ($HONOURABLE && $func->{trans} =~ /print|readline/) {
848 0         0 $func->{trans} =
849             "Lingua::tlhInganHol::yIghun::$func->{trans}_honourably";
850 0 0 0     0 if (@args && $args[0]{type} =~ s/_handle$//) {
851 0         0 $args[0]{trans} = '\\*'.$args[0]{trans};
852             }
853             }
854 1         4 pushtok('acc', translate(@args, $func));
855             }
856              
857             sub args {
858 0     0 0 0 my ($func) = @_;
859 0         0 my @args;
860 0         0 my $first = 1;
861 0         0 while (1) {
862 0 0       0 my $arg = top('acc') or last;
863 0         0 unshift @args, $arg;
864 0 0       0 last if $arg->{object};
865 0 0 0     0 last if $first and $arg->{list};
866 0         0 $first=0;
867             }
868 0         0 $func = tok('verb',$func,$v_args{$func});
869 0 0 0     0 if ($HONOURABLE && $func->{trans} eq 'print') {
870 0         0 $func->{trans} =
871             "Lingua::tlhInganHol::yIghun::$func->{trans}_honourably";
872 0 0 0     0 if (@args && $args[0]{type} =~ s/_handle$//) {
873 0         0 $args[0]{trans} = '\\*'.$args[0]{trans};
874             }
875             }
876 0         0 pushtok('acc', translate(@args, $func));
877             }
878              
879             sub args_u {
880 3     3 0 8 my ($func) = @_;
881 3         5 my @args;
882 3         6 my $first = 1;
883 3         5 while (1) {
884 9 100       23 my $arg = top('acc','dat') or last;
885 6         11 unshift @args, $arg;
886 6 50 66     29 last if $first && $arg->{list};
887 6 50       18 last if $arg->{object};
888 6         8 $first = 0;
889             }
890 3 100       18 $func = tok('verb',(@args>1 ? 'tI' : 'yI').$func,$func);
891 3         13 pushtok('acc', translate(@args, $func));
892             }
893              
894             sub args_ur {
895 0     0 0 0 my ($func) = @_;
896 0         0 my @args;
897 0         0 my $first = 1;
898 0         0 while (1) {
899 0 0       0 my $arg = top('acc','dat') or last;
900 0         0 unshift @args, $arg;
901 0 0 0     0 last if $first && $arg->{list};
902 0 0       0 last if $arg->{object};
903 0         0 $first = 0;
904             }
905 0 0       0 $func = tok('verb',(@args>1 ? 'tI' : 'yI').$func.'vetlh',"\$$func");
906 0         0 pushtok('acc', translate(@args, $func));
907             }
908              
909             sub control {
910 1     1 1 2 my ($control) = @_;
911 1 50       4 my $condition = top('acc','dat')
912             or die "$control: tob Sambe'!\n"; # missing test
913 1 50       4 my $block = top('block')
914             or die "$control: ngoqghom Sambe'!\n"; # missing code group
915 1         4 $control = tok('control',$control,$control{$control});
916 1         4 pushtok('cmd', translate($block,$condition,$control));
917             }
918              
919              
920             my @translation;
921              
922             sub object {
923 0 0 0 0 0 0 die "'e': Doch Sambe'"
924             unless @stack && $stack[-1]{type} =~ /^(acc|dat)$/;
925 0         0 $stack[-1]{raw} .= " 'e'";
926 0         0 $stack[-1]{object} = 1;
927             }
928              
929             sub done {
930 13 0   13 0 29 my $cmd = top('cmd','acc','dat')
    50          
931             or die +(@stack ? "<<$stack[-1]{raw}>>Daq: " : "") .
932             'rIn pIHbe!';
933             # unexpected ending
934 13         30 $cmd = "$cmd->{trans};\n";
935 13         37 while (my $conj = top('sent_conj')) {
936 0 0       0 my $left = top('cmd','acc','dat')
    0          
937             or die +(@stack ? "<<$stack[-1]{raw} $conj>>Daq: " : "") .
938             "ra' PoS pIHbe!"; # unexpected left cmd
939 0         0 $cmd = "$left->{trans} $conj->{trans} $cmd";
940             }
941 13         83 $translation[-1] .= $cmd;
942             }
943              
944             sub startblock {
945             # print STDERR qq if $DEBUG;
946 2     2 0 4 push @translation, "";
947 2         5 pushtok('start of block', "{", "{");
948             }
949              
950             sub endblock {
951 2 50   2 0 7 print STDERR qq if $DEBUG;
952 2 0 0     4 top('start of block')
      33        
953             or @stack and die "betleH HivtaH Sampa' veQ: $stack[0]{raw}\n "
954             # garbage found before attacking batleth
955             or die "betleH HivtaH Sambe'";
956             # missing attacking batleth
957 2         11 pushtok('block', "{...}", "{".pop(@translation)."}");
958             }
959              
960             my %nsuff = ( "vo'" => 'abl',
961             "vo'Hal" => 'abl_handle',
962             "Hal" => 'abl_handle',
963             "vaD" => 'dat',
964             "vaDDoS" => 'dat_handle',
965             "DoS" => 'dat_handle',
966             "'e'" => 'object',
967             "" => 'acc' );
968             my $nsuff = qr/${\join"|",reverse sort keys %nsuff}/;
969              
970             sub startlist {
971 1     1 0 4 pushtok('start of list','(','(');
972             }
973              
974             sub endlist {
975 1     1 0 5 my $type = $nsuff{$_[0]};
976 1 50       5 print STDERR qq if $DEBUG;
977 1         2 my @args;
978 1         1 while (1) {
979 26 50       56 die "'etlh HivtaH Sambe'" unless @stack;
980             # missing attacking sword
981 26         29 my $arg = pop @stack;
982 26 100       53 last if $arg->{type} eq 'start of list';
983 25         36 unshift @args, $arg;
984             }
985 1         19 my $raw = join " ", map $_->{raw}, @args;
986 1         20 my $trans = join ",", map $_->{trans}, @args;
987              
988 1         8 pushtok($type, "($raw)$_[0]", "($trans)")->{list} = 1;
989             }
990              
991             my $sing = qr/(?:yI)?/;
992             my $plur = qr/(?:tI)?/;
993             my $any = qr/(?:[yt]I)?/;
994              
995             my %sigil = ( "mey" => '@', "pu'" => '%', "" => '$' );
996             my $type = qr/${\join"|",reverse sort keys %sigil}/;
997              
998             my %comp = ( "tIn" => '>', "mach" => '<',
999             "tInbe'" => '<=', "machbe'" => '<',
1000             "nung" => 'lt', "tlha'" => 'gt',
1001             "nungbe'" => 'ge', "tlha'be'" => 'le',
1002             );
1003             my $comp = inqr keys %comp;
1004              
1005             sub greater {
1006 0     0 0   my ($op) = @_;
1007 0 0         my $arg = top('acc') or die "$op law': DIp $op Sambe'"; # missing noun
1008 0           pushtok('greater', "$arg->{raw} $op law'", "$arg->{trans} $comp{$op}");
1009             }
1010              
1011             sub lesser {
1012 0     0 0   my ($op) = @_;
1013 0 0         my $arg = top('acc')
1014             or die "$op puS: DIp ${op}be' Sambe'!"; # missing noun
1015 0 0         my $greater = top('greater')
1016             or die "$op puS: <<$op law'>> nung Sambe'!";
1017             # preceding *op* law missing
1018 0           pushtok('acc', "$greater->{raw} $arg->{raw} $op puS",
1019             "$greater->{trans} $arg->{trans}");
1020             }
1021              
1022             # my %conj_h = ( "je" => '&&', "joq" => '||' );
1023             my %conj_l = ( "'ej" => 'and', "qoj" => 'or' );
1024              
1025             # my $conj_h = enqr keys %conj_h;
1026             my $conj_l = enqr keys %conj_l;
1027              
1028             # sub conj_h {
1029             # my ($conj) = @_;
1030             # die "$conj: DIp poS Sambe'!" # missing noun on left
1031             # unless @stack && $stack[-1]{type} eq 'acc';
1032             # pushtok('noun_conj', $conj, $conj_h{$conj});
1033             # }
1034              
1035             sub conj_l {
1036 0     0 0   pushtok('sent_conj', $_[0], $conj_l{$_[0]});
1037             }
1038              
1039              
1040             FILTER {
1041             $DEBUG = grep /yIQIj/, @_;
1042             $HONOURABLE = !grep /tera('|::)nganHol/, @_;
1043             my $TRANS = grep /yImugh/, @_;
1044             @stack = ();
1045             $translation[0] = "";
1046             pos $_ = 0;
1047             while (pos $_ < length $_) {
1048             /\G\s+(#.*|jay')?/gc # skip ws, invective, and comments
1049             or /\G!/gc and done
1050             or /\G$conj_l/gc and conj_l("$1")
1051             # or /\G$conj_h/gc and conj_h("$1")
1052             or /\G($number)/gc and pushtok('acc',"$1",to_Terran($1))
1053             or /\G(<<(.*?)>>('e')?)/gc
1054             and pushtok($3?'object':'acc',"$1",qq{qq<$2>})
1055             or /\G(<(.*?)>('e')?)/gc
1056             and pushtok($3?'object':'acc',"$1",qq{q<$2>})
1057             or /\G($comp)\s+law'/gc and greater("$1")
1058             or /\G($comp)\s+puS/gc and lesser("$1")
1059             or /\G$n_decl/gc and decl(nostop $1)
1060             or /\G$sub_decl/gc and sub_decl(nostop $1)
1061             or /\G$sing$v_usage/gc and usage("$1")
1062             or /\G$sing$v_go/gc and go("$1")
1063             or /\G$any$v_listop/gc and listop("$1")
1064             or /\G$any$v_blockop/gc and blockop("$1")
1065             or /\G$sing$v_match/gc and match("$1")
1066             or /\G$any$v_change/gc and change("$1")
1067             or /\G$sing$v_arg1/gc and arg1("$1")
1068             or /\G$sing$v_arg1_da/gc and arg1_da("$1")
1069             or /\G$plur$v_arg2/gc and arg2("$1")
1070             # or /\G$plur$v_arg2_i/gc and arg2_i("$1")
1071             or /\G$sing$v_arg2_da/gc and arg2_da("$1")
1072             or /\G$sing$v_arg2_a/gc and arg2_a("$1")
1073             or /\G$any$v_args/gc and args("$1")
1074             or /\G$any$v_args_da/gc and args_da("$1")
1075             or /\G$sing$v_unop/gc and unop("$1")
1076             or /\G$sing$v_unop_dpre/gc
1077             and unop_dpre("$1")
1078             or /\G$sing$v_unop_dpost/gc
1079             and unop_dpost("$1")
1080             or /\G$plur$v_binop/gc and binop("$1")
1081             or /\G$v_binop_np/gc and binop("$1")
1082             or /\G$any$v_binop_d/gc and binop_d("$1")
1083             or /\G$plur$v_ternop/gc and ternop("$1")
1084             or /\G$control/gc and control("$1")
1085             or /\G[yt]I([^\s!]+?)vetlh$EOW/gc
1086             and args_ur(nostop $1)
1087             or /\G[yt]I([^\s!]+)/gc and args_u(nostop $1)
1088             or /\G[{]/gc and startblock
1089             or /\G[}]/gc and endblock
1090             or /\G[(]/gc and startlist
1091             or /\G[)]($nsuff)/gc and endlist("$1")
1092             or /\G((\S+?)$s_decl$EOW)/gc
1093             and pushtok('dat', "$1",
1094             "$s_decl{$3} ".
1095             ($sigil{substr$3,0,3}||'$').
1096             nostop $2)
1097             or /\G((?:nuqDaq\s+)?(\S+?)laHwI'($nsuff)$EOW)/gc
1098             and pushtok($nsuff{$3}, "$1",
1099             "\\&".nostop $2)
1100             or /\G(nuqDaq\s+(\S+?)($type)($nsuff)$EOW)/gc
1101             and pushtok($nsuff{$4}, "$1",
1102             "\\".$sigil{$3}.nostop $2)
1103             or /\G((\S+?)($type)vetlh($nsuff)$EOW)/gc
1104             and pushtok($nsuff{$4}, "$1",
1105             $sigil{$3}
1106             . "{".nostop($2)."}")
1107             or /\G(nuqDaq\s+$noun_abl($nsuff)$EOW)/gc
1108             and pushtok($nsuff{$3},"$1",
1109             "\\*$noun_abl{$2}")
1110             or /\G(nuqDaq\s+$noun_dat($nsuff)$EOW)/gc
1111             and pushtok($nsuff{$3},"$1",
1112             "\\*$noun_dat{$2}")
1113             or /\G($noun_abl($nsuff)$EOW)/gc
1114             and pushtok($nsuff{$3},"$1",
1115             $noun_abl{$2})
1116             or /\G($noun_dat($nsuff)$EOW)/gc
1117             and pushtok($nsuff{$3},"$1",
1118             $noun_dat{$2})
1119             or /\G(nuqDaq\s+$noun_acc($nsuff)$EOW)/gc
1120             and pushtok($nsuff{$3},"$1",
1121             "\\$noun_acc{$2}")
1122             or /\G($noun_acc($nsuff)$EOW)/gc
1123             and pushtok($nsuff{$3},"$1",
1124             $noun_acc{$2})
1125             or /\G((\S+?)($type)($nsuff)$EOW)/gc
1126             and pushtok($nsuff{$4},"$1",
1127             "$sigil{$3}". nostop $2)
1128             or /\G(.+)\b/gc and die "<<$1>>Daq ngoq SovlaHbe'"
1129             # Unrecognizable code
1130             }
1131             die "ngoq tlhol:\n\t" . join(" ", map $_->{raw}, @stack) . "\n "
1132             if @stack; # unprocessed code
1133             $_ = $translation[0];
1134             print STDERR and exit if $TRANS;
1135             }
1136             qr/^\s*(Lingua(::|')tlhInganHol(::|')yIghun)?\s*(yI)?lo'Qo'\s*!\s*$/;
1137              
1138             1;
1139             __END__