Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions Rules/Nemeth/Nemeth_Rules.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@
tag: mrow
variables:
- RowStart: "*[1]"
- RowEnd: "DEBUG(*[3])"
- RowEnd: "*[3]"
match:
- "*[2][self::m:mtable] and"
- (IsBracketed(., '(', ')') or IsBracketed(., '[', ']') or IsBracketed(., '|', '|'))
Expand All @@ -230,9 +230,9 @@
match: "."
replace:
- test:
if: "preceding-sibling::*"
then: [t: "⠀"]
- t: "⠠"
if: "count(parent::*) > 1"
then: [t: "⠠"]
- t: ""
- x: $RowStart
- test:
if: .[self::m:mlabeledtr]
Expand All @@ -243,7 +243,9 @@
if: .[self::m:mlabeledtr]
then: [x: "*[position()>1]"]
else: {x: "*"}
- t: "⠠"
- test:
if: "count(parent::*) > 1"
then: [t: "⠠"]
- x: $RowEnd
-
name: default
Expand Down
18 changes: 11 additions & 7 deletions Rules/Nemeth/unicode.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2179,9 +2179,9 @@
# test if first ancestor that isn't an mrow is a script tag (rule 78)
- if: "self::m:mn"
then: [t: "⠠"]
- else_if: "ancestor-or-self::*[not(parent::m:mrow)][1][parent::m:msub or DEBUG(parent::m:msup )or parent::m:msubsup][preceding-sibling::*]"
- else_if: "ancestor-or-self::*[not(parent::m:mrow)][1][parent::m:msub or parent::m:msup or parent::m:msubsup][preceding-sibling::*]"
then: [t: "⠪"] # Rule 78
else: [t: "⠠⠀"]
else: [t: ","] # ',' used for matching purposes, converted to "⠠⠀"
- "-": # 0x002D (Hyphen) (0x2212 normalized to here)
- test:
if: "self::m:mtext"
Expand All @@ -2190,9 +2190,9 @@

