|
22 | 22 | then: |
23 | 23 | - bookmark: "*[1]/@id" |
24 | 24 | - test: |
25 | | - if: parent::*[self::m:negative] |
26 | | - then: [{T: "negativt"}] # phrase(minus 4 is a 'negative' number) |
27 | | - else: [{T: "positivt"}] # phrase(10 is a 'positive' number) |
| 25 | + if: parent::*[self::m:minus and count(*)=1] |
| 26 | + then: [{T: "den negative"}] # phrase(minus 4 is a 'negative' number) |
| 27 | + else: [{T: "den positive"}] # phrase(10 is a 'positive' number) |
28 | 28 | - test: |
29 | 29 | if: "$Verbosity!='Terse'" |
30 | 30 | then: {T: "kvadratroten av"} # phrase(the square root 'of' 5) |
|
48 | 48 | if: $ClearSpeak_Roots = 'PosNegSqRoot' or $ClearSpeak_Roots = 'PosNegSqRootEnd' |
49 | 49 | then: |
50 | 50 | - test: |
51 | | - if: "parent::m:negative or parent::m:positive" |
| 51 | + if: "parent::*[(self::m:minus or self::m:plus) and count(*)=1]" |
52 | 52 | then: [{bookmark: "parent/@id"}] |
53 | 53 | - test: |
54 | | - if: parent::m:negative |
55 | | - then: [{T: "negativt"}] # phrase(minus 6 is a 'negative' number) |
56 | | - else: [{T: "positivt"}] # phrase(10 is a 'positive' number) |
| 54 | + if: parent::m:minus |
| 55 | + then: [{T: "den negative"}] # phrase(minus 6 is a 'negative' number) |
| 56 | + else: [{T: "den positive"}] # phrase(10 is a 'positive' number) |
57 | 57 | - test: |
58 | 58 | if: "*[2][self::m:mn]" |
59 | 59 | then_test: |
60 | | - - if: "*[2][text()='2']" |
| 60 | + - if: "*[2][.='2']" |
61 | 61 | then: {T: "kvadratroten"} # phrase(5 is the 'square root' of 25) |
62 | | - - else_if: "*[2][text()='3']" |
| 62 | + - else_if: "*[2][.='3']" |
63 | 63 | then: {T: "kubikkroten"} # phrase(5 is the 'cube root' of 625) |
64 | 64 | - else_if: "*[2][not(contains(., ','))]" # SWEDISH: Changed decimal point to comma. |
65 | 65 | then: [{x: "ToOrdinal(*[2])"}, {T: "roten"}] # phrase(the square 'root' of 25) |
66 | 66 | else: |
67 | 67 | - T: "roten av grad" # phrase(the square 'root' of 36) |
68 | 68 | - x: "*[2]" |
| 69 | + - pause: short |
69 | 70 | # SWEDISH: Removed verbosity settings. |
70 | 71 | - T: "av" # phrase(the square root 'of' 36) |
71 | 72 | - x: "*[1]" |
|
82 | 83 |
|
83 | 84 | # The 'negative' rule interacts with the msqrt/mroot rules as those might pick off this case ("the negative square root of x") |
84 | 85 | - name: negative_and_positive |
85 | | - tag: [negative, positive] |
86 | | - match: "." |
| 86 | + tag: [plus, minus] |
| 87 | + match: "count(*)=1 and contains(@data-intent-property, ':prefix:')" |
87 | 88 | replace: |
88 | 89 | - test: |
89 | 90 | if: |
|
93 | 94 | else: |
94 | 95 | - bookmark: "@id" |
95 | 96 | - test: |
96 | | - if: "self::m:negative" |
| 97 | + if: "self::m:minus" |
97 | 98 | then: [{T: "minus"}] # phrase(minus 5 is a 'negative' number) |
98 | 99 | else: [{T: "pluss"}] # phrase(7 is a 'positive' number) |
99 | 100 | - x: "*[1]" |
|
104 | 105 | # Units (e.g., meters per second) |
105 | 106 | - name: per-fraction |
106 | 107 | tag: fraction |
107 | | - match: "$ClearSpeak_Fractions='Per'" |
| 108 | + match: "$ClearSpeak_Fractions='Per' or |
| 109 | + BaseNode(*[1])[contains(@data-intent-property, ':unit') or (self::m:mrow and self::*[3][contains(@data-intent-property, ':unit')])] and |
| 110 | + BaseNode(*[1])[contains(@data-intent-property, ':unit') or (self::m:mrow and self::*[3][contains(@data-intent-property, ':unit')])]" |
108 | 111 | replace: |
109 | 112 | - x: "*[1]" |
110 | 113 | - T: "per" # phrase('5 meters 'per' second) |
|
119 | 122 | # SWEDISH: Alternative logic for handling correct reading out of common fractions. |
120 | 123 | variables: [IsPlural: "*[1]!=1"] |
121 | 124 | replace: |
122 | | - - pause: short |
123 | | - - test: |
124 | | - if: "*[1]=1" |
125 | | - then: [T: "en"] |
126 | | - else: [x: "*[1]"] |
| 125 | + #- pause: short |
| 126 | + #- test: |
| 127 | + #if: "*[1]=1" |
| 128 | + #then: [T: "en"] |
| 129 | + #else: [x: "*[1]"] |
| 130 | + - x: "*[1]" |
127 | 131 | - x: "ToOrdinal(*[2], true(), $IsPlural)" # extra args specify fractional ordinal and whether it is plural |
128 | 132 |
|
129 | 133 | - name: common-fraction-mixed-number |
130 | 134 | tag: fraction |
131 | 135 | match: |
132 | | - - "preceding-sibling::*[1][self::m:mo][text()=''] and" # preceding element is invisible plus |
| 136 | + - "preceding-sibling::*[1][self::m:mo][.=''] and" # preceding element is invisible plus |
133 | 137 | - "($ClearSpeak_Fractions='Auto' or $ClearSpeak_Fractions='Ordinal' or $ClearSpeak_Fractions='EndFrac') and" |
134 | 138 | - "*[1][self::m:mn][not(contains(., ',')) and ($ClearSpeak_Fractions='Ordinal' or text()<20)] and" |
135 | 139 | - "*[2][self::m:mn][not(contains(., ',')) and ($ClearSpeak_Fractions='Ordinal' or (2<= text() and text()<=10))]" |
136 | 140 | # SWEDISH: Alternative logic for handling correct reading out of common fractions. |
137 | 141 | variables: [IsPlural: "*[1]!=1"] |
138 | 142 | replace: |
139 | | - - pause: short |
140 | | - - test: |
141 | | - if: "*[1]=1" |
142 | | - then: [T: "en"] |
143 | | - else: [x: "*[1]"] |
| 143 | + #- pause: short |
| 144 | + #- test: |
| 145 | + #if: "*[1]=1" |
| 146 | + #then: [T: "en"] |
| 147 | + #else: [x: "*[1]"] |
| 148 | + - x: "*[1]" |
144 | 149 | - x: "ToOrdinal(*[2], true(), $IsPlural)" # extra args specify fractional ordinal and whether it is plural |
145 | 150 |
|
146 | 151 | - name: fraction-over-simple |
|
177 | 182 | - " ((*[1][self::m:mi or self::m:mtext][string-length(.)>1]) or " # fractions with text |
178 | 183 | - " (*[1][self::m:mrow][count(*)=3][ " |
179 | 184 | - " *[1][self::m:mn] and " |
180 | | - - " *[2][self::m:mo][text()=''] and " # invisible times |
| 185 | + - " *[2][self::m:mo][.=''] and " # invisible times |
181 | 186 | - " *[3][self::m:mi or self::m:mtext][string-length(.)>1] ]) ) and" |
182 | 187 | - " ((*[2][self::m:mi or self::m:mtext][string-length(.)>1]) or " # fractions with text |
183 | 188 | - " (*[2][self::m:mrow][count(*)=3][ " |
184 | 189 | - " *[1][self::m:mn] and " |
185 | | - - " *[2][self::m:mo][text()=''] and " # invisible times |
| 190 | + - " *[2][self::m:mo][.=''] and " # invisible times |
186 | 191 | - " *[3][self::m:mi or self::m:mtext][string-length(.)>1] ]) )" |
187 | 192 | - ")" |
188 | 193 | replace: |
|
229 | 234 | then: [{x: "*[1]"}, {bookmark: "*[2]/@id"}, {T: "invers"}] # phrase(8 over 5 is the 'inverse' of 5 over 8) |
230 | 235 | else_test: |
231 | 236 | if: $ClearSpeak_Trig = 'ArcTrig' |
232 | | - then: [{bookmark: "*[2]/@id"}, {T: "buelenge"}, {x: "*[1]"}] # phrase(the 'buelenge' of a circle) |
| 237 | + then: [{bookmark: "*[2]/@id"}, {T: "arcus"}, {x: "*[1]"}] # phrase(the 'buelenge' of a circle) |
233 | 238 | else: [{bookmark: "*[2]/@id"}, {T: "invers"}, {x: "*[1]"}] # default/Auto # phrase(8 over 5 is the 'inverse' of 5 over 8) |
234 | 239 |
|
235 | 240 |
|
236 | 241 | - name: function-squared-or-cubed |
237 | 242 | tag: power |
238 | 243 | match: |
239 | | - - "*[2][self::m:mn][text()='2' or text()='3'] and" |
240 | | - - "following-sibling::*[1][self::m:mo][text()='']" #invisible function apply |
| 244 | + - "*[2][self::m:mn][.='2' or .='3'] and" |
| 245 | + - "following-sibling::*[1][self::m:mo][.='']" #invisible function apply |
241 | 246 | replace: |
242 | 247 | - x: "*[1]" |
243 | 248 | - bookmark: "*[2]/@id" |
244 | 249 | - test: |
245 | | - if: "*[2][text()='2']" |
| 250 | + if: "*[2][.='2']" |
246 | 251 | then: {T: "i andre"} # phrase(25 equals 5 'squared') #Marthe: "sin^2x sin kvadrert av x" |
247 | 252 | else: {T: "i tredje"} # phrase(625 equals 5 'cubed') |
248 | 253 |
|
249 | 254 | - name: function-power |
250 | 255 | tag: power |
251 | 256 | match: |
252 | | - - "following-sibling::*[1][self::m:mo][text()='']" #invisible function apply |
| 257 | + - "following-sibling::*[1][self::m:mo][.='']" #invisible function apply |
253 | 258 | replace: |
254 | 259 | - x: "*[1]" |
255 | 260 | - T: "opphøyd i" |
|
281 | 286 |
|
282 | 287 | - name: squared |
283 | 288 | tag: power |
284 | | - match: "*[2][self::m:mn][text()='2'] and $ClearSpeak_Exponents = 'Auto'" |
| 289 | + match: "*[2][self::m:mn][.='2'] and $ClearSpeak_Exponents = 'Auto'" |
285 | 290 | replace: |
286 | 291 | - x: "*[1]" |
287 | 292 | - bookmark: "*[2]/@id" |
288 | 293 | - T: "i andre" # phrase(7 'squared' equals 49) #Marthe: "7 kvadrert, 7^2" |
289 | 294 |
|
290 | 295 | - name: cubed |
291 | 296 | tag: power |
292 | | - match: "*[2][self::m:mn][text()='3'] and $ClearSpeak_Exponents = 'Auto'" |
| 297 | + match: "*[2][self::m:mn][.='3'] and $ClearSpeak_Exponents = 'Auto'" |
293 | 298 | replace: |
294 | 299 | - x: "*[1]" |
295 | 300 | - bookmark: "*[2]/@id" |
|
308 | 313 | - name: simple-negative-integer |
309 | 314 | tag: power |
310 | 315 | match: |
311 | | - - "*[2][self::m:negative and" |
| 316 | + - "*[2][self::m:minus and count(*)=1 and" |
312 | 317 | - " *[1][self::m:mn][not(contains(., ','))]" |
313 | 318 | - " ]" |
314 | 319 | replace: |
|
342 | 347 | match: |
343 | 348 | - "$ClearSpeak_Exponents = 'Auto' and" |
344 | 349 | - "*[2][self::m:power][" |
345 | | - - " *[2][self::m:mn][text()='2' or text()='3'] and " # exp is 2 or 3 |
| 350 | + - " *[2][self::m:mn][.='2' or .='3'] and " # exp is 2 or 3 |
346 | 351 | # base is mn, mi, common fraction ([xxx] case) |
347 | 352 | - " *[1][self::m:mn or self::m:mi or " |
348 | 353 | - " self::m:fraction[*[1][self::m:mn][not(contains(., ',')) and text()<20] and" |
|
359 | 364 | tag: power |
360 | 365 | match: |
361 | 366 | - "$ClearSpeak_Exponents = 'Auto' and" |
362 | | - - " *[2][self::m:negative and " |
| 367 | + - " *[2][self::m:minus and count(*)=1 and " |
363 | 368 | - " *[1]/*[1][self::m:power][" |
364 | | - - " *[2][self::m:mn][text()='2' or text()='3'] and " # exp is 2 or 3" |
| 369 | + - " *[2][self::m:mn][.='2' or .='3'] and " # exp is 2 or 3" |
365 | 370 | # base is mn, mi, common fraction ([xxx] case) |
366 | 371 | - " *[1][self::m:mn or self::m:mi or " |
367 | 372 | - " self::m:fraction[*[1][self::m:mn][not(contains(., ',')) and text()<20] and" |
|
381 | 386 | - "$ClearSpeak_Exponents = 'Auto' and" |
382 | 387 | - " *[2][self::m:mrow][count(*)=3][ " |
383 | 388 | - " *[3][self::m:power][" |
384 | | - - " *[2][self::m:mn][text()='2' or text()='3'] and " # exp is 2 or 3 |
| 389 | + - " *[2][self::m:mn][.='2' or .='3'] and " # exp is 2 or 3 |
385 | 390 | - " *[1][self::m:mi]" |
386 | 391 | - " ] and " |
387 | | - - " *[2][self::m:mo][text()=''] and " # invisible times |
| 392 | + - " *[2][self::m:mo][.=''] and " # invisible times |
388 | 393 | # base is mn, or common fraction ([xxx] case) |
389 | 394 | - " *[1][self::m:mn or " |
390 | 395 | - " self::m:fraction[*[1][self::m:mn][not(contains(., ',')) and text()<20] and" |
|
403 | 408 | - "$ClearSpeak_Exponents = 'Auto' and" |
404 | 409 | - " *[2][self::m:mrow][count(*)=3][ " |
405 | 410 | - " *[3][self::m:power][" |
406 | | - - " *[2][self::m:mn][text()='2' or text()='3'] and " # exp is 2 or 3 |
| 411 | + - " *[2][self::m:mn][.='2' or .='3'] and " # exp is 2 or 3 |
407 | 412 | - " *[1][self::m:mi]" |
408 | 413 | - " ] and " |
409 | | - - " *[2][self::m:mo][text()=''] and " # invisible times |
410 | | - - " *[1][self::m:negative and " |
| 414 | + - " *[2][self::m:mo][.=''] and " # invisible times |
| 415 | + - " *[1][self::m:minus and count(*)=1 and " |
411 | 416 | # base is mn, or common fraction ([xxx] case) |
412 | 417 | - " *[1][self::m:mn or " |
413 | 418 | - " self::m:fraction[*[1][self::m:mn][not(contains(., ',')) and text()<20] and" |
|
476 | 481 | if: "$Verbosity!='Terse'" |
477 | 482 | then: {T: "den"} # phrase('the' empty set) |
478 | 483 | - T: "tomme mengden" # phrase(the 'empty set') |
479 | | - - else_if: "count(*[1]/*)=3 and *[1]/*[2][self::m:mo][text()=':' or text()='|' or text()='∣']" |
| 484 | + - else_if: "count(*[1]/*)=3 and *[1]/*[2][self::m:mo][.=':' or .='|' or .='∣']" |
480 | 485 | then: |
481 | 486 | - T: "mengden av" # phrase(this is a 'set of' numbers) |
482 | 487 | - test: |
|
501 | 506 | # SWEDISH: rewrote the intervals function to better deal with Swedish convention of speaking intervals |
502 | 507 | - name: ClearSpeak-intervals # avoid overriding with default "intervals" name |
503 | 508 | variables: |
504 | | - - is_intervals_start_infinity: "*[1][self::m:negative and *[1][text()='∞']]" |
505 | | - - is_intervals_end_infinity: "*[2][text()='∞'or (self::m:positive and *[1][text()='∞'])]" |
| 509 | + - is_intervals_start_infinity: "*[1][self::m:minus and count(*)=1 and *[1][.='∞']]" |
| 510 | + - is_intervals_end_infinity: "*[2][text()='∞'or (self::m:plus and count(*)=1 and *[1][.='∞'])]" |
506 | 511 | tag: [open-interval, open-closed-interval, closed-interval, closed-open-interval] |
507 | 512 | match: "." |
508 | 513 | replace: |
|
562 | 567 | variables: [{log_is_simple: "IsNode(*[3],'simple')"}] |
563 | 568 | match: |
564 | 569 | - "count(*)=3 and" |
565 | | - - "*[1][self::m:mi][text()='log' or text()='ln' or text()='lg'] and" |
566 | | - - "*[2][self::m:mo][text()='']" |
| 570 | + - "*[1][self::m:mi][.='log' or .='ln' or .='lg'] and" |
| 571 | + - "*[2][self::m:mo][.='']" |
567 | 572 | replace: |
568 | 573 | - test: |
569 | 574 | if: "$log_is_simple" |
570 | 575 | then_test: |
571 | | - - if: "*[1][text()='log']" |
| 576 | + - if: "*[1][.='log']" |
572 | 577 | then: [{T: "log"}] # phrase(the 'log' of x) |
573 | | - - else_if: "*[1][text()='lg']" |
| 578 | + - else_if: "*[1][.='lg']" |
574 | 579 | then: [{spell: "'lg'"}] # phrase(the 'lg' of x) |
575 | 580 | - else_if: $ClearSpeak_Log = 'LnAsNaturalLog' |
576 | 581 | then: [{T: "den naturlige logaritmen"}] # phrase(the 'natural log' of the product of 2 numbers) |
577 | 582 | else: [{spell: "'ln'"}] |
578 | 583 | else: |
579 | 584 | - test: |
580 | | - - if: "*[1][text()='log']" |
| 585 | + - if: "*[1][.='log']" |
581 | 586 | then: |
582 | 587 | - test: |
583 | 588 | - if: "$Verbosity='Verbose'" |
584 | 589 | then: [{T: "logaritmen"}] |
585 | 590 | else: [{T: "log"}] |
586 | | - - else_if: "*[1][text()='lg']" |
| 591 | + - else_if: "*[1][.='lg']" |
587 | 592 | then: |
588 | 593 | - test: |
589 | 594 | - if: "$Verbosity='Verbose'" |
|
592 | 597 | - else_if: $ClearSpeak_Log = 'LnAsNaturalLog' or $Verbosity='Verbose' |
593 | 598 | then: [{T: "den naturlige logaritmen"}] # phrase(the 'natural log' of x) |
594 | 599 | else: [{spell: "'ln'"}] |
595 | | - - test: |
596 | | - - if: "$Verbosity='Verbose'" |
597 | | - then: [{T: "av"}] # phrase(the natural log 'of' x) |
| 600 | + #- test: |
| 601 | + #- if: "$Verbosity='Verbose'" |
| 602 | + #then: [{T: "av"}] # phrase(the natural log 'of' x) |
| 603 | + - T: "av" |
598 | 604 | - pause: short |
599 | 605 | - x: "*[3]" |
600 | 606 |
|
|
687 | 693 | - name: ClearSpeak_Functions_None |
688 | 694 | tag: mo |
689 | 695 | match: |
690 | | - - "text()='' and $ClearSpeak_Functions = 'None' and" |
| 696 | + - ".='' and $ClearSpeak_Functions = 'None' and" |
691 | 697 | - "not(preceding-sibling::*[1][IsInDefinition(., 'TrigFunctionNames')])" # Functions=None does not apply to "trig" functions |
692 | 698 | replace: |
693 | 699 | test: |
|
699 | 705 | tag: mo |
700 | 706 | match: |
701 | 707 | # Note: this rule is also part of the paren rule so that the parens speak |
702 | | - - "text()='' and $ClearSpeak_ImpliedTimes = 'None'" |
| 708 | + - ".='' and $ClearSpeak_ImpliedTimes = 'None'" |
703 | 709 | replace: |
704 | 710 | - T: "" |
705 | 711 |
|
|
708 | 714 | match: |
709 | 715 | # say "times" when invisible times is followed by parens or a superscript that has a base with parens or "|"s |
710 | 716 | # if we aren't sure if it is times or not, don't say anything |
711 | | - - "text()='' and (not(@data-function-guess) or $ClearSpeak_Functions = 'None') and" |
| 717 | + - ".='' and (not(@data-function-guess) or $ClearSpeak_Functions = 'None') and" |
712 | 718 | - "not(ancestor-or-self::*[contains(@data-intent-property, ':structure:')]) and (" |
713 | 719 | - " $ClearSpeak_ImpliedTimes = 'MoreImpliedTimes'" |
714 | 720 | - " or " |
715 | 721 | - " following-sibling::*[1][" |
716 | 722 | - " IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '|', '|') or " |
717 | 723 | - " self::m:matrix or self::m:determinant or self::m:binomial or" # followed by parens |
| 724 | + - " self::m:square-root or self::m:msqrt or self::m:root or self::m:mroot or" |
718 | 725 | - " ( (self::m:msup or self::m:msub or self::m:msubsup or self::m:power) and " # followed by msup, etc. |
719 | 726 | - " *[1][self::m:mrow[IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '|', '|')] or " |
720 | 727 | - " self::m:matrix or self::m:determinant]" # base has parens |
|
736 | 743 | - " not(self::m:math) ] and " # rule out [x] standing alone |
737 | 744 | - "( IsBracketed(., '(', ')') or IsBracketed(., '[', ']') ) and " |
738 | 745 | - "not( $ClearSpeak_Functions = 'None' and " |
739 | | - - " (preceding-sibling::*[1][text()=''] or following-sibling::*[1][text()='']) ) and " |
| 746 | + - " (preceding-sibling::*[1][.=''] or following-sibling::*[1][.='']) ) and " |
740 | 747 | - "not( $ClearSpeak_ImpliedTimes = 'None' and " |
741 | | - - " (preceding-sibling::*[1][text()=''] or following-sibling::*[1][text()='']) ) and " |
| 748 | + - " (preceding-sibling::*[1][.=''] or following-sibling::*[1][.='']) ) and " |
742 | 749 | - "IsNode(*[2], 'simple') and" |
743 | 750 | - "not(ancestor-or-self::*[contains(@data-intent-property, ':structure:')])" |
744 | 751 | # missing clause: 'a positive fraction that is spoken as an ordinal |
|
0 commit comments