---
#default rules shared among several speech rules
- name: probability-given
  tag: math
  match: "count(*)=6 and *[1][.='P'] and *[2][.='('] and *[4][.='|'] and *[6][.=')']"
  replace:
  - x: "*[1]"
  - pause: short
  - t: "открывающая круглая скобка"
  - pause: short
  - x: "*[3]"
  - x: "*[4]"
  - x: "*[5]"
  - pause: short
  - t: "закрывающая круглая скобка"

- name: probability-given-bracketed
  tag: [math, mrow]
  match: "*[1][self::m:mi[.='P']] and *[last()][IsBracketed(., '(', ')') and .//m:mo[.='|']]"
  replace:
  - t: "пэ большое"
  - pause: short
  - t: "скобка открывается"
  - pause: short
  - test:
    - if: "*[last()]//*[self::m:mi[.='A']]"
      then: [t: "а большое"]
    - else: [x: "*[last()]//*[self::m:mo[.='|']]/preceding-sibling::*[1]"]
  - x: "*[last()]//*[self::m:mo[.='|']]"
  - test:
    - if: "*[last()]//*[self::m:mi[.='B']]"
      then: [t: "бэ большое"]
    - else: [x: "*[last()]//*[self::m:mo[.='|']]/following-sibling::*[1]"]
  - pause: short
  - t: "скобка закрывается"

- name: vector-cross-product
  tag: [math, mrow]
  match: "$SpeechStyle='ClearSpeak' and $ClearSpeak_MultSymbolX='Cross' and count(*)=3 and *[1][self::m:mi] and *[2][.='×'] and *[3][self::m:mi]"
  replace:
  - test:
    - if: "*[1][.='u']"
      then: [t: "у"]
    - else: [x: "*[1]"]
  - x: "*[2]"
  - x: "*[3]"

- name: limit-followed-by-fraction
  tag: [math, mrow]
  match: "count(*)=2 and *[1][name()='limit'] and *[2][name()='fraction' or name()='mfrac' or .//*[name()='fraction' or name()='mfrac']]"
  replace:
  - t: "предел при"
  - x: "*[1]/*[1]"
  - pause: short
  - t: "от"
  - test:
      if: "$Impairment='LearningDisability'"
      then: [pause: medium]
      else: [pause: short]
  - x: "*[2]"

- name: limit-followed-by-apply-fraction
  tag: mrow
  match: "count(*)=3 and *[1][name()='limit'] and *[2][.='\u2061'] and *[3][name()='fraction' or name()='mfrac']"
  replace:
  - t: "предел при"
  - x: "*[1]/*[1]"
  - pause: short
  - t: "от"
  - test:
      if: "$Impairment='LearningDisability'"
      then: [pause: medium]
      else: [pause: short]
  - x: "*[3]"

- name: default
  tag: math
  match: "."
  replace:
  - with:
      variables:
      - ClearSpeak_Fractions: "IfThenElse($Verbosity='Verbose' and $ClearSpeak_Fractions='Auto', 'EndFrac', $ClearSpeak_Fractions)"
      - ClearSpeak_AbsoluteValue: "IfThenElse($Verbosity='Verbose' and $ClearSpeak_AbsoluteValue='Auto', 'AbsEnd', $ClearSpeak_AbsoluteValue)"
      - ClearSpeak_Roots: "IfThenElse($Verbosity='Verbose' and $ClearSpeak_Roots='Auto', 'RootEnd', $ClearSpeak_Roots)"
      - ClearSpeak_Matrix: "IfThenElse($Verbosity='Verbose' and $ClearSpeak_Matrix='Auto', 'EndMatrix', $ClearSpeak_Matrix)"

      - MatchingPause: false()
      # should be set at mtable level, but unknown intents make that impossible to know
      - IsColumnSilent: false()
      replace:
      - test:
          if: "$MathRate = 100"
          then: [x: "*"]
          else:
          - rate:
              value: "$MathRate"
              replace: [x: "*"]

- name: empty-mrow
  tag: mrow
  match: "not(*)"
  replace:
  - t: "полем" # say nothing -- placeholder

- name: limit-approach
  tag: mrow
  match: "parent::m:limit and count(*)=3 and *[2][.='→' or .='↗']"
  replace:
  - x: "*[1]"
  - t: "стремящемся к"
  - x: "*[3]"
  - test:
      if: "*[2][.='↗']"
      then: [t: "снизу"]

- name: probability-given
  tag: mrow
  match: "count(*)=6 and *[1][.='P'] and *[2][.='('] and *[4][.='|'] and *[6][.=')']"
  replace:
  - x: "*[1]"
  - pause: short
  - t: "открывающая круглая скобка"
  - pause: short
  - x: "*[3]"
  - x: "*[4]"
  - x: "*[5]"
  - pause: short
  - t: "закрывающая круглая скобка"

- name: literal-function-application
  tag: mrow
  match:
  - "count(*)=3 and *[2][.='⁡'] and *[3][IsBracketed(., '(', ')')] and"
  - "($SpeechStyle='LiteralSpeak' or ancestor-or-self::*[contains(@data-intent-property, ':literal:')])"
  replace:
  - x: "*[1]"
  - pause: short
  - t: "открывающая круглая скобка"
  - test:
      if: "*[3]/*[2]"
      then: [x: "*[3]/*[2]"]
      else: [x: "*[3]"]
  - pause: short
  - t: "закрывающая круглая скобка"

- name: literal-perpendicular-row
  tag: mrow
  match: "count(*)=3 and *[2][self::m:mi[.='perpendicular-to' or .='perpendicular to' or .='perpendicular_to']]"
  replace:
  - x: "*[1]"
  - pause: short
  - x: "*[2]"
  - pause: short
  - x: "*[3]"

- name: modified-variable
  tag: modified-variable
  match: "count(*)=2"
  replace:
  - x: "*[1]"
  - x: "*[2]"

- name: phi-exponential-equation
  tag: mrow
  match: "count(*)=3 and *[1][.//m:mi[.='ϕ']] and *[2][.='='] and *[3][.//m:mi[.='c'] and .//*[name()='power' and *[1][self::m:mi[.='e']]]]"
  replace:
  - x: "*[1]"
  - x: "*[2]"
  - pause: medium
  - x: "*[3]"

- name: coefficient-exponential
  tag: mrow
  match: "count(*)=3 and *[1][self::m:mi[.='c']] and *[2][.='\u2062'] and *[3][name()='power' and *[1][self::m:mi[.='e']]]"
  replace:
  - x: "*[1]"
  - pause: short
  - x: "*[3]"

- name: exponent-product
  tag: mrow
  match: "count(*)=3 and *[1][name()='minus' and .//m:mi[.='h']] and *[2][.='\u2062'] and *[3][name()='power'] and parent::*[name()='power']"
  replace:
  - x: "*[1]"
  - pause: short
  - x: "*[3]"

