--- - name: intent-literal-silent tag: [mi, mo, mn] match: "contains(@data-intent-property, ':silent:')" # say nothing replace: [] # handling of negative numbers that come from 'intent' is hard -- we do something that is close to right here - name: intent-literal-negative-number tag: mn match: "starts-with(text(), '-')" replace: - T: "minus" # phrase(10 'minus' 4 equals 6) - x: "translate(text(), '-_', '')" - name: default tag: square-root match: "." replace: - test: if: $ClearSpeak_Roots = 'PosNegSqRoot' or $ClearSpeak_Roots = 'PosNegSqRootEnd' then: - bookmark: "*[1]/@id" - test: if: parent::*[self::m:negative] then: [{T: "negativa"}] # phrase(minus 4 is a 'negative' number) else: [{T: "positiva"}] # phrase(10 is a 'positive' number) - test: if: "$Verbosity!='Terse'" then: {T: "kvadratroten ur"} # phrase(the square root 'of' 5) else: {T: "roten ur"} - x: "*[1]" - test: - if: "$ClearSpeak_Roots = 'RootEnd' or $ClearSpeak_Roots = 'PosNegSqRootEnd'" then: - pause: short - T: "slut rot" # phrase(the square root of x 'end root') - pause: medium - else_if: "IsNode(*[1], 'simple')" then: [{pause: short}] else: [{pause: long}] - name: default tag: root match: "." replace: - test: if: $ClearSpeak_Roots = 'PosNegSqRoot' or $ClearSpeak_Roots = 'PosNegSqRootEnd' then: - test: if: "parent::m:negative or parent::m:positive" then: [{bookmark: "parent/@id"}] - test: if: parent::m:negative then: [{T: "negativa"}] # phrase(minus 6 is a 'negative' number) else: [{T: "positiva"}] # phrase(10 is a 'positive' number) - test: if: "*[2][self::m:mn]" then_test: - if: "*[2][text()='2']" then: {T: "kvadratroten"} # phrase(5 is the 'square root' of 25) - else_if: "*[2][text()='3']" then: {T: "kubikroten"} # phrase(5 is the 'cube root' of 625) - else_if: "*[2][not(contains(., ','))]" # SWEDISH: Changed decimal point to comma. then: [{x: "ToOrdinal(*[2])"}, {T: "roten"}] # phrase(the square 'root' of 25) else: - T: "roten av grad" # phrase(the square 'root' of 36) - x: "*[2]" # SWEDISH: Removed verbosity settings. - T: "ur" # phrase(the square root 'of' 36) - x: "*[1]" - test: if: $ClearSpeak_Roots = 'RootEnd' or $ClearSpeak_Roots = 'PosNegSqRootEnd' then: - pause: short - T: "slut rot" # phrase(start the fifth root of x 'end root') - pause: medium else_test: if: IsNode(*[1], 'simple') then: [{pause: short}] else: [{pause: long}] # The 'negative' rule interacts with the msqrt/mroot rules as those might pick off this case ("the negative square root of x") - name: negative_and_positive tag: [negative, positive] match: "." replace: - test: if: - "*[1][self::m:square-root or self::m:root] and" - "($ClearSpeak_Roots = 'PosNegSqRoot' or $ClearSpeak_Roots = 'PosNegSqRootEnd')" then: {T: ""} else: - bookmark: "@id" - test: if: "self::m:negative" then: [{T: "minus"}] # phrase(minus 5 is a 'negative' number) else: [{T: "plus"}] # phrase(7 is a 'positive' number) - x: "*[1]" # Fraction rules # Mixed numbers mostly "just work" because the invisible char reads as "and" and other parts read properly on their own # Units (e.g., meters per second) - name: per-fraction tag: fraction match: "$ClearSpeak_Fractions='Per'" replace: - x: "*[1]" - T: "per" # phrase('5 meters 'per' second) - x: "*[2]" - name: common-fraction tag: fraction match: - "($ClearSpeak_Fractions='Auto' or $ClearSpeak_Fractions='Ordinal' or $ClearSpeak_Fractions='EndFrac') and" - "*[1][self::m:mn][not(contains(., ',')) and ($ClearSpeak_Fractions='Ordinal' or text()<20)] and" - "*[2][self::m:mn][not(contains(., ',')) and ($ClearSpeak_Fractions='Ordinal' or (2<= text() and text()<=10))]" # SWEDISH: Alternative logic for handling correct reading out of common fractions. variables: [IsPlural: "*[1]!=1"] replace: - pause: short - test: if: "*[1]=1" then: [T: "en"] else: [x: "*[1]"] - x: "ToOrdinal(*[2], true(), $IsPlural)" # extra args specify fractional ordinal and whether it is plural - name: common-fraction-mixed-number tag: fraction match: - "preceding-sibling::*[1][self::m:mo][text()='⁤'] and" # preceding element is invisible plus - "($ClearSpeak_Fractions='Auto' or $ClearSpeak_Fractions='Ordinal' or $ClearSpeak_Fractions='EndFrac') and" - "*[1][self::m:mn][not(contains(., ',')) and ($ClearSpeak_Fractions='Ordinal' or text()<20)] and" - "*[2][self::m:mn][not(contains(., ',')) and ($ClearSpeak_Fractions='Ordinal' or (2<= text() and text()<=10))]" # SWEDISH: Alternative logic for handling correct reading out of common fractions. variables: [IsPlural: "*[1]!=1"] replace: - pause: short - test: if: "*[1]=1" then: [T: "en"] else: [x: "*[1]"] - x: "ToOrdinal(*[2], true(), $IsPlural)" # extra args specify fractional ordinal and whether it is plural - name: fraction-over-simple tag: fraction match: - "($ClearSpeak_Fractions='Over' or $ClearSpeak_Fractions='FracOver' or $ClearSpeak_Fractions='OverEndFrac') or" - "( not($ClearSpeak_Fractions='General' or $ClearSpeak_Fractions='GeneralEndFrac') and" - " (IsNode(*[1],'simple') and IsNode(*[2],'simple')) )" # simple fraction in ClearSpeak spec replace: - pause: short - test: # SWEDISH: Made a test to differentiate between "division" and "bråk", where "bråk" should have integers as both nominator and denominator. We do however allow single identifiers as well. if: "(*[1][self::m:mn][not(contains(., ','))] or *[1][self::m:mi][string-length(.)=1]) and (*[2][self::m:mn][not(contains(., ','))] or *[2][self::m:mi][string-length(.)=1])" then: - test: if: "$Verbosity!='Terse'" then: [T: "bråk"] # [{ot: "the"}] - pause: short else: - test: if: "$Verbosity!='Terse'" then: [T: "division"] - pause: short - x: "*[1]" - T: "genom" # phrase(the fraction 3 'over' 4) - x: "*[2]" - test: # very ugly!!! -- replicate nested ordinal fraction as they are an exception # SWEDISH: Included the same differentiating test here, as above. if: "(*[1][self::m:mn][not(contains(., ','))] or *[1][self::m:mi][string-length(.)=1]) and (*[2][self::m:mn][not(contains(., ','))] or *[2][self::m:mi][string-length(.)=1])" then: - pause: short - test: if: "$Verbosity!='Terse'" then: [T: "slut bråk"] # phrase(7 over 8 'end fraction') - pause: short else: - pause: short - test: if: "$Verbosity!='Terse'" then: [T: "slut division"] # phrase(7 over 8 'end fraction') - pause: short - # fraction with text or numbers followed by text in both numerator and denominator name: fraction-over-text tag: fraction match: - "not($ClearSpeak_Fractions='General' or $ClearSpeak_Fractions='GeneralEndFrac') and" - "( " - " ((*[1][self::m:mi or self::m:mtext][string-length(.)>1]) or " # fractions with text - " (*[1][self::m:mrow][count(*)=3][ " - " *[1][self::m:mn] and " - " *[2][self::m:mo][text()='⁢'] and " # invisible times - " *[3][self::m:mi or self::m:mtext][string-length(.)>1] ]) ) and" - " ((*[2][self::m:mi or self::m:mtext][string-length(.)>1]) or " # fractions with text - " (*[2][self::m:mrow][count(*)=3][ " - " *[1][self::m:mn] and " - " *[2][self::m:mo][text()='⁢'] and " # invisible times - " *[3][self::m:mi or self::m:mtext][string-length(.)>1] ]) )" - ")" replace: - pause: short - x: "*[1]" - T: "genom" # phrase(the fraction 3 'over' 4) - x: "*[2]" - test: if: "$ClearSpeak_Fractions='EndFrac' or $ClearSpeak_Fractions='OverEndFrac'" then: - pause: short - T: "slut division" # phrase(7 over 8 'end fraction') - pause: short - name: default tag: fraction match: "." replace: - test: if: "$Verbosity!='Terse'" then: [T: "division med täljaren"] # phrase(the 'fraction with numerator' 6) else: - T: "division" - pause: short - T: "täljare" - test: if: not(IsNode(*[1], 'simple')) then: {pause: medium} - x: "*[1]" - pause: medium - test: if: "$Verbosity!='Terse'" then: [T: "och nämnaren"] # phrase(the fraction with numerator 5 'and denominator' 8) else: [T: "nämnare"] - x: "*[2]" - pause: long - test: if: "$ClearSpeak_Fractions='EndFrac' or $ClearSpeak_Fractions='GeneralEndFrac'" then: - pause: short - T: "slut division" # phrase(the fraction with 3 over 4 'end fraction') - pause: short # rules for functions raised to a power # these could have been written on 'mrow' but putting them on msup seems more specific # to see if it is a function, we look right to see if the following sibling is apply-function - name: ClearSpeak-function-inverse tag: inverse-function match: "." replace: - test: if: $ClearSpeak_Trig = 'TrigInverse' then: [{x: "*[1]"}, {bookmark: "*[2]/@id"}, {T: "invers"}] # phrase(8 over 5 is the 'inverse' of 5 over 8) else_test: if: $ClearSpeak_Trig = 'ArcTrig' then: [{bookmark: "*[2]/@id"}, {T: "arc"}, {x: "*[1]"}] # phrase(the 'arc' of a circle) else: [{bookmark: "*[2]/@id"}, {T: "invers"}, {x: "*[1]"}] # default/Auto # phrase(8 over 5 is the 'inverse' of 5 over 8) - name: function-squared-or-cubed tag: power match: - "*[2][self::m:mn][text()='2' or text()='3'] and" - "following-sibling::*[1][self::m:mo][text()='⁡']" #invisible function apply replace: - x: "*[1]" - bookmark: "*[2]/@id" - test: if: "*[2][text()='2']" then: {T: "kvadrat"} # phrase(25 equals 5 'squared') else: {T: "kubik"} # phrase(625 equals 5 'cubed') - name: function-power tag: power match: - "following-sibling::*[1][self::m:mo][text()='⁡']" #invisible function apply replace: - x: "*[1]" - T: "upphöjt till" - bookmark: "*[2]/@id" - x: "*[2]" - pause: short - name: AfterPower-nested tag: power match: # directly a superscript or an mrow that contains a superscript - "$ClearSpeak_Exponents = 'AfterPower' and" - "*[2][self::m:power or self::m:power or self::m:mrow[m:power]]" replace: - x: "*[1]" - T: "upphöjt till exponenten" # phrase(5 'raised to the exponent' x plus 1) - pause: short - x: "*[2]" - pause: short - T: "slut exponent" # phrase(5 raised to the exponent x plus 1 'end exponent') - name: AfterPower-default tag: power match: "$ClearSpeak_Exponents = 'AfterPower'" replace: - x: "*[1]" - T: "upphöjt till" # phrase(x is 'raised to the power' 4) - x: "*[2]" - pause: short - name: squared tag: power match: "*[2][self::m:mn][text()='2'] and $ClearSpeak_Exponents = 'Auto'" replace: - x: "*[1]" - bookmark: "*[2]/@id" - T: "kvadrat" # phrase(7 'squared' equals 49) - name: cubed tag: power match: "*[2][self::m:mn][text()='3'] and $ClearSpeak_Exponents = 'Auto'" replace: - x: "*[1]" - bookmark: "*[2]/@id" - T: "kubik" # phrase(5 'cubed' equals 125) - name: simple-integer tag: power match: "*[2][self::m:mn][not(contains(., ','))]" replace: - x: "*[1]" - T: "upphöjt till" - bookmark: "*[2]/@id" - x: "*[2]" - pause: short - name: simple-negative-integer tag: power match: - "*[2][self::m:negative and" - " *[1][self::m:mn][not(contains(., ','))]" - " ]" replace: - x: "*[1]" - T: "upphöjt till" - bookmark: "*[2]/@id" - x: "*[2]" - pause: short - name: simple-var tag: power match: "*[2][self::m:mi][string-length(.)=1]" replace: - x: "*[1]" - T: "upphöjt till" - bookmark: "*[2]/@id" - x: "*[2]" - pause: short # match nested exponent, where the nested exponent is has the power 2 or 3 (n below) # [xxx]^n, - [xxx]^n, [xxx] var^n, -[xxx] var^n # where xxx is a number or common fraction (or a var in the first two forms) # short of creating a specialized built-in function, I don't see a way to eliminate a lot of repetition in the matches # also really bad is that the test of a common fraction is replicated here (four times!) # Note: the ClearSpeak doc doesn't say these only apply when the pref is "Auto", # but the test cases all fall back to "raised to the exponent" when not "Auto" # If these are allowed for non-Auto values, then you end up with "...power power...". - # [xxx]^n name: nested-squared-or-cubed tag: power match: - "$ClearSpeak_Exponents = 'Auto' and" - "*[2][self::m:power][" - " *[2][self::m:mn][text()='2' or text()='3'] and " # exp is 2 or 3 # base is mn, mi, common fraction ([xxx] case) - " *[1][self::m:mn or self::m:mi or " - " self::m:fraction[*[1][self::m:mn][not(contains(., ',')) and text()<20] and" - " *[2][self::m:mn][not(contains(., ',')) and 2<= text() and text()<=10]]" - " ]" - " ]" replace: - x: "*[1]" - T: "upphöjt till" # phrase(x 'raised to the' second power) - x: "*[2]" - # - [xxx]^n name: nested-negative-squared-or-cubed tag: power match: - "$ClearSpeak_Exponents = 'Auto' and" - " *[2][self::m:negative and " - " *[1]/*[1][self::m:power][" - " *[2][self::m:mn][text()='2' or text()='3'] and " # exp is 2 or 3" # base is mn, mi, common fraction ([xxx] case) - " *[1][self::m:mn or self::m:mi or " - " self::m:fraction[*[1][self::m:mn][not(contains(., ',')) and text()<20] and" - " *[2][self::m:mn][not(contains(., ',')) and 2<= text() and text()<=10]]" - " ]" - " ]" - " ]" replace: - x: "*[1]" - T: "upphöjt till" # phrase(x 'raised to the' second power) - x: "*[2]" - # [xxx] var^n name: nested-var-squared-or-cubed tag: power match: - "$ClearSpeak_Exponents = 'Auto' and" - " *[2][self::m:mrow][count(*)=3][ " - " *[3][self::m:power][" - " *[2][self::m:mn][text()='2' or text()='3'] and " # exp is 2 or 3 - " *[1][self::m:mi]" - " ] and " - " *[2][self::m:mo][text()='⁢'] and " # invisible times # base is mn, or common fraction ([xxx] case) - " *[1][self::m:mn or " - " self::m:fraction[*[1][self::m:mn][not(contains(., ',')) and text()<20] and" - " *[2][self::m:mn][not(contains(., ',')) and 2<= text() and text()<=10]]" - " ]" - " ]" replace: - x: "*[1]" - T: "upphöjt till" # phrase(x 'raised to the' second power) - x: "*[2]" - # -[xxx] var^n name: nested-negative-var-squared-or-cubed tag: power match: - "$ClearSpeak_Exponents = 'Auto' and" - " *[2][self::m:mrow][count(*)=3][ " - " *[3][self::m:power][" - " *[2][self::m:mn][text()='2' or text()='3'] and " # exp is 2 or 3 - " *[1][self::m:mi]" - " ] and " - " *[2][self::m:mo][text()='⁢'] and " # invisible times - " *[1][self::m:negative and " # base is mn, or common fraction ([xxx] case) - " *[1][self::m:mn or " - " self::m:fraction[*[1][self::m:mn][not(contains(., ',')) and text()<20] and" - " *[2][self::m:mn][not(contains(., ',')) and 2<= text() and text()<=10]]" - " ]" - " ]" - " ]" replace: - x: "*[1]" - T: "upphöjt till" # phrase(x 'raised to the' second power) - x: "*[2]" - name: default-exponent-power tag: power match: # directly a superscript or an mrow that contains a superscript - "*[2][self::m:power or self::m:power or self::m:mrow[m:power]]" replace: - x: "*[1]" - T: "upphöjt till exponenten" # phrase(x is 'raised to the exponent') - pause: short - x: "*[2]" - pause: short - T: "slut exponent" # phrase(and now 'end exponent' has been reached) - name: default tag: power match: "." replace: - x: "*[1]" - T: "upphöjt till" # phrase(x 'raised to the' second power) - x: "*[2]" # # Some rules on mrows # - # the inference rules lump absolute value and cardinality together, so those rules are implemented here name: ClearSpeak-absolute-value tag: absolute-value match: "." # SWEDISH: Differentiate between the initial and ending declaration of the terms. variables: - WordToSay: "IFTHENELSE($ClearSpeak_AbsoluteValue = 'Cardinality', 'kardinaliteten', 'absolutbeloppet')" - EndToSay: "IFTHENELSE($ClearSpeak_AbsoluteValue = 'Cardinality', 'kardinalitet', 'absolutbelopp')" replace: - x: "$WordToSay" - T: "av" # phrase(the absolute value 'of' 25) - x: "*[1]" - test: if: "$ClearSpeak_AbsoluteValue = 'AbsEnd'" then: - pause: short - T: "slut" # phrase('end' absolute value) - x: "$EndToSay" - pause: short - name: set tag: set match: "." replace: - test: - if: "count(*)=0" then: [{T: "den tomma mängden"}] # phrase('the empty set') - else_if: "count(*)=2" then: - test: if: "$Verbosity!='Terse'" then: {T: "den"} # phrase('the' empty set) - T: "tomma mängden" # phrase(the 'empty set') - else_if: "count(*[1]/*)=3 and *[1]/*[2][self::m:mo][text()=':' or text()='|' or text()='∣']" then: - T: "mängden av" # phrase(this is a 'set of' numbers) - test: if: $ClearSpeak_Sets != 'woAll' then: [{T: "alla"}] # phrase(the set of 'all' integers) - x: "*[1]/*[1]" - T: "sådana att" # phrase(the set S 'such that' x is less than y) - x: "*[1]/*[3]" else: - test: if: $ClearSpeak_Sets != 'SilentBracket' then: - T: "mängden" # phrase(this is a 'set' of integers) - x: "*[1]" #- # intervals are controlled by a ClearSpeak Preference -- parens/brackets don't have to match, so we avoid IsBracketed # # alternatively, we could have four (or ten) rules, but there is a lot of duplication if we do that # # this one rule handles all ten cases listed as part $ClearSpeak_Paren = 'Interval' # # note that *[2] is an mrow with X, ",", Y, so getting X or Y is a double index # onto the [not] [including]... part # SWEDISH: rewrote the intervals function to better deal with Swedish convention of speaking intervals - name: ClearSpeak-intervals # avoid overriding with default "intervals" name variables: - is_intervals_start_infinity: "*[1][self::m:negative and *[1][text()='∞']]" - is_intervals_end_infinity: "*[2][text()='∞'or (self::m:positive and *[1][text()='∞'])]" tag: [open-interval, open-closed-interval, closed-interval, closed-open-interval] match: "." replace: - test: - if: "$Verbosity!='Terse'" then: - T: "det" - test: - if: "name(.)='open-interval'" then: [T: "öppna"] - else_if: "name(.)='open-closed-interval' or name(.)='closed-open-interval'" then: [T: "halvöppna"] - else_if: "name(.)='closed-interval'" then: [T: "slutna"] - T: "intervallet från" # phrase('the interval from' a to b) - test: - if: "name(.)='closed-open-interval'" then: [T: "och med"] - x: "*[1]" - T: "till" # phrase(the interval from a 'to' b) - test: - if: "name(.)='open-closed-interval'" then: [T: "och med"] - x: "*[2]" - name: binomial-frac-vector tag: matrix match: - "$ClearSpeak_Matrix = 'Combinatorics' and " - "count(*[1]/*)=1 and count(*)=2" replace: - x: "*[1]/*[1]/*" # mtable/mtr/mtd - T: "över" # phrase(the binomial coefficient n 'choose' m) - x: "*[2]/*[1]/*" - name: ClearSpeak-default tag: [mtr, mlabeledtr] match: "parent::m:matrix or parent::m:determinant" replace: - T: "rad" # phrase(the first 'row' of a matrix) - x: "count(preceding-sibling::*)+1" - test: if: .[self::m:mlabeledtr] then: - T: "med etiketten" # phrase(the line 'with label' first equation) - x: "*[1]/*" - pause: short - pause: medium - test: if: .[self::m:mlabeledtr] then: [{x: "*[position()>1]"}] else: {x: "*"} - # handle both log and ln name: ClearSpeak-log tag: mrow variables: [{log_is_simple: "IsNode(*[3],'simple')"}] match: - "count(*)=3 and" - "*[1][self::m:mi][text()='log' or text()='ln' or text()='lg'] and" - "*[2][self::m:mo][text()='⁡']" replace: - test: if: "$log_is_simple" then_test: - if: "*[1][text()='log']" then: [{T: "logg"}] # phrase(the 'log' of x) - else_if: "*[1][text()='lg']" then: [{spell: "'lg'"}] # phrase(the 'lg' of x) - else_if: $ClearSpeak_Log = 'LnAsNaturalLog' then: [{T: "naturliga logaritmen"}] # phrase(the 'natural log' of the product of 2 numbers) else: [{spell: "'ln'"}] else: - test: - if: "*[1][text()='log']" then: - test: - if: "$Verbosity='Verbose'" then: [{T: "logaritmen"}] else: [{T: "logg"}] - else_if: "*[1][text()='lg']" then: - test: - if: "$Verbosity='Verbose'" then: [{T: "tio-logaritmen"}] else: [{spell: "'lg'"}] # phrase(the 'lg' of x) - else_if: $ClearSpeak_Log = 'LnAsNaturalLog' or $Verbosity='Verbose' then: [{T: "naturliga logaritmen"}] # phrase(the 'natural log' of x) else: [{spell: "'ln'"}] - test: - if: "$Verbosity='Verbose'" then: [{T: "av"}] # phrase(the natural log 'of' x) - pause: short - x: "*[3]" - name: ClearSpeak-multi-line tag: [piecewise, system-of-equations, lines] # these are ignored in favor of the ClearSpeak prefs match: "." variables: [IsColumnSilent: true()] replace: - x: "count(*)" - test: - if: $ClearSpeak_MultiLineOverview = 'Auto' then: - test: - if: "($ClearSpeak_MultiLineLabel = 'Auto' and self::m:piecewise) or $ClearSpeak_MultiLineLabel = 'Case'" then: - test: - if: "count(*) > 1 and $ClearSpeak_MultiLineLabel != 'None'" then: [{T: "fall"}] else: [{T: "fall"}] # phrase(this is the first 'case' of three cases) - else_if: "$ClearSpeak_MultiLineLabel = 'Auto' or $ClearSpeak_MultiLineLabel = 'Line'" # already dealt with Auto/Case then: - test: - if: "count(*) > 1 and $ClearSpeak_MultiLineLabel != 'None'" then: [{T: "rader"}] # phrase(this is the first 'line' of three lines) else: [{T: "rad"}] # phrase(this is the first 'line' of three lines) - else_if: "$ClearSpeak_MultiLineLabel = 'Constraint'" then: - test: - if: "count(*) > 1 and $ClearSpeak_MultiLineLabel != 'None'" then: [{T: "avgränsningar"}] # phrase(this is the first 'constraint' of three constraints) else: [{T: "avgränsning"}] # phrase(this is the first 'constraint' of three constraints) - else_if: "$ClearSpeak_MultiLineLabel = 'Equation'" then: - test: - if: "count(*) > 1 and $ClearSpeak_MultiLineLabel != 'None'" then: [{T: "ekvationer"}] # phrase(this is the first 'equation' of three equations) else: [{T: "ekvation"}] # phrase(this is the first 'equation' of three equations) - else_if: "$ClearSpeak_MultiLineLabel = 'Row'" then: - test: - if: "count(*) > 1 and $ClearSpeak_MultiLineLabel != 'None'" then: [{T: "rader"}] # phrase(this is the first 'row' of three rows) else: [{T: "rad"}] # phrase(this is the first 'row' of three rows) - else_if: "$ClearSpeak_MultiLineLabel = 'Step'" then: - test: - if: "count(*) > 1 and $ClearSpeak_MultiLineLabel != 'None'" then: [{T: "steg"}] # phrase(this is the first 'step' of three steps) else: [{T: "steg"}] # phrase(this is the first 'step' of three steps) # SWEDISH: Every expression had to be inflected separately. - pause: short - x: "*" - name: ClearSpeak-default-multiline tag: [mtr, mlabeledtr] match: "parent::m:piecewise or parent::m:system-of-equations or parent::m:lines" replace: - test: - if: "($ClearSpeak_MultiLineLabel = 'Auto' and parent::m:piecewise) or $ClearSpeak_MultiLineLabel = 'Case'" then: [{T: "fall"}] # phrase(in this 'case' x is not equal to y) - else_if: "$ClearSpeak_MultiLineLabel = 'Auto' or $ClearSpeak_MultiLineLabel = 'Line'" # already dealt with Auto/Case then: [{T: "rad"}] # phrase(the straight 'line' between x and y) - else_if: "$ClearSpeak_MultiLineLabel = 'Constraint'" then: [{T: "avgränsning"}] # phrase(there is a 'constraint' on possible values) - else_if: "$ClearSpeak_MultiLineLabel = 'Equation'" then: [{T: "ekvation"}] # phrase(the 'equation' pi r squared gives the area of a circle) - else_if: "$ClearSpeak_MultiLineLabel = 'Row'" then: [{T: "rad"}] # phrase(the values on the top 'row' are relevant) - else_if: "$ClearSpeak_MultiLineLabel = 'Step'" then: [{T: "steg"}] # phrase(this is a 'step' by step process) # else 'None -- don't say anything' - test: if: "$ClearSpeak_MultiLineLabel != 'None'" then: - x: "count(preceding-sibling::*)+1" - test: if: .[self::m:mlabeledtr] then: - T: "med etiketten" # phrase(the item 'with label' complete) - x: "*[1]/*" - pause: medium - test: if: .[self::m:mlabeledtr] then: [{x: "*[position()>1]"}] else: {x: "*"} - test: if: "$ClearSpeak_MultiLineLabel != 'None'" then: [{pause: long}] - name: ClearSpeak_Functions_None tag: mo match: - "text()='⁡' and $ClearSpeak_Functions = 'None' and" - "not(preceding-sibling::*[1][IsInDefinition(., 'TrigFunctionNames')])" # Functions=None does not apply to "trig" functions replace: test: if: "$ClearSpeak_ImpliedTimes = 'None'" then: [{T: ""}] else: [{T: "gånger"}] # phrase(5 'times' 3 equals 15) - name: no-times tag: mo match: # Note: this rule is also part of the paren rule so that the parens speak - "text()='⁢' and $ClearSpeak_ImpliedTimes = 'None'" replace: - T: "" - name: ClearSpeak-times tag: mo match: # say "times" when invisible times is followed by parens or a superscript that has a base with parens or "|"s # if we aren't sure if it is times or not, don't say anything - "text()='⁢' and (not(@data-function-guess) or $ClearSpeak_Functions = 'None') and" - "not(ancestor-or-self::*[contains(@data-intent-property, ':structure:')]) and (" - " $ClearSpeak_ImpliedTimes = 'MoreImpliedTimes'" - " or " - " following-sibling::*[1][" - " IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '|', '|') or self::m:binomial or" # followed by parens - " ( (self::m:msup or self::m:msub or self::m:msubsup or self::m:power) and " # followed by msup, etc. - " *[1][self::m:mrow][IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '|', '|')]" # base has parens - " )" - " ]" # other possibility is the preceding element has parens (but not the following) # this is not mentioned in the ClearSpeak rules or examples but seems like it should say "times". E.g, |x| y - " or " - " preceding-sibling::*[1][" - " IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '|', '|')]" # followed by parens - " )" replace: - T: "gånger" # phrase(5 'times' 3 equals 15) - name: no-say-parens tag: mrow match: - "parent::*[not(self::m:msup) and not(self::m:msub) and not(self::m:msubsup) and not(self::m:power) and" - " not(self::m:math) ] and " # rule out [x] standing alone - "( IsBracketed(., '(', ')') or IsBracketed(., '[', ']') ) and " - "not( $ClearSpeak_Functions = 'None' and " - " (preceding-sibling::*[1][text()='⁡'] or following-sibling::*[1][text()='⁡']) ) and " - "not( $ClearSpeak_ImpliedTimes = 'None' and " - " (preceding-sibling::*[1][text()='⁢'] or following-sibling::*[1][text()='⁢']) ) and " - "IsNode(*[2], 'simple') and" - "not(ancestor-or-self::*[contains(@data-intent-property, ':structure:')])" # missing clause: 'a positive fraction that is spoken as an ordinal # (either by the Ordinal preference or by the default rules)' replace: - x: "*[2]" - include: "SharedRules/geometry.yaml" - include: "SharedRules/linear-algebra.yaml" - include: "SharedRules/calculus.yaml" - include: "SharedRules/general.yaml" - include: "SharedRules/default.yaml"