- ".": # 0x002E (Full stop or decimal pt)
- test:
if: "DEBUG(self::m:mn)"
if: "self::m:mn"
then_test:
if: "DEBUG(string-length(text()) = 1)"
if: "string-length(text()) = 1"
then: [t: "𝑁⠨"] # example 8c(4) -- lone "." is not considered numeric, but not a period
else: [t: "N⠨"]
else: [t: "P⠲"] # period
Expand All @@ -2210,7 +2210,11 @@
- "^": [t: "⠸⠣"] # 0x005E (Circumflex accent)
- "_": [t: ""] # 0x005F (Low line)
- "{": [t: "⠨⠷"] # 0x007B (Left curly bracket)
- "|": [t: "⠳"] # 0x007C (Vertical line)
- "|": # 0x007C (Vertical line)
- test:
if: "preceding-sibling::* and following-sibling::*"
then: [t: "⠀⠳⠀"] # comparison (e.g., such that -- rule 145)
else: [t: "⠳"] # absolute value, others???
- "}": [t: "⠨⠾"] # 0x007D (Right curly bracket)
- "~": [t: "⠈⠱"] # 0x007E (Tilde)
- "¢": [t: "⠈⠉"] # 0x00A2 (Cent sign)
Expand Down Expand Up @@ -2446,8 +2450,8 @@
- "∟": [t: "⠫⠪⠨⠗⠻"] # 0x221F (Right angle)
- "∠": [t: "⠫⠪"] # 0x2220 (Angle)
- "∡": [t: "⠫⠪⠈⠫⠁⠻"] # 0x2221 (Measured angle)
- "∣": [t: "⠀⠳⠀"] # 0x2223 (Divides)
- "∤": [t: "⠀⠌⠳⠀"] # 0x2224 (Does not divide)
- "∣": [t: "⠳"] # 0x2223 (Divides)
- "∤": [t: "⠌⠳"] # 0x2224 (Does not divide)
- "∥": [t: "⠀⠫⠇⠀"] # 0x2225 (Parallel to)
- "∦": [t: "⠀⠌⠫⠇⠀"] # 0x2226 (Not parallel to)
- "∧": [t: "⠈⠩"] # 0x2227 (Logical AND)
Expand Down
60 changes: 53 additions & 7 deletions src/canonicalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,14 @@ pub fn canonicalize(mathml: Element) -> Element {
struct CanonicalizeContext {
}

#[derive(PartialEq)]
#[allow(non_camel_case_types)]
enum DigitBlockType {
None,
DecimalBlock_3,
BinaryBlock_4,
}

impl CanonicalizeContext {
fn new() -> CanonicalizeContext {
return CanonicalizeContext{}
Expand Down Expand Up @@ -443,12 +451,22 @@ impl CanonicalizeContext {
return mathml;
}

fn is_digit_block(mathml: Element) -> bool {
fn is_digit_block(mathml: Element) -> DigitBlockType {
// returns true if an 'mn' with exactly three digits
lazy_static! {
static ref IS_DIGIT_BLOCK: Regex = Regex::new(r"^\d\d\d$").unwrap(); // only Unicode whitespace
static ref IS_DIGIT_BLOCK: Regex = Regex::new(r"^\d\d\d$").unwrap();
static ref IS_BINARY_DIGIT_BLOCK: Regex = Regex::new(r"^[01]{4}$").unwrap();
}
if name(&mathml) == "mn" {
let text = as_text(mathml);
if IS_DIGIT_BLOCK.is_match(text) {
return DigitBlockType::DecimalBlock_3;
}
if IS_BINARY_DIGIT_BLOCK.is_match(text) {
return DigitBlockType::BinaryBlock_4;
}
}
return name(&mathml) == "mn" && IS_DIGIT_BLOCK.is_match(as_text(mathml));
return DigitBlockType::None;
}

fn merge_number_blocks<'a>(mrow: Element<'a>) -> Element<'a> {
Expand All @@ -459,6 +477,8 @@ impl CanonicalizeContext {
let mut i = 0;
while i < children.len() {
let child = as_element(children[i]);
let mut is_comma = false;
let mut is_decimal_pt = false;
if name(&child) == "mn" {
let mut looking_for_separator = true;
let mut end = children.len() - i;
Expand All @@ -467,14 +487,28 @@ impl CanonicalizeContext {
let sibling_name = name(&sibling);
// FIX: generalize to more types of spacing (e.g., mtext with space)
// FIX: generalize to include locale ("." vs ",")
if looking_for_separator {
if sibling_name == "mo" {
let leaf_text = as_text(sibling);
is_comma = leaf_text == ",";
is_decimal_pt = leaf_text == ".";
} else {
is_comma = false;
is_decimal_pt = false;
}
};
println!("j/name={}/{}, looking={}, is ',' {}, '.' {}, ",
i+j, sibling_name, looking_for_separator, is_comma, is_decimal_pt);
if !(looking_for_separator &&
(sibling_name == "mspace" || (sibling_name == "mo" && as_text(sibling) == ","))) &&
(looking_for_separator || !is_digit_block(sibling)) {
end = j;
(sibling_name == "mspace" || is_comma || is_decimal_pt)) &&
( looking_for_separator ||
!(is_decimal_pt || is_digit_block(sibling) != DigitBlockType::None)) {
end = j+1;
break;
}
looking_for_separator = !looking_for_separator;
}
println!("start={}, end={}", i, i+end);
if is_likely_a_number(mrow, i, i+end) {
merge_block(mrow, i, i+end);
children = mrow.children(); // mrow has changed, so we need a new children array
Expand All @@ -497,6 +531,18 @@ impl CanonicalizeContext {
}
if name(&as_element(children[start+1])) == "mspace" ||
IS_WHITESPACE.is_match(as_text(as_element(children[start+1]))) {
// make sure all the digit blocks are of the same type
let mut digit_block = DigitBlockType::None; // initial "illegal" value (we know it is not NONE)
for child in children {
let child = as_element(child);
if name(&child) == "mn" {
if digit_block == DigitBlockType::None {
digit_block = is_digit_block(child);
} else if is_digit_block(child) != digit_block {
return false; // differing digit block types
}
}
}
return true; // digit block separated by whitespace
}

Expand All @@ -514,7 +560,7 @@ impl CanonicalizeContext {
}
let parent = parent.element().unwrap();
if name(&parent) != "mrow" {
// if parent is not an mrow, then there aren't parens around this
// if parent is not an mrow, then there aren't parens around this
return true;
}
let preceding = parent.preceding_siblings();
Expand Down
17 changes: 12 additions & 5 deletions src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub fn speak_mathml(mathml_str: &str) -> String {
let package = package.unwrap();
cleanup_mathml(&package);
let mathml = get_element(&package);
return crate::speech::speak_mathml(&mathml);
return crate::speech::speak_mathml(mathml);
}

/// Given MathML, a Unicode braille string is return.
Expand All @@ -64,7 +64,7 @@ pub fn braille_mathml(mathml_str: &str) -> String {
let package = package.unwrap();
cleanup_mathml(&package);
let mathml = get_element(&package);
return crate::speech::braille_mathml(&mathml);
return crate::speech::braille_mathml(mathml);
}

thread_local!{
Expand Down Expand Up @@ -108,7 +108,7 @@ pub fn GetSpokenText(_py: Python) -> PyResult<String> {
return MATHML_INSTANCE.with(|package_instance| {
let package_instance = package_instance.borrow();
let mathml = get_element(&*package_instance);
let speech = crate::speech::speak_mathml(&mathml);
let speech = crate::speech::speak_mathml(mathml);
eprintln!("Time taken: {}ms", instant.elapsed().as_millis());
return Ok( speech );
});
Expand Down Expand Up @@ -196,8 +196,15 @@ fn set_speech_tags(pref_manager: &mut PreferenceManager, speech_tags: String ) -
/// Get the braille associated with the MathML that was set by [`SetMathML`].
/// The braille returned depends upon the preference for braille output.
pub fn GetBraille(_py: Python) -> PyResult<String> {
// FIX: not yet implemented (basically what the braille says)
return Ok("⠠⠃⠗⠁⠊⠇⠇⠑ ⠛⠑⠝⠑⠗⠁⠞⠊⠕⠝ ⠝⠕⠞ ⠽⠑⠞ ⠊⠍⠏⠇⠑⠍⠑⠝⠞".to_string());
use std::time::{Instant};
let instant = Instant::now();
return MATHML_INSTANCE.with(|package_instance| {
let package_instance = package_instance.borrow();
let mathml = get_element(&*package_instance);
let braille = crate::speech::braille_mathml(mathml);
eprintln!("Time taken: {}ms", instant.elapsed().as_millis());
return Ok( braille );
});
}

#[pyfunction]
Expand Down
68 changes: 34 additions & 34 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,47 +46,47 @@ fn main() {
// let logger = builder.build().unwrap();
// info!(logger, "Hello World!");

// let expr = "
// <math display='block' xmlns='http://www.w3.org/1998/Math/MathML'>
// <mrow>
// <mrow><mo>[</mo>
// <mtable>
// <mtr>
// <mtd>
// <mn>3</mn>
// </mtd>
// <mtd>
// <mn>1</mn>
// </mtd>
// <mtd>
// <mn>4</mn>
// </mtd>
// </mtr>
// <mtr>
// <mtd>
// <mn>0</mn>
// </mtd>
// <mtd>
// <mn>2</mn>
// </mtd>
// <mtd>
// <mn>6</mn>
// </mtd>
// </mtr>
// </mtable>
// <mo>]</mo></mrow></mrow>
// </math>
// ";
let expr = "
<math display='block' xmlns='http://www.w3.org/1998/Math/MathML'>
<mrow>
<mrow><mo>[</mo>
<mtable>
<mtr>
<mtd>
<mn>3</mn>
</mtd>
<mtd>
<mn>1</mn>
</mtd>
<mtd>
<mn>4</mn>
</mtd>
</mtr>
<mtr>
<mtd>
<mn>0</mn>
</mtd>
<mtd>
<mn>2</mn>
</mtd>
<mtd>
<mn>6</mn>
</mtd>
</mtr>
</mtable>
<mo>]</mo></mrow></mrow>
</math>
";

// let expr = "
// <math xmlns='http://www.w3.org/1998/Math/MathML'>
// <mi>log</mi><mo>&#x2061;</mo><mrow><mo>(</mo><mrow><mi>x</mi><mo>+</mo><mi>y</mi></mrow><mo>)</mo></mrow>
// <mo>+</mo>
// <mi>f</mi><mo>&#x2061;</mo><mrow><mo>(</mo><mrow><mi>x</mi><mo>+</mo><mi>y</mi></mrow><mo>)</mo></mrow>
// </math>"";
let expr = "<math><mi>c</mi><mo>=</mo><mn>4</mn><mspace width=\"thinmathspace\"></mspace><mn>598</mn>
<mspace width=\"thinmathspace\"></mspace><mn>037</mn>
<mspace width=\"thinmathspace\"></mspace><mn>234</mn></math>";
// let expr = "<math><mi>c</mi><mo>=</mo><mn>4</mn><mspace width=\"thinmathspace\"></mspace><mn>598</mn>
// <mspace width=\"thinmathspace\"></mspace><mn>037</mn>
// <mspace width=\"thinmathspace\"></mspace><mn>234</mn></math>";
// let expr = "<math><mn>𝟏𝟐𝟑</mn></math>";
// let expr = "<math><mtext>A</mtext><mo>=</mo><mn>00</mn><mo>,</mo><mtext>B</mtext><mo>=</mo>
// <mn>01</mn><mo>,</mo><mo>…</mo><mo>,</mo><mtext>Z</mtext><mo>=</mo><mn>25</mn></math>";
Expand Down
Loading