- name: set-membership-in-builder
  tag: mrow
  match: "count(*)=3 and *[2][.='∈'] and ancestor::*[self::m:set]"
  replace:
  - x: "*[1]"
  - test:
    - if: "$SpeechStyle='ClearSpeak' and $ClearSpeak_SetMemberSymbol='Belongs'"
      then:
      - pause: short
      - t: "входящих в"
    - else_if: "$SpeechStyle='ClearSpeak' and $ClearSpeak_SetMemberSymbol='Element'"
      then:
      - pause: short
      - t: "являющихся элементами"
    - else_if: "$SpeechStyle='ClearSpeak' and ($ClearSpeak_SetMemberSymbol='Member')"
      then:
      - pause: short
      - t: "принадлежащих"
    - else: [t: "из"]
  - test:
    - if: "*[3][.='ℕ']"
      then: [t: "натуральных чисел"]
    - else_if: "*[3][.='ℤ']"
      then_test:
      - if: "$SpeechStyle='ClearSpeak' and $ClearSpeak_SetMemberSymbol='Belongs'"
        then: [t: "целые числа"]
      - else_if: "$SpeechStyle='ClearSpeak' and $ClearSpeak_SetMemberSymbol='Member'"
        then: [t: "целым числам"]
      - else: [t: "целых чисел"]
    - else_if: "*[3][.='ℚ']"
      then: [t: "рациональных чисел"]
    - else_if: "*[3][.='ℝ']"
      then: [t: "действительных чисел"]
    - else: [x: "*[3]"]
  - pause: short

- name: set-builder-even-number
  tag: mrow
  match: "*[self::m:mi[.='x']] and *[self::m:mtext[contains(., 'even') and contains(., 'number')]] and ancestor::*[self::m:set]"
  replace:
  - x: "*[self::m:mtext[contains(., 'even') and contains(., 'number')]]"

- name: set-membership-under-large-op
  tag: mrow
  match: "count(*)=3 and *[2][.='∈'] and ancestor::*[self::m:large-op]"
  replace:
  - x: "*[1]"
  - test:
    - if: "$SpeechStyle='ClearSpeak' and $ClearSpeak_SetMemberSymbol='Belongs'"
      then:
      - pause: short
      - t: "входящему в"
    - else_if: "$SpeechStyle='ClearSpeak' and $ClearSpeak_SetMemberSymbol='In'"
      then: [t: "из"]
    - else_if: "$SpeechStyle='ClearSpeak' and ($ClearSpeak_SetMemberSymbol='Auto' or $ClearSpeak_SetMemberSymbol='Member')"
      then:
      - pause: short
      - t: "принадлежащему"
    - else:
      - pause: short
      - t: "являющемуся элементом"
  - test:
    - if: "*[3][.='ℤ']"
      then_test:
      - if: "$SpeechStyle='ClearSpeak' and $ClearSpeak_SetMemberSymbol='Belongs'"
        then: [t: "целые числа"]
      - else_if: "$SpeechStyle='ClearSpeak' and ($ClearSpeak_SetMemberSymbol='Auto' or $ClearSpeak_SetMemberSymbol='Member')"
        then: [t: "целым числам"]
      - else: [t: "целых чисел"]
    - else_if: "*[3][.='ℚ']"
      then: [t: "рациональных чисел"]
    - else: [x: "*[3]"]
  - pause: short

- name: set-not-member
  tag: mrow
  match: "count(*)=3 and *[2][.='∉']"
  replace:
  - x: "*[1]"
  - pause: short
  - test:
    - if: "$SpeechStyle='ClearSpeak' and $ClearSpeak_SetMemberSymbol='Belongs'"
      then: [t: "не входит в"]
    - else_if: "$SpeechStyle='ClearSpeak' and $ClearSpeak_SetMemberSymbol='Element'"
      then: [t: "не является элементом"]
    - else_if: "$SpeechStyle='ClearSpeak'"
      then: [t: "не принадлежит"]
    - else: [t: "не является элементом"]
  - test:
    - if: "*[3][.='ℝ'] and $SpeechStyle='ClearSpeak' and $ClearSpeak_SetMemberSymbol='Belongs'"
      then: [t: "действительные числа"]
    - else_if: "*[3][.='ℝ'] and $SpeechStyle='ClearSpeak' and $ClearSpeak_SetMemberSymbol!='Element'"
      then: [t: "действительным числам"]
    - else_if: "*[3][.='ℝ']"
      then: [t: "действительных чисел"]
    - else: [x: "*[3]"]

- name: probability-chain
  tag: mrow
  match: "count(*)=5 and *[1][.//m:mtext[contains(., 'and')]] and *[2][.='='] and *[3][.//m:mo[.='∩']] and *[4][.='='] and *[5][.//m:mi[.='P']]"
  replace:
  - x: "*[1]/*[1]"
  - pause: medium
  - t: "открывающая круглая скобка"
  - pause: short
  - x: "*[1]/*[3]/*[2]"
  - pause: medium
  - t: "закрывающая круглая скобка"
  - pause: medium
  - x: "*[2]"
  - pause: medium
  - x: "*[3]/*[1]"
  - pause: short
  - t: "открывающая круглая скобка"
  - pause: short
  - x: "*[3]/*[3]/*[2]"
  - pause: medium
  - t: "закрывающая круглая скобка"
  - pause: medium
  - x: "*[4]"
  - pause: short
  - x: "*[5]/*[1]/*[1]"
  - t: "от"
  - x: "*[5]/*[1]/*[3]/*[2]"
  - pause: short
  - x: "*[5]/*[3]/*[1]"
  - t: "от"
  - x: "*[5]/*[3]/*[3]/*[2]"

- name: modified-variable-product
  tag: mrow
  match: "count(*)>2 and *[1][name()='modified-variable'] and not(*[.='+'])"
  replace:
  - insert:
      nodes: "*[name()='modified-variable' or name()='mover']"
      replace: [pause: auto]

- name: modified-variable-sum
  tag: mrow
  match: "count(*)=9 and *[2][.='+'] and *[4][.='+'] and *[6][.='+'] and *[8][.='+'] and *[1][.//*[name()='modified-variable']] and *[5][.//*[name()='modified-variable']]"
  replace:
  - x: "*[1]/*[1]"
  - pause: short
  - x: "*[1]/*[3]"
  - pause: short
  - x: "*[1]/*[5]"
  - pause: short
  - x: "*[1]/*[7]"
  - pause: short
  - x: "*[1]/*[9]"
  - pause: medium
  - x: "*[2]"
  - x: "*[3]"
  - pause: medium
  - x: "*[4]"
  - x: "*[5]/*[1]"
  - pause: short
  - x: "*[5]/*[3]"
  - pause: short
  - x: "*[5]/*[5]"
  - pause: short
  - x: "*[5]/*[7]"
  - pause: short
  - x: "*[5]/*[9]"
  - pause: medium
  - x: "*[6]"
  - x: "*[7]"
  - pause: auto
  - x: "*[8]"
  - x: "*[9]"

- name: default
  tag: mrow
  match: "."
  replace:
  - insert:
      nodes: "*"
      replace:
      - test:
        - if: "(name(.)='mover' or name(.)='modified-variable' or (name(.)='mrow' and .//*[name(.)='mover' or name(.)='modified-variable'])) and
               following-sibling::*[1][.='+'] and
               following-sibling::*[2][name(.)='mover' or name(.)='modified-variable' or (name(.)='mrow' and .//*[name(.)='mover' or name(.)='modified-variable'])] and
               not(following-sibling::*[2][name(.)='vector' or (name(.)='mover' and *[2][.='→'])])"
          then: [pause: medium]
        - else_if: "self::m:mo[.='='] and following-sibling::*[1][.//m:mi[.='c']]"
          then: [pause: medium]
        - else_if: "self::m:mo[.='='] and following-sibling::*[1][.//m:mi[.='P']] and following-sibling::*[2][.='=']"
          then: [pause: medium]
        - else_if: "self::m:mo[.='='] and following-sibling::*[1][.//m:mi[.='P']]"
          then: [pause: short]
        - else_if: "name(.)='mrow' and .//m:mi[.='P'] and following-sibling::*[1][.='=']"
          then: [pause: medium]
        - else_if: "name(.)='mrow' and .//m:mi[.='P'] and following-sibling::*[1][.='\u2062'] and following-sibling::*[2][.//m:mi[.='P']]"
          then: [pause: short]
        - else_if: "self::m:mi[.='P'] and parent::*[following-sibling::*[1][.='='] and not(preceding-sibling::*[1][.='='])]"
          then: [pause: medium]
        - else_if: "self::m:mi[.='c'] and following-sibling::*[1][.='\u2062'] and
                    following-sibling::*[2][(name(.)='power' or name(.)='msup') and *[1][self::m:mi[.='e']]]"
          then: [pause: short]
        - else_if: "(name(.)='power' or name(.)='msup' or name(.)='minus') and
                    following-sibling::*[1][.='\u2062'] and following-sibling::*[2][name(.)='power' or name(.)='msup'] and
                    ancestor::*[name(.)='power' or name(.)='msup']"
          then: [pause: short]
        - else_if: "(name(.)='power' or name(.)='msup') and following-sibling::*[1][name(.)='power' or name(.)='msup'] and
                    ancestor::*[name(.)='power' or name(.)='msup']"
          then: [pause: short]
        - else_if: "self::m:mi[.='P'] and not(preceding-sibling::*[1][.='=']) and
                    ((following-sibling::*[1][IsBracketed(., '(', ')')] and following-sibling::*[2][.='=']) or
                     (following-sibling::*[1][.='\u2061'] and following-sibling::*[2][IsBracketed(., '(', ')')] and following-sibling::*[3][.='=']))"
          then: [pause: medium]
        - else_if: "IsBracketed(., '(', ')') and count(*)=3 and
                    (preceding-sibling::*[1][.='\u2061'] or preceding-sibling::*[2][self::m:mi[.='P']]) and
                    (following-sibling::*[1][self::m:mi[.='P']] or (following-sibling::*[1][.='\u2062'] and following-sibling::*[2][self::m:mi[.='P']]))"
          then: [pause: short]
        - else_if: "not(IsNode(., 'leaf') and following-sibling::*[1][IsNode(., 'leaf')]) or
                    following-sibling::*[1][self::m:mo[.='=']] or
                    (self::m:mi[contains('αβγδεζηθικλμνξοπρςστυφχψωϕ', text())] and following-sibling::*[1][.='+']) or
                    (self::m:mo[.='+'] and preceding-sibling::*[1][self::m:mi[contains('αβγδεζηθικλμνξοπρςστυφχψωϕ', text())]])"
          then: [pause: auto]

- name: default
  tag: mn
  match: "."
  replace:
  - bookmark: "@id"
  - x: "translate(., $BlockSeparators, '')"   # remove digit block separators

- name: english-and
  tag: mtext
  match: "normalize-space(.)='and' or contains(., 'and')"
  replace:
  - t: "и"

- name: english-if
  tag: mtext
  match: "normalize-space(.)='if' or contains(., 'if')"
  replace:
  - test:
      if: "ancestor::m:mtd"
      then: [pause: short]
  - t: "если"

- name: even-number-text
  tag: mtext
  match: "contains(., 'even') and contains(., 'number')"
  replace:
  - test:
      if: "$SpeechStyle='ClearSpeak'"
      then: [t: "— чётное число"]
      else: [t: "икс — чётное число"]

- name: fraction-text-terms
  tag: [mi, mtext]
  match: ".='rise' or .='run' or .='miles' or .='gallons'"
  replace:
  - test:
    - if: ".='rise'"
      then: [t: "подъём"]
    - else_if: ".='run'"
      then: [t: "длину"]
    - else_if: ".='miles'"
      then: [t: "мили"]
    - else: [t: "галлона"]

- name: perpendicular-to
  tag: mo
  match: "@intent='perpendicular-to' or .='perpendicular to'"
  replace:
  - t: "перпендикулярно"

- name: set-builder-such-that
  tag: mo
  match: ".=':' and ancestor::*[self::m:set] and preceding-sibling::*[.='ℤ' or .='ℕ' or (self::m:mrow and *[2][.='∈'])]"
  replace:
  - t: "таких что"

- name: perpendicular-to-intent-node
  tag: "*"
  match: "@intent='perpendicular-to' or .='perpendicular to' or contains(name(.), 'perpendicular')"
  replace:
  - t: "перпендикулярно"

- name: default
  tag: [mo, mtext]
  match: "."
  replace:
  - bookmark: "@id"
  - x: "text()"

- name: default
  tag: mi
  match: "."
  replace:
  - bookmark: "@id"
  - test:
    - if: "text()='perpendicular-to' or text()='perpendicular to' or text()='perpendicular_to'"
      then: [t: "перпендикулярно"]
    - else_if: "text()='A' and parent::*[self::m:mrow and IsBracketed(., '(', ')') and count(*)=3 and preceding-sibling::*[2][self::m:mi[.='P']]]"
      then: [t: "заглавной а"]
    - else_if: "text()='B' and parent::*[self::m:mrow and IsBracketed(., '(', ')') and count(*)=3 and preceding-sibling::*[2][self::m:mi[.='P']]]"
      then: [t: "заглавной бэ"]
    - else_if: "text()='e' and parent::*[self::m:power or self::m:msup][*[1][text()='e']]"
      then: [t: "е"]
    - else_if: "text()='g' and following-sibling::*[1][.='⁡' or (.='⁢' and @data-function-guess)]"
      then: [t: "же"]
    - else_if: "$SpeechStyle='SimpleSpeak' and (text()='n' or text()='k') and parent::*[self::m:mrow and count(*)=3 and *[2][.='+'] and *[3][self::m:mn]] and ancestor::*[name()='fraction']"
      then_test:
      - if: "text()='n'"
        then: [t: "эн"]
      - else: [t: "ка"]
    - else_if: "text()='n' and parent::*[self::m:mrow and parent::*[self::m:power] and count(*)>1]"
      then: [t: "эн"]
    - else_if: "(text()='n' or text()='k') and ancestor::*[name()='binomial']"
      then_test:
      - if: "text()='n'"
        then: [t: "эн"]
      - else: [t: "ка"]
    - else_if: "text()='i' and (ancestor::*[self::m:large-op] or ancestor::*[preceding-sibling::*[1][self::m:large-op or IsInDefinition(., 'LargeOperators') or .//*[self::m:large-op or IsInDefinition(., 'LargeOperators')]]] or preceding-sibling::*[1][self::m:large-op or IsInDefinition(., 'LargeOperators')])"
      then: [t: "и"]
    - else_if: "text()='n' and (ancestor::*[self::m:large-op] or ancestor::*[preceding-sibling::*[1][self::m:large-op or IsInDefinition(., 'LargeOperators') or .//*[self::m:large-op or IsInDefinition(., 'LargeOperators')]]] or preceding-sibling::*[1][self::m:large-op or IsInDefinition(., 'LargeOperators')])"
      then: [t: "эн"]
    - else_if: "text()='d' and preceding-sibling::*[1][.='⁢'] and following-sibling::*[1][.='⁢']"
      then: [t: "д"]
    - else_if: "text()='b' and parent::*[self::m:mover or self::m:modified-variable]"
      then: [t: "б"]
    - else_if: "text()='x' and ancestor::*[self::m:limit]"
      then: [t: "икс"]
    - else_if: "text()='x' and (($SpeechStyle='ClearSpeak' and ancestor::*[name()='set']) or (ancestor::*[name()='set' and not(.//*[.='∈'])] and ancestor::*[self::m:mrow and *[2][.=':']]))"
      then: [t: "икс"]
    - else_if: "text()='i' and $SpeechStyle='ClearSpeak' and ancestor-or-self::*[following-sibling::*[.='∉']]"
      then: [t: "и"]
    - else_if: "text()='i' and (parent::*[self::m:binomial or self::m:pochhammer] or (parent::*[self::m:mmultiscripts] and preceding-sibling::*) or (parent::*[self::m:indexed-by or self::m:msub or self::m:power[@data-from-mathml='msubsup']] and preceding-sibling::*) or parent::*[self::m:mrow and parent::*[self::m:indexed-by or self::m:msub or self::m:power[@data-from-mathml='msubsup']] and preceding-sibling::*])"
      then: [t: "и"]
    - else_if: "text()='j' and (parent::*[self::m:binomial or self::m:pochhammer] or (parent::*[self::m:mmultiscripts] and preceding-sibling::*) or (parent::*[self::m:indexed-by or self::m:msub or self::m:power[@data-from-mathml='msubsup']] and preceding-sibling::*) or parent::*[self::m:mrow and parent::*[self::m:indexed-by or self::m:msub or self::m:power[@data-from-mathml='msubsup']] and preceding-sibling::*])"
      then: [t: "джей"]
    - else_if: "text()='k' and (parent::*[self::m:binomial or self::m:pochhammer] or (parent::*[self::m:mmultiscripts] and preceding-sibling::*) or (parent::*[self::m:indexed-by or self::m:msub or self::m:power[@data-from-mathml='msubsup']] and preceding-sibling::*) or parent::*[self::m:mrow and parent::*[self::m:indexed-by or self::m:msub or self::m:power[@data-from-mathml='msubsup']] and preceding-sibling::*])"
      then: [t: "ка"]
    - else_if: "text()='l' and (parent::*[self::m:binomial or self::m:pochhammer] or (parent::*[self::m:mmultiscripts] and preceding-sibling::*) or (parent::*[self::m:indexed-by or self::m:msub or self::m:power[@data-from-mathml='msubsup']] and preceding-sibling::*) or parent::*[self::m:mrow and parent::*[self::m:indexed-by or self::m:msub or self::m:power[@data-from-mathml='msubsup']] and preceding-sibling::*])"
      then: [t: "эль"]
    - else_if: "text()='m' and (parent::*[self::m:binomial or self::m:pochhammer] or (parent::*[self::m:mmultiscripts] and preceding-sibling::*) or (parent::*[self::m:indexed-by or self::m:msub or self::m:power[@data-from-mathml='msubsup']] and preceding-sibling::*) or parent::*[self::m:mrow and parent::*[self::m:indexed-by or self::m:msub or self::m:power[@data-from-mathml='msubsup']] and preceding-sibling::*])"
      then: [t: "эм"]
    - else_if: "text()='n' and (parent::*[self::m:binomial or self::m:pochhammer] or (parent::*[self::m:mmultiscripts] and preceding-sibling::*) or (parent::*[self::m:indexed-by or self::m:msub or self::m:power[@data-from-mathml='msubsup']] and preceding-sibling::*) or parent::*[self::m:mrow and parent::*[self::m:indexed-by or self::m:msub or self::m:power[@data-from-mathml='msubsup']] and preceding-sibling::*])"
      then: [t: "эн"]
    - else_if: "string-length(.)=1 and contains('ABCDEFGHIJKLMNOPQRSTUVWXYZ', text()) and ancestor::*[preceding-sibling::*[1][self::m:large-op or IsInDefinition(., 'LargeOperators')]]"
      then:
      - x: "translate(text(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"
      - t: "большое"
    - else_if: "string-length(.) = 1 and text() != '_'"       # need unicode.tdl to kick in for single letter tokens
      then: [x: "text()"]
    - else_if: "@data-chem-element"                      # NavMode=Character needs this
      then: [spell: "text()", pause: "short"]
      else: [x: "translate(., '-_\u00A0', '  ')"]   # from intent literals or from extra spaces added (which get deleted)

- name: default
  tag: ms
  match: "."
  replace:
  - t: "строка"      # phrase('the string' is long)
  - pause: short
  - x: "text()"

- name: default
  tag: mstyle
  match: "."
  replace:
  - insert:
      nodes: "*"
      replace:
      - test:
        - if: "self::m:mo[.='='] and following-sibling::*[1][self::m:mi[.='c'] or .//m:mi[.='c']]"
          then: [pause: medium]
        - else_if: "self::m:mi[.='c'] and following-sibling::*[1][.='\u2062'] and
                    following-sibling::*[2][(name(.)='power' or name(.)='msup') and *[1][self::m:mi[.='e']]]"
          then: [pause: short]
        - else_if: "(name(.)='power' or name(.)='msup') and following-sibling::*[1][name(.)='power' or name(.)='msup'] and
                    ancestor::*[name(.)='power' or name(.)='msup']"
          then: [pause: short]
        - else_if: "self::m:mi[.='P'] and not(preceding-sibling::*[1][.='=']) and
                    ((following-sibling::*[1][IsBracketed(., '(', ')')] and following-sibling::*[2][.='=']) or
                     (following-sibling::*[1][.='\u2061'] and following-sibling::*[2][IsBracketed(., '(', ')')] and following-sibling::*[3][.='=']))"
          then: [pause: medium]
        - else_if: "IsBracketed(., '(', ')') and following-sibling::*[1][.='=']"
          then: [pause: medium]
        - else_if: "self::m:mo[.='='] and
                    ((following-sibling::*[1][self::m:mi[.='P']] and following-sibling::*[2][IsBracketed(., '(', ')')] and following-sibling::*[3][.='=']) or
                     (following-sibling::*[1][self::m:mi[.='P']] and following-sibling::*[2][.='\u2061'] and following-sibling::*[3][IsBracketed(., '(', ')')] and following-sibling::*[4][.='=']))"
          then: [pause: medium]
        - else_if: "self::m:mo[.='='] and following-sibling::*[1][self::m:mi[.='P']]"
          then: [pause: short]
        - else_if: "IsBracketed(., '(', ')') and count(*)=3 and
                    (preceding-sibling::*[1][.='\u2061'] or preceding-sibling::*[2][self::m:mi[.='P']]) and
                    (following-sibling::*[1][self::m:mi[.='P']] or (following-sibling::*[1][.='\u2062'] and following-sibling::*[2][self::m:mi[.='P']]))"
          then: [pause: short]


- name: literal-simple
  # don't include nested fractions. E.g, fraction a plus b over c + 1 end fraction" is ambiguous
  # by simplistic SimpleSpeak's rules "b over c" is a fraction, but if we say nested fractions
  # are never simple, then any 'over' applies only to enclosing "fraction...end fraction" pair.
  tag: mfrac
  match:
  - "(IsNode(*[1],'leaf') and IsNode(*[2],'leaf')) and"
  - "not(ancestor::*[name() != 'mrow'][1]/self::m:fraction)" # FIX: can't test for mrow -- what should be used???
  replace:
  - x: "*[1]"
  - t: "разделить на"               # phrase("the fraction x 'over' y")
  - x: "*[2]"
  - pause: short

- name: literal-default
  tag: mfrac
  match: "."
  replace:
  - t: "дробь, числитель:"              # phrase("'start'  fraction x over y end of fraction")
  - pause: short
  - x: "*[1]"
  - test:
      if: "not(IsNode(*[1],'leaf'))"
      then: [pause: short]
  - t: "знаменатель:"               # phrase("the fraction x 'over' y")
  - test:
      if: "not(IsNode(*[2],'leaf'))"
      then: [pause: short]
  - x: "*[2]"
  - pause: short
  - test:
      if: "$Impairment = 'Blindness'"
      then: [t: "конец дроби"]          # phrase("start of fraction x over y 'end over'")
  - pause: medium


# not sure what really should be said for these since we should not assume they are square roots
- name: literal-default
  tag: msqrt
  match: "."
  replace:
  - t: "квадратный корень"
  - test:
      if: "$Verbosity!='Terse'"
      then: [t: "из"]    # phrase("the root 'of' x")
  - x: "*[1]"
  - pause: short
  - test:
      if: "not(IsNode(*[1],'leaf')) or $Impairment = 'Blindness'"
      then: [t: "конец корня"] # phrase("root of x 'end root symbol'")

# not sure what really should be said for these since we should not assume they are square roots
- name: literal-default
  tag: mroot
  match: "."
  replace:
  - test:
    - if: "*[2][.='2']"
      then: [t: "квадратный корень"]
    - else_if: "*[2][.='3']"
      then: [t: "кубический корень"]
    - else:
      - t: "корень степени" # phrase("the 'root with index' 3 of 5")
      - x: "*[2]"
  - pause: short
  - t: "из"              # phrase("the root 'of' x")
  - x: "*[1]"
  - pause: short
  - test:
      if: "not(IsNode(*[1],'leaf')) or $Impairment = 'Blindness'"
      then: [t: "конец корня"] # phrase("root of x 'end root symbol'")


- name: simple-sub
  tag: indexed-by
  # invisible comma -- want "x 1 when subscript is an integer"
  match: "count(*)=2 and $Verbosity='Terse' and *[2][self::m:mn and translate(., '.,', '')=.]"
  replace:
  - x: "*[1]"
  - x: "*[2]"
  - pause: short

- name: no-end-sub
  tag: indexed-by
  match: "count(*)=2 and *[2][self::m:mrow and *[2][.='⁣']]"
  replace:
  - x: "*[1]"
  - t: "с индексом"               # phrase(x 'sub' 2)
  - x: "*[2]"
  - pause: short

- name: subscript-in-power
  tag: indexed-by
  match: "count(*)=2 and parent::*[self::m:power]"
  replace:
  - x: "*[1]"
  - t: "нижний индекс"
  - x: "*[2]"
  - pause: short

# otherwise let definitions/default infix handle it

- name: literal
  tag: msub
  match: "."
  replace:
  - x: "*[1]"
  - test:
      if: "not($Verbosity='Terse' and *[2][self::m:mn and not(translate(., '.,', '')!=.)])"  # just say "x 1" for terse vs "x sub 1"
      then: [t: "нижний индекс"]      # phrase(x 'sub' 2)
  - x: "*[2]"


- name: literal
  tag: [msup, msubsup]
  match: "."
  replace:
  - x: "*[1]"
  - test:
      if: "name(.)='msubsup'"
      then:
      - t: "нижний индекс"          # phrase(x 'sub' 2)
      - x: "*[2]"
  - test:
      if: "*[last()][translate(., '′″‴⁗†‡°*', '')='']"
      then:  [x: "*[last()]"]
      else_test:
          if: "ancestor-or-self::*[contains(@data-intent-property, ':literal:')]"  # FIX: is this test necessary?
          then:
          - t: "верхний индекс"      # phrase(x 'super' 2)
          - x: "*[last()]"
          - test:
              if: "not(IsNode(*[last()], 'simple')) or $Impairment = 'Blindness'"
              then: [t: "конец верхнего индекса"]      # phrase(x super 2 'end of super')
          else:
          - test:
              if: "$Verbosity='Verbose'"
              then: [t: "верхний индекс"]
              else: [t: "в степени"]
          - x: "*[last()]"
          - test:
              if: "$Verbosity='Verbose'"
              then: [t: "конец верхнего индекса"]
              else: [t: "конец степени"]

- name: default
  tag: munder
  match: "."
  replace:
  - test:
      if: "not(IsNode(*[1], 'leaf'))"
      then: [t: "количество"]      # phrase(phrase(x 'quantity' with y above it)
  - x: "*[1]"
  - t: "с"      # phrase(x 'with' z below it)
  - x: "*[2]"
  - t: "ниже"      # phrase(x with z 'below' it)

- name: diacriticals
  tag: mover
  match: "*[1][self::m:mi] and *[2][translate(., '\u0306\u030c.\u00A8\u02D9\u20DB\u20DC`^ˇ~→¯_', '')='']"
  replace:
  - x: "*[1]"
  - x: "*[2]"

- name: default
  tag: mover
  match: "."
  replace:
  - test:
      if: "not(IsNode(*[1], 'leaf'))"
      then: [t: "количество"]      # phrase(phrase(the 'quantity' x plus 1 with y above it)
  - x: "*[1]"
  - t: "с"         # phrase(x modified 'with' y above it)
  - x: "*[2]"
  - t: "с"        # phrase(x modified 'with' y above it)

- name: default
  tag: munderover
  match: "."
  replace:
  - test:
      if: "not(IsNode(*[1], 'leaf'))"
      then: [t: "количество"]      # phrase(the 'quantity' x plus 1 with y above it)
  - x: "*[1]"
  - t: "с"         # phrase(x modified 'with' y above it)
  - x: "*[2]"
  - t: "ниже и"    # phrase(x modified with y 'below and' y above it)
  - x: "*[3]"
  - t: "выше"        # phrase(x modified with y 'above' it)

- name: default
  #   Here we support up to 2 prescripts and up to 4 postscripts -- that should cover all reasonable cases
  #   If there are more, we just dump them out without regard to sup/super :-(
  # FIX: this could use more special cases 
  # There is (currently) no way in MathCAT to deal with n-ary arguments other than "all" ('*') or an individual entry ('*[1]').
  tag: mmultiscripts
  match: "."
  variables:
  # computing the number of postscripts is messy because of <mprescripts> being optionally present -- we use "mod" to get the count right
  - Prescripts: "m:mprescripts/following-sibling::*"
  - NumChildren: "count(*)" # need to stash this since the count is wrong inside '*[...]' below
  - Postscripts: "*[position()>1 and position() < (last() + ($NumChildren mod 2) -count($Prescripts))]"
  replace:
  - x: "*[1]"
  - test:
      if: "$Prescripts" # more common case
      then:
      - with:
          variables:
          - PreSubscript: "'левый нижний индекс'"
          - PreSuperscript: "'левый верхний индекс'"
          replace:
          - test: # only bother announcing if there is more than one prescript
              if: "count($Prescripts) > 2"
              then:
              - t: "с"      # phrase(substitute x 'with' y)
              - x: "count($Prescripts) div 2"
              - t: "индексами перед"
              - pause: short
          - test:
              if: "not($Prescripts[1][self::m:none])"
              then:
              - x: "$PreSubscript"
              - x: "$Prescripts[1]"
          - test:
              if: "not($Prescripts[1][self::m:none] or $Prescripts[2][self::m:none])"
              then: [t: "и"]      # phrase(10 is greater than 8 'and' less than 15)
          - test:
              if: "not($Prescripts[2][self::m:none])"
              then:
              - x: "$PreSuperscript"
              - x: "$Prescripts[2]"
          - pause: short
          - test:
              if: "count($Prescripts) > 2" # more common case
              then:
              - test:
                  if: "not($Prescripts[3][self::m:none])"
                  then:
                  - x: "$PreSubscript"
                  - x: "$Prescripts[3]"
              - test:
                  if: "not($Prescripts[3][self::m:none] or $Prescripts[4][self::m:none])"
                  then: [t: "и"]      # phrase(10 is grater than 8 'and' less than 15)
              - test:
                  if: "not($Prescripts[4][self::m:none])"
                  then:
                  - x: "$PreSuperscript"
                  - x: "$Prescripts[4]"
              - test:
                  if: "count($Prescripts) > 4" # give up and just dump them out so at least the content is there
                  then:
                  - t: "и далее"
                  - test:
                      if: "not($Prescripts[5][self::m:none])"
                      then:
                      - x: "$PreSubscript"
                      - x: "$Prescripts[5]"
                  - test:
                      if: "not($Prescripts[5][self::m:none] or $Prescripts[6][self::m:none])"
                      then: [t: "и"]
                  - test:
                      if: "not($Prescripts[6][self::m:none])"
                      then:
                      - x: "$PreSuperscript"
                      - x: "$Prescripts[6]"
                  - test:
                      if: "not($Prescripts[7][self::m:none])"
                      then:
                      - x: "$PreSubscript"
                      - x: "$Prescripts[7]"
                  - test:
                      if: "not($Prescripts[7][self::m:none] or $Prescripts[8][self::m:none])"
                      then: [t: "и"]
                  - test:
                      if: "not($Prescripts[8][self::m:none])"
                      then:
                      - x: "$PreSuperscript"
                      - x: "$Prescripts[8]"
  - test:
      if: "$Postscripts"
      then:
      - with:
          variables:
          - PostSubscript: "IfThenElse($Verbosity='Verbose', 'нижний индекс', 'нижний')"
          - PostSuperscript: "IfThenElse($Verbosity='Verbose', 'верхний индекс', 'верхний')"
          replace:
          - test: # only bother announcing if there is more than one postscript
              if: "count($Postscripts) > 2"
              then:
              - test:
                  if: "$Prescripts"
                  then: [pause: short, t: "и"]      # phrase(10 is greater than 8 'and' less than 15)
              - t: "с"      # phrase(substitute x 'with' y)
              - x: "count($Postscripts) div 2"
              - t: "индексами после"
              - pause: short
          - test:
              if: "not($Postscripts[1][self::m:none])"
              then:
              - x: "$PostSubscript"
              - x: "$Postscripts[1]"
          - test:
              if: "not($Postscripts[1][self::m:none] or $Postscripts[2][self::m:none])"
              then: [t: "и"]      # phrase(10 is greater than 8 'and' less than 15)
          - test:
              if: "not($Postscripts[2][self::m:none])"
              then:
              - x: "$PostSuperscript"
              - x: "$Postscripts[2]"
          - test:
              if: "count($Postscripts) > 2"
              then:
              - test:
                  if: "not($Postscripts[3][self::m:none])"
                  then:
                  - x: "$PostSubscript"
                  - x: "$Postscripts[3]"
              - test:
                  if: "not($Postscripts[3][self::m:none] or $Postscripts[4][self::m:none])"
                  then: [t: "и"]      # phrase(10 is greater than 8 'and' less than 15)
              - test:
                  if: "not($Postscripts[4][self::m:none])"
                  then:
                  - x: "$PostSuperscript"
                  - x: "$Postscripts[4]"
              - test:
                  if: "count($Postscripts) > 4"
                  then:
                  - test:
                      if: "not($Postscripts[5][self::m:none])"
                      then:
                      - x: "$PostSubscript"
                      - x: "$Postscripts[5]"
                  - test:
                      if: "not($Postscripts[5][self::m:none] or $Postscripts[6][self::m:none])"
                      then: [t: "и"]      # phrase(10 is greater than 8 'and' less than 15)
                  - test:
                      if: "not($Postscripts[6][self::m:none])"
                      then:
                      - x: "$PostSuperscript"
                      - x: "$Postscripts[6]"
                  - test:
                      if: "count($Postscripts) > 6"
                      then:
                      - test:
                          if: "not($Postscripts[7][self::m:none])"
                          then:
                          - x: "$PostSubscript"
                          - x: "$Postscripts[7]"
                      - test:
                          if: "not($Postscripts[7][self::m:none] or $Postscripts[8][self::m:none])"
                          then: [t: "и"]      # phrase(10 is less than 15 'and' greater than 5)
                      - test:
                          if: "not($Postscripts[8][self::m:none])"
                          then:
                          - x: "$PostSuperscript"
                          - x: "$Postscripts[8]"
                      - test:
                          if: "count($Postscripts) > 8" # give up and just dump them out so at least the content is there
                          then:
                          - t: "и далее"
                          - test:
                              if: "not($Postscripts[9][self::m:none])"
                              then:
                              - x: "$PostSubscript"
                              - x: "$Postscripts[9]"
                          - test:
                              if: "not($Postscripts[9][self::m:none] or $Postscripts[10][self::m:none])"
                              then: [t: "и"]
                          - test:
                              if: "not($Postscripts[10][self::m:none])"
                              then:
                              - x: "$PostSuperscript"
                              - x: "$Postscripts[10]"

- name: default
  tag: mtable
  variables: [IsColumnSilent: false()]
  match: "."
  replace:
  - t: "стол с"      # phrase(the 'table with' 3 rows)
  - x: count(*)
  - test:
      if: count(*)=1
      then: [t: "строкой"]      # phrase(the table with 1 'row')
      else: [t: "строками"]      # phrase(the table with 3 'rows')
  - t: "и "      # phrase(the table with 3 rows 'and' 4 columns)
  - x: "count(*[1]/*)"
  - test:
      if: "count(*[1]/*)=1"
      then: [t: "столбцом"]      # phrase(the table with 3 rows and 1 'column')
      else: [t: "столбцами"]      # phrase(the table with 3 rows and 4 'columns')
  - pause: long
  - x: "*"

- name: default
  # callers/context should do that.
  # this may get called from navigation -- in that case, there is no context to speak the row #, so don't do it
  tag: [mtr, mlabeledtr]
  match: "."
  replace:
  - pause: medium
  - t: "строка"      # phrase(the first 'row' of a matrix)
  - x: "count(preceding-sibling::*)+1"
  - test:
      if: .[self::m:mlabeledtr]
      then:
      - t: "с меткой"      # phrase(the line 'with label' first equation)
      - x: "*[1]/*"
      - pause: short
  - pause: medium
  - test:
      if: .[self::m:mlabeledtr]
      then: [x: "*[position()>1]"]
      else: {x: "*"}

- name: default
  tag: mtd
  match: "."
  replace:
  - test:
      #  ClearSpeak normally speaks "column 1" even though it says the row number, which is a waste...
      #  The following is commented out but the count(...)!=0 probably belongs in other rule sets
      #   if: not($IsColumnSilent) and ($ClearSpeak_Matrix = 'SpeakColNum' or count(preceding-sibling::*) != 0)
      if: "not($IsColumnSilent)"
      then:
      - t: "столбец"      # phrase(the first 'column' of the matrix)
      - x: "count(preceding-sibling::*)+1"
      - pause: medium
  - x: "*"
  - test:
    # short pause after each element; medium pause if last element in a row; long pause for last element in matrix
    - if: count(following-sibling::*) > 0
      then: [pause: short]
    - else_if: count(../following-sibling::*) > 0
      then: [pause: medium]
      else: [pause: long]


- name: empty-box
  # The ordering below is the order in which words come out when there is more than one value
  # Note: @notation can contain more than one value
  tag: menclose
  match: "@notation='box' and *[self::m:mtext and .=' ']"
  replace:
  - t: "пустое поле"      # phrase(the 'empty box' contains no values)

- name: default
  # The ordering below is the order in which words come out when there is more than one value
  # Note: @notation can contain more than one value
  tag: menclose
  match: "."
  replace:
  - test:
      if: ".[contains(concat(' ', normalize-space(@notation), ' '), ' box ')]"
      then: [t: "рамка", pause: short]      # phrase(the 'box' around the expression)
  - test:
      if: ".[contains(@notation,'roundedbox')]"
      then: [t: "скругленная рамка", pause: short]      # phrase(the 'round box' around the expression)
  - test:
      if: ".[contains(@notation,'circle')]"
      then: [t: "окружность", pause: short]      # phrase(the 'circle' around the expression)
  - test:
      if: ".[ contains(concat(' ', normalize-space(@notation), ' '), ' left ') or contains(concat(' ', normalize-space(@notation), ' '), ' right ') or contains(@notation,'top') or contains(@notation,'bottom') ]"
      then:
      - test:
          if: ".[contains(concat(' ', normalize-space(@notation), ' '), ' left ')]"
          then: [t: "линия слева", pause: short]      # phrase(line on 'left' of the expression)
      - test:
          if: ".[contains(concat(' ', normalize-space(@notation), ' '), ' right ')]"
          then: [t: "линия справа", pause: short]      # phrase(line on 'right' of the expression)
      - test:
          if: ".[contains(@notation,'top')]"
          then: [t: "линия сверху", pause: short]      # phrase(line on 'top' of the expression)
      - test:
          if: ".[contains(@notation,'bottom')]"
          then: [t: "снизу", pause: short]      # phrase(line on the 'bottom' of the expression)
  - test:
      if: ".[ contains(@notation,'updiagonalstrike') or contains(@notation,'downdiagonalstrike') or contains(@notation,'verticalstrike') or contains(@notation,'horizontalstrike') ]"
      then:
      - test:
          if: ".[contains(@notation,'updiagonalstrike') and contains(@notation,'downdiagonalstrike')]"
          then: [t: "икс", pause: short] # seems better to say 'x cross out' than 'up diagonal, down diagonal cross out'
          else:
          - test:
              if: ".[contains(@notation,'updiagonalstrike')]"
              then: [t: "диагональ вверх", pause: short]      # phrase(the line runs 'up diagonal')
          - test:
              if: ".[contains(@notation,'downdiagonalstrike')]"
              then: [t: "диагональ вниз", pause: short]      # phrase(the line runs 'down diagonal')
      - test:
          if: ".[contains(@notation,'verticalstrike')]"
          then: [t: "вертикальная", pause: short]      # phrase(the line is  'vertical')
      - test:
          if: ".[contains(@notation,'horizontalstrike')]"
          then: [t: "горизонтальная", pause: short]      # phrase(the line is 'horizontal')
      - t: "перечёркивание"      # phrase(please 'cross out' the incorrect answer)
      - pause: short
  - test:
      if: ".[contains(@notation,'uparrow')]"
      then: [t: "стрелка вверх", pause: short]      # phrase(direction is shown by the 'up arrow')
  - test:
      if: ".[contains(concat(' ', normalize-space(@notation), ' '), ' downarrow ')]"
      then: [t: "стрелка вниз", pause: short]      # phrase(the trend is shown by the 'down arrow')
  - test:
      if: ".[contains(@notation,'leftarrow')]"
      then: [t: "стрелка влево", pause: short]      # phrase(the 'left arrow' indicates going back)
  - test:
      if: ".[contains(concat(' ', normalize-space(@notation), ' '), ' rightarrow ')]"
      then: [t: "стрелка вправо", pause: short]      # phrase(the 'right arrow' indicates moving forward)
  - test:
      if: ".[contains(@notation,'northeastarrow')]"
      then: [t: "стрелка на северо-восток", pause: short]      # phrase(direction is indicated by the 'northeast arrow')
  - test:
      if: ".[contains(concat(' ', normalize-space(@notation), ' '), ' southeastarrow ')]"
      then: [t: "стрелка на юго-восток", pause: short]      # phrase(direction is shown by the 'southeast arrow')
  - test:
      if: ".[contains(concat(' ', normalize-space(@notation), ' '), ' southwestarrow ')]"
      then: [t: "стрелка на юго-запад", pause: short]      # phrase(direction is shown by the 'southwest arrow')
  - test:
      if: ".[contains(@notation,'northwestarrow')]"
      then: [t: "стрелка на северо-запад", pause: short]      # phrase(direction is shown by the 'northwest arrow')
  - test:
      if: ".[contains(@notation,'updownarrow')]"
      then: [t: "двунаправленная вертикальная стрелка", pause: short]      # phrase(upward movement is indicated by the 'double ended vertical arrow')
  - test:
      if: ".[contains(@notation,'leftrightarrow')]"
      then: [t: "двунаправленная горизонтальная стрелка", pause: short]      # phrase(progress is indicated by the 'double ended horizontal arrow')
  - test:
      if: ".[contains(@notation,'northeastsouthwestarrow')]"
      then: [t: "двунаправленная диагональная стрелка вверх", pause: short]      # phrase(trend is indicated by the 'double ended up diagonal arrow')
  - test:
      if: ".[contains(@notation,'northwestsoutheastarrow')]"
      then: [t: "двунаправленная диагональная стрелка вниз", pause: short]      # phrase(trend is indicated by the 'double ended down diagonal arrow')
  - test:
      if: ".[contains(@notation,'actuarial')]"
      then: [t: "актуарный символ", pause: short]      # phrase(the 'actuarial symbol' represents a specific quantity)
  - test:
      if: ".[contains(@notation,'madrub')]"
      then: [t: "арабский символ факториала", pause: short]      # phrase(the 'arabic factorial symbol' represents a factorial operation)
  - test:
      if: ".[contains(@notation,'phasorangle')]"
      then: [t: "угол фазы", pause: short]      # phrase(the 'phasor angle' is used to measure electrical current)
  - test:
      if: ".[contains(@notation,'longdiv') or not(@notation) or normalize-space(@notation) ='']" # default
      then: [t: "знак деления уголком", pause: short]      # phrase(the 'long division symbol' indicates  a long division calculation)
  - test:
      if: ".[contains(@notation,'radical')]"
      then: [t: "квадратный корень", pause: short]      # phrase(5 is the 'square root' of 25)
  - t: "содержащее"      # phrase(parentheses are 'enclosing' part of the equation)
  - test:
      if: "*[self::m:mtext and .=' ']"
      then: [t: "пространство"]     # otherwise there is complete silence      # phrase(there is a 'space' between the words)
      else: [x: "*"]
  - test:
      if: "$Impairment = 'Blindness' and ( $SpeechStyle != 'SimpleSpeak' or not(IsNode(*[1], 'leaf')) )"
      then: [t: "конец"]      # phrase(reached the 'end enclosure' point)
  - pause: short

- name: semantics
  tag: "semantics"
  match: "*[@encoding='MathML-Presentation']"
  replace:
  - x: "*[@encoding='MathML-Presentation']/*[1]"

- name: semantics-default
  tag: "semantics"
  match: .
  replace:
  - x: "*[1]"

- name: apply-function
  tag: "apply-function"
  match: .
  replace:
  - x: "*[1]"
  - t: "от"      # phrase(the function sine 'applied to' x plus y)
  - x: "*[2]"


# Here are the intent hints that need to be handled: 'prefix' | 'infix' | 'postfix' | 'function' | 'silent'
- name: silent-intent
  # uncaught intent -- the args have been inserted in the order of speech 
  tag: "*"
  match: "count(*)>0 and (contains(@data-intent-property, ':silent:') or translate(name(.), '-_', '')='')"
  replace:
  - x: "*"
  - test:
      if: "IsNode(., '2D')"
      then: [pause: short]
      else: [pause: auto]

- name: nofix-intent
  # uncaught intent -- the args have been inserted in the order of speech 
  tag: "*"
  match: "contains(@data-intent-property, ':nofix:') "
  replace:
  - x: "SpeakIntentName(name(.), $Verbosity, 'nofix')"

- name: prefix-intent
  # uncaught intent -- the args have been inserted in the order of speech 
  tag: "*"
  match: "count(*)>0 and contains(@data-intent-property, ':prefix:')"
  replace:
  - x: "SpeakIntentName(name(.), $Verbosity, 'prefix')"
  - x: "*"
  - test:
      if: "not( IsBracketed(., '', '') or IsNode(*[last()], 'simple') )"
      then: [x: "GetBracketingIntentName(name(.), $Verbosity, 'prefix', 'end')"]
  - test:
      if: "IsNode(., '2D')"
      then: [pause: short]
      else: [pause: auto]

- name: postfix-intent
  # uncaught intent -- the args have been inserted in the order of speech 
  tag: "*"
  match: "count(*)>0 and contains(@data-intent-property, ':postfix:')"
  replace:
  - test:
      if: "$Impairment = 'Blindness' and not( IsBracketed(., '', '') or IsNode(*[1], 'simple') )"
      then: [x: "GetBracketingIntentName(name(.), $Verbosity, 'postfix', 'start')"]
  - x: "*"
  - x: "SpeakIntentName(name(.), $Verbosity, 'postfix')"

- name: infix-intent
  # uncaught intent -- the args have been inserted in the order of speech 
  tag: "*"
  match: "count(*)>0 and contains(@data-intent-property, ':infix:')"
  replace:
  - test:
      if: "$Impairment = 'Blindness' and not( IsBracketed(., '', '') or IsNode(*[1], 'simple') )"
      then: [x: "GetBracketingIntentName(name(.), $Verbosity, 'infix', 'start')"]
  - test:
      if: "count(*) = 1"  # in cases such as continued-row, plus/minus might have just one child
      then:
      - x: "SpeakIntentName(name(.), $Verbosity, 'infix')"
      - pause: auto
      - x: "*[1]"
      else:
      - insert:
          nodes: "*"
          replace: [x: "SpeakIntentName(name(.), $Verbosity, 'infix')", pause: auto]
  - test:
      if: "$Impairment = 'Blindness' and not( IsBracketed(., '', '') or IsNode(*[last()], 'simple') )"
      then: [x: "GetBracketingIntentName(name(.), $Verbosity, 'infix', 'end')"]
  - test:
      if: "IsNode(., '2D')"   # add (probably) a slightly longer pause if this came from a 2D node
      then: [pause: short]
      else: [pause: auto]

- name: function-intent
  # uncaught intent -- speak as foo of arg1 comma arg2 .... The MathML spec requires arguments to functions
  tag: "*"
  match: "count(*)>0"
  replace:
  - x: "SpeakIntentName(name(.), $Verbosity, 'function')"
  - test:
      if: "$Verbosity != 'Terse' and not(contains(@data-intent-property, ':literal:')) and
           not(count(*)=2 and (IsInDefinition(*[1], 'TrigFunctionNames') or IsInDefinition(name(.), 'TerseFunctionNames')) and IsNode(*[2], 'simple'))"
      then: [t: "от", pause: auto]      # phrase(sine 'of' 5)
  - insert:
      nodes: "*"
      replace:
      - test:
          if: "not(contains(@data-intent-property, ':literal:'))"
          then: [x: "','"]
      - pause: auto
  - test:
      # speak "end ..." if not bracketed or last child is not simple and not last node
      if: "$Impairment = 'Blindness' and not(*[last()][IsBracketed(., '', '') or IsNode(., 'simple')] )"
      then: [x: "GetBracketingIntentName(name(.), $Verbosity, 'function', 'end')"]
  - test:
      if: "IsNode(., '2D')"
      then: [pause: short]
      else: [pause: auto]

- name: perpendicular-to
  tag: "*"
  match: "contains(name(.), 'perpendicular')"
  replace:
  - t: "перпендикулярно"

- name: default-text
  # unknown leaf -- just speak the text -- could be a literal intent
  tag: "*"
  match: "."
  replace:
  - x: "translate(name(), '-_', ' ')"
