diff --git a/Rules/Languages/en/definitions.yaml b/Rules/Languages/en/definitions.yaml index 8bb43d7f3..dfd707341 100644 --- a/Rules/Languages/en/definitions.yaml +++ b/Rules/Languages/en/definitions.yaml @@ -1,7 +1,7 @@ --- - include: "../../definitions.yaml" -# If an "intent" is used, the 'terse:medium:verbose' speech for the intent name is given here for a prefix||infix||postfix||function fixity +# If an "intent" is used, the 'terse:medium:verbose' speech for the intent name is given here for a prefix||infix||postfix||function||nofix||silent fixity # If only one ":" is used, the first part is used for 'terse' and the second part is used for 'medium' and 'verbose' # If no ":"s are used, the same speech is used for all forms # If bracketing words make sense, they are separated with ";"s @@ -10,45 +10,303 @@ # for readability, spaces can be used around any of the delimiter characters # Note: if there are multiple fixities, the first one is used if the fixity is not given in the intent - IntentMappings: { - "indexed-by": "infix= ; sub; end sub: end sub: end subscript", - "modified-variable": "silent= ", - "say-super": "infix=super: superscript: superscript", # used with 'mo' for superscripts (e.g, "<") - "skip-super": "silent=", # used with 'mo' for superscripts (e.g, "*") - - "absolute-value": "function= ; absolute value: the absolute value: the absolute value; end absolute value", "binomial": "infix=binomial; choose; end binomial", - "dimension-product": "infix=by", + + ### Functions and Inverses # "closed-interval": "other=closed-interval; from,to; end closed-interval", + # "closed-interval":"function=closed interval between; and", #NOTE: Check test, does not follow this pattern + #"closed-open-interval":"function=interval between; included and", + #"open-closed-interval":"function=interval between; and included", + #"open-interval":"function=open interval between; and", + "inverse":"function=inverse || postfix=inverse", + + "domain": "function= ; domain", + "codomain": "function= ; codomain", + + "image":"function=image", + #"fraction":"function=fraction; over; end fraction", # NOTE: Fails + "mixed-fraction":"infix=and", # NOTE: in website says function, but follow infix speech pattern. + "quotient":"function=integer part; divided by", # NOTE: Logic somewhere here failing, becomes "divided by of x comma, y" instead of "integer part of x divided by y" + "evaluated-at":"infix=evaluated at", + "remainder":"function=the remainder; divided by", + + "max":"function=max", + "min":"function=min", + + "power":"infix=to the power", + "root":"function=root", + "greatest-common-divisor": "function=gcd: the gcd: the greatest common divisor", + "least-common-multiple":"function=lcm: the lcm: the least common multiple", # In webpage typo "lest common" + + "absolute-value": "function= ; absolute value: the absolute value: the absolute value; end absolute value", + "complex-conjugate":"function=complex conjugate", + "complex-arg":"function=arg", + "real-part": "function=the real part", "imaginary-part": "function=imaginary part: the imaginary part: the imaginary part", - "least-common-multiple": "function=lcm: the lcm: the least common multiple", + + "polar-coordinate":"function=polar coordinate; comma", + "spherical-coordinate":"function=spherical coordinate; comma; comma", + "cartesian-coordinate":"function=cartesian coordinate; comma", + "coordinate":"function=coordinate; comma", + "floor":"function=floor", + "ceiling":"function=ceiling", + "round":"function=rounded-value", + "fractional-part":"function=fractional part", + + + ### Calculus + # "definite-integral":"function=integral over || function=integral from; to", # Property ??? + # "derivative":"function=the derivative; with respect to", # Property ??? + # "partial-derivative":"function=partial", ## Note, included with infix, but separately under calculus tab has ??? for functionality + + "limit": "prefix=limit as", + "tends-to":"infix=tends to", + "tends-to-from-above":"infix=tends to from above", + "tends-to-from-below":"infix=tends to from below", + + + ### Sets + "set": "function= ; set: the set", + "set-difference":"function=set difference; and || infix=minus", # NOTE: not tested + "complement":"function=complement", + #"empty-set":"nofix=empty set", + "cardinality":"function=cardinality", # NOTE: does not have a defined speech template in website + "list":"function=list", + "tuple": "function= ; tuple: the tuple", + + + ### Sequence and Series + "sum":"function= ; sum over : sum ; ", #: sum over : sum from; to", + "product":"function=product || function=product over || function=product from; to", + + + ### Elementary classical functions + "sine":"function=sin: sine", + "cosine":"function=cos: cosine", + "tangent":"function=tan: tangent", + "secant":"function=seech: secant", + "cosecant":"function=co-seech: cosecant", + "cotangent":"function=co-tan: cotangent", + + "arcsine":"function=arcsine", + "arccosine":"function=arccosine", + "arctangent":"function=arctangent", + "arcsecant":"function=arcsecant", + "arccosecant":"function=arc-cosecant", + "arccotangent":"function=arc-cotangent", + + "hyperbolic-sine":"function=shine", + "hyperbolic-cosine":"function=cosh", + "hyperbolic-tangent":"function=tanch", + "hyperbolic-secant":"function=sech", + "hyperbolic-cosecant":"function=cosech", + "hyperbolic-cotangent":"function=coth", + + "arc-hyperbolic-sine":"function=arc shine", + "arc-hyperbolic-cosine":"function=arc cosh", + "arc-hyperbolic-tangent":"function=arc tanch", + "arc-hyperbolic-secant":"function=arc sech", + "arc-hyperbolic-cosecant":"function=arc cosech", + "arc-hyperbolic-cotangent":"function=arc coth", + + "exponential":"function=exponential", + "natural-logarithm": "function=l n: natural log: natural log", + "logarithm":"function=log", ##Check arity 2 + + + ### Statistics and Probability + "mean":"function=mean", + "standard-deviation":"function=standard deviation", + "variance":"function=variance", + "median":"function=median", + "mode":"function=mode", + + "conditional-probability":"function=probability; given", # NOTE: Check test + + + ### Linear Algebra + "vector": "function= ; vector || prefix=vector", # prefix not tested, also prefix not on webpage + "matrix":"function=matrix", # NOTE: Failing test, recheck + "determinant":"function=determinant", + "adjugate":"function=adjugate", + "magnitude":"function=magnitude", + "norm": "function=; norm: norm: norm; end norm", + "span":"function=span", + + "unit-vector":"prefix=unit vector", + + "identity-matrix":"nofix=identity matrix", # NOTE: no function specified + "transpose":"function=transpose || postfix=transpose", # postfix needs testing + "dimensional-product":"infix=by", # INFIX + + + ### Constants and Sets + "set-of-integers":"nofix=ℤ: set of all integers", + "set-of-reals":"nofix=ℝ: set of all real numbers", + "set-of-rationals":"nofix=ℚ: set of all rational numbers", + "set-of-natural-numbers":"nofix=ℕ: set of all natural numbers", + "set-of-complex-numbers":"nofix=ℂ: set of all complex numbers", + "set-of-primes":"nofix=ℙ: set of all prime numbers", + + + ### Geometry + "line-segment":"prefix=line segment", + "directed-line-segment":"prefix=directed line segment", + "line":"prefix=line", + "ray":"prefix=ray", + "arc":"prefix=arc", + + "length":"function=length", + "area":"function=area", + + "point":"prefix=point", ## NOTE: Has ??? for property in site. Should it be prefix? Or something else. + + ### Separators + "time-separator":"infix=", + + ### General Concepts + "fenced-group":"function=fenced-group", # appears both under general concepts and grouping + # NOTE: in site mentions "the pair x and y", due to being defined as function, needs the "of" keyword + "ordered-pair": "function= ; the pair; and", # Needs to be tested, test converts "and" to "comma," + #"indexed-by": "infix= ; sub; end sub: end sub: end subscript", + "indexed-by": "infix= ; indexed by; ", + + "highlight":"postfix=highlighted", + "least-common-denominator":"function=least common denominator", + "rate":"infix=per", + "translation":"function= translation by; comma", # NOTE: not tested, changes "translation" -> "comma" in test + "constraint":"infix= ; with constraint; ", + + "binomial-coefficient":"infix=choose", + "pochhammer":"function=permutation", + "permutation-cycle":"function=permutation cycle", + "embellished-name":"infix=with annotation", + + ### Grouping + "annotation":"infix= ; which is ;", # NOTE: Follows the same order as indexed-by, in site listed as function. Should it be infix? + "braced-group":"function=grouped; end grouped", # NOTE: not tested, site is missing "of" keyword function introduces + #"repeating-decimal":"function=repeating decimal", # NOTE: BREAKS TEST. Check again. Site is missing "of" keyword function introduces. + + + ### Other + ## Default fixity function + "curl": "function=curl", + "divergence": "function=divergence", + "gradient": "function=gradient", + "laplacian": "function=laplacian", + + ## Default fixity prefix + "angle": "prefix=angle", + "angle-measure": "prefix=angle measure", + "change": "prefix=change in", + "for-all": "prefix=for all", + "measured-angle": "prefix=measured angle", + "not": "prefix=not", + "number-of": "prefix=number of", + "partial-derivative": "prefix=partial", + "right-angle": "prefix=right angle", + "square-root-of": "prefix=square root of", + "there-does-not-exist": "prefix=there does not exist", + "there-exists": "prefix=there exists", + + + ## Default fixity infix + "and": "infix=and", + "applied-to": "infix=applied to", + "approximately": "infix=approximately", + "congruent": "infix=congruent to", + "cartesian-product": "infix=cartesian product", + "composed-with": "infix=composed with", + "cross-product": "infix=cross: cross product: cross product", + "defined-as": "infix=defined as", + "divided-by": "infix=divided by", + "divides": "infix=divides", + "does-not-belong-to": "infix=does not belong to", + "does-not-divide": "infix=does not divide", + "dot-product": "infix=dot product", + "downwards-diagonal-ellipsis": "infix=downwards diagonal ellipsis", + "direct-product": "infix=direct product", + "element-of": "infix=element of", + "ellipsis": "infix=ellipsis", + "equals": "infix=equals", + "equivalent-to": "infix=equivalent to", + "evaluates-to": "infix=evaluates to", + "given": "infix=given", + "greater-than": "infix=greater than", + "greater-than-or-equal-to": "infix=greater than or equal to", + "identically-equals": "infix=identically equals", + "if-and-only-if": "infix=if and only if", + "implies": "infix=implies", + "inner-product": "infix=inner product", + "intersection": "infix=intersection", + "less-than": "infix=less than", + "less-than-or-equal-to": "infix=less than or equal to", + "list-separator": "infix=comma", + "maps-to": "infix=maps to", + "member-of": "infix=member of", + "minus-or-plus": "infix=minus or plus", + "not-subset": "infix=not subset of", + "not-superset": "infix=not superset of", + "not-equal-to": "infix=not equal to", + "not-member-of": "infix=not member of", + "not-parallel-to": "infix=not parallel to", + "obtained-from": "infix=obtained from", + "or": "infix=or", + "outer-product": "infix=outer product", + "parallel-to": "infix=parallel to", + "perpendicular": "infix=perpendicular to", + "plus": "infix=plus || prefix=positive", # Prefix not tested + "minus": "infix=minus || prefix=negative", # Prefix not tested + "plus-or-minus": "infix=plus or minus", + "precedes": "infix=precedes", + "proportional": "infix=proportional to", + "range-separator": "infix=through", + "ratio": "infix=ratio", + "similar": "infix=similar to", + "subset": "infix=subset of", + "subset-or-equal": "infix=subset or equal to", + "succeeds": "infix=succeeds", + "such-that": "infix=such that", + "superset": "infix=superset of", + "superset-or-equal": "infix=superset or equal to", + "tilde": "infix=tilde", + "times": "infix=times", + "union": "infix=union", + "upwards-diagonal-ellipsis": "infix=upwards diagonal ellipsis", + "vertical-ellipsis": "infix=vertical ellipsis", + "xor": "infix=exclusive or", + + ## Default fixity postfix + "factorial": "postfix=factorial", + "percent": "postfix=percent", + + ## Default fixity nofix + "diameter":"nofix=d: diameter", + "distance":"nofix=d; D: distance", + "probability":"nofix=P: probability", + "radius":"nofix=r: radius", + "volume":"nofix=V: volume || function=volume", + "exponential-e":"nofix=e", + "imaginary-i":"nofix=i", + "differential-d":"nofix=d", + "golden-ratio":"nofix=golden ratio", + + + ## Other : Not tested, don't appear in https://w3c.github.io/mathml-docs/intent-core-concepts/ + "modified-variable": "silent= ", + "say-super": "infix=super: superscript: superscript", # used with 'mo' for superscripts (e.g, "<") + "skip-super": "silent=", # used with 'mo' for superscripts (e.g, "*") # "large-op": "infix=over || other=from,to", - "limit": "prefix=limit as: the limit as: the limit as", "lim-sup": "prefix=lim sup as: the limit superior as: the limit superior as", "lim-inf": "prefix=lim inf as: the limit inferior as : the limit inferior as", "logarithm-with-base": "prefix=log base: the log base: the log base", - "natural-logarithm": "function=l n: natural log: natural log", - "minus": "infix=minus || prefix=negative", - "plus": "infix=plus || prefix=positive", # "pochhammer": "infix=permutations of", # arguments are in reverse order, so can't work here - "real-part": "function=the real part", - "set-of-integers": "nofix=set of all integers", - - "transpose": "postfix=transpose || function=transpose", - "norm": "function=; norm: norm: norm; end norm", "trace": "function= ; trace : trace: the trace; end trace", "dimension": "function=; dimension : dimension: the dimension; end dimension", "homomorphism": "function= ; homomorphism : homomorphism: the homomorphism; end homomorphism", "kernel": "function= ; kernel : kernel: the kernel; end kernel", - "vector": "function= ; vector || prefix=vector", - "cross-product": "infix=cross: cross product: cross product", - "dot-product": "infix=dot: dot product: dot: dot product", - - "divergence": "function= ; dihv: divergence: divergence; end divergence", - "curl": "function= ; curl; end curl", - "gradient": "function= ; del: gradient: gradient; end gradient", - "laplacian": "function=lahplahsian", # speech engines don't do a good job with "laplacian" - + "chemistry-concentration": "function= ; concentration: concentration of: the concentration of; end concentration", } diff --git a/tests/Languages/en/definitions.rs b/tests/Languages/en/definitions.rs new file mode 100644 index 000000000..6680b80c5 --- /dev/null +++ b/tests/Languages/en/definitions.rs @@ -0,0 +1,1026 @@ +/// Tests for rules in definitions: +/// * modified var +use crate::common::*; +use anyhow::Result; + +#[test] +fn tuple_basic() -> Result<()> { + // function + let expr = r#" + + + x + y + + + "#; + + test("en", "ClearSpeak", expr, "the tuple of x comma, y")?; + test("en", "SimpleSpeak", expr, "the tuple of x comma, y")?; + + return Ok(()); +} + +#[test] +fn my_set_basic() -> Result<()> { + let expr = r#" + + + x + y + + + "#; + + test("en", "ClearSpeak", expr, "the set of x comma, y")?; + + Ok(()) +} + +#[test] +fn fixed_test() -> Result<()> { + let expr = r#" + + R + + + "#; + + test("en", "ClearSpeak", expr, "set of all real numbers")?; + Ok(()) +} + +#[test] +fn i_test() -> Result<()> { + let expr = r#" + + i + + + "#; + + test("en", "ClearSpeak", expr, "i")?; + Ok(()) +} + + +#[test] +fn floor_basic() -> Result<()> { + let expr = r#" + + + x + + + "#; + + test("en", "ClearSpeak", expr, "floor of x")?; + + Ok(()) +} + +#[test] +fn set_difference_basic() -> Result<()> { + let expr = r#" + + + A + + B + + + "#; + + test( "en", "ClearSpeak", expr, "set difference of cap eigh and cap b")?; + + Ok(()) +} + +#[test] +fn postfix_test() -> Result<()> { + let tests = [ + ( + "transpose", + r#" + + x + T + + "#, + "x transpose", + ), + ( + "highlight", + r#" + + x + + "#, + "x highlighted", + ), + ]; + + // Loop through all test cases, name _, body, and expected result + for (_, body, expected) in tests { + let expr = format!( + r#" + + {} + + "#, + body + ); + + test("en", "ClearSpeak", &expr, expected)?; + } + + Ok(()) +} + +#[test] +fn prefix_test() -> Result<()> { + // Prefix test limit, unit-vector, line-segment + // Directed-line-segment, line, ray, arc + let tests = [ + ( + "limit", + r#" + + x + + "#, + "limit as x", + ), + ( + "unit-vector", + r#" + + x + ^ + + "#, + "unit vector x", + ), + ( + "line-segment", + r#" + + x + ¯ + + "#, + "line segment x", + ), + ]; + + for (_, body, expected) in tests { + let expr = format!( + r#" + + {} + + "#, + body + ); + + test("en", "ClearSpeak", &expr, expected)?; + } + + Ok(()) +} + + +#[test] +fn functions_and_inverses_tests() -> Result<()> { + let tests = vec![ + //("closed-interval", "closed interval between x and y"), + //("closed-open-interval", "interval between x included and y"), + //("open-closed-interval", "interval between x and y included"), + //("open-interval", "open interval between x and y"), + + ("inverse", "inverse of x"), + ("domain", "domain of x"), + ("codomain", "codomain of x"), + ("image", "image of x"), + + //("fraction", "fraction x over y end fraction"), + ("mixed-fraction", "x and y"), + ("quotient", "integer part of x divided by y"), + ("evaluated-at", "x evaluated at y"), + ("remainder", "the remainder x divided by y"), + + ("max", "max x"), + ("min", "min x"), + + ("power", "x to the power y"), + + ("root", "root x"), + + ("greatest-common-divisor", "gcd: the gcd: the greatest common divisor x"), + ("least-common-multiple", "lcm: the lcm: the least common multiple x"), + + ("absolute-value", "absolute value: the absolute value: the absolute value x end absolute value"), + + ("complex-conjugate", "complex conjugate x"), + ("complex-arg", "arg x"), + ("real-part", "the real part x"), + ("imaginary-part", "imaginary part: the imaginary part: the imaginary part x"), + + ("polar-coordinate", "polar coordinate x comma y"), + ("spherical-coordinate", "spherical coordinate x comma y comma z"), + ("cartesian-coordinate", "cartesian coordinate x comma y"), + ("coordinate", "coordinate x comma y"), + + ("floor", "floor x"), + ("ceiling", "ceiling x"), + ("round", "rounded-value x"), + ("fractional-part", "fractional part x"), + + + ]; + + for (intent, expected) in tests { + let expr = match intent { + + "max" + | "min" + | "greatest-common-divisor" + | "least-common-multiple" + | "spherical-coordinate" + | "cartesian-coordinate" + | "coordinate" => { + format!( + " + + x + y + z + + ", + intent + ) + } + + "power" + | "mixed-fraction" + | "quotient" + | "evaluated-at" + | "remainder" + | "closed-interval" + | "closed-open-interval" + | "open-closed-interval" + | "open-interval" + | "polar-coordinate" => { + format!( + " + + x + y + + ", + intent + ) + } + + _ => { + format!( + " + + x + + ", + intent + ) + } + }; + + test("en", "ClearSpeak", &expr, expected)?; + } + + Ok(()) +} + + +#[test] +fn calculus_tests() -> Result<()> { + let tests = vec![ + //("derivative", "the derivative of x with respect to x"), + //"definite-integral", "integral over x from x to x"), + + // prefix + ("limit", "limit as x"), + + // infix + ("tends-to", "x tends to y"), + ("tends-to-from-above", "x tends to from above y"), + ("tends-to-from-below", "x tends to from below y"), + ]; + + for (intent, expected) in tests { + let expr = match intent { + "limit" => { + format!( + " + + x + + ", + intent + ) + } + + _ => { + // infix cases + format!( + " + + x + y + + ", + intent + ) + } + }; + + test("en", "ClearSpeak", &expr, expected)?; + } + + Ok(()) +} + + +#[test] +fn set_tests() -> Result<()> { + let tests = vec![ + ("set", "the set of x"), + // ("set-difference", "set difference of x and y"), + ("complement", "complement of x"), + //("empty-set", "empty set"), + ("cardinality", "cardinality of x"), + ("list", "list of x"), + ("tuple", "the tuple of x"), + ]; + + for (intent, expected) in tests { + let expr = format!( + " + + x + + ", + intent + ); + + test("en", "ClearSpeak", &expr, expected)?; + } + + Ok(()) +} + + +#[test] +fn sequence_and_series_intents() -> Result<()> { + let tests = [ + ( + "sum-1", + r#" + + + x + + "#, + "sum of x", + ), + ( + "sum-2", + r#" + + + i + x + + "#, + "sum over i of x", + ), + ( + "sum-3", + r#" + + + i + n + x + + "#, + "sum from i to n of x", + ), + ( + "product-1", + r#" + + + x + + "#, + "product of x", + ), + ( + "product-2", + r#" + + + i + x + + "#, + "product over i of x", + ), + ( + "product-3", + r#" + + + i + n + x + + "#, + "product from i to n of x", + ), + ]; + + for (_, body, expected) in tests { + let expr = format!( + r#" + + {} + + "#, + body + ); + + test("en", "ClearSpeak", &expr, expected)?; + } + + Ok(()) +} + +#[test] +fn elementary_classical_tests() -> Result<()> { + let tests = vec![ + // Trig + ("sine", "sine of x"), + ("cosine", "cosine of x"), + ("tangent", "tangent of x"), + ("secant", "secant of x"), + ("cosecant", "cosecant of x"), + ("cotangent", "cotangent of x"), + + // Inverse trig + ("arcsine", "arcsine of x"), + ("arccosine", "arccosine of x"), + ("arctangent", "arctangent of x"), + ("arcsecant", "arcsecant of x"), + ("arccosecant", "arc-cosecant of x"), + ("arccotangent", "arc-cotangent of x"), + + // Hyperbolic trig + ("hyperbolic-sine", "shine of x"), + ("hyperbolic-cosine", "cosh of x"), + ("hyperbolic-tangent", "tanch of x"), + ("hyperbolic-secant", "sech of x"), + ("hyperbolic-cosecant", "cosech of x"), + ("hyperbolic-cotangent", "coth of x"), + + // Inverse hyperbolic trig + ("arc-hyperbolic-sine", "arc shine of x"), + ("arc-hyperbolic-cosine", "arc cosh of x"), + ("arc-hyperbolic-tangent", "arc tanch of x"), + ("arc-hyperbolic-secant", "arc sech of x"), + ("arc-hyperbolic-cosecant", "arc cosech of x"), + ("arc-hyperbolic-cotangent", "arc coth of x"), + ]; + + for (intent, expected) in tests { + let expr = format!( + " + + x + + ", + intent + ); + + test("en", "ClearSpeak", &expr, expected)?; + } + + Ok(()) +} + +#[test] +fn statistics_and_probability_tests() -> Result<()> { + let tests = vec![ + ("mean", "mean of x"), + ("standard-deviation", "standard deviation of x"), + ("variance", "variance of x"), + ("median", "median of x"), + ("mode", "mode of x"), + + // conditional probability typically two arguments + // ("conditional-probability", "probability of x given y"), + ]; + + for (intent, expected) in tests { + let expr = match intent { + "conditional-probability" => format!( + " + + P + ( + + x + | + y + + ) + + ", + intent + ), + _ => format!( + " + + x + + ", + intent + ), + }; + + test("en", "ClearSpeak", &expr, expected)?; + } + + Ok(()) +} + +#[test] +fn linear_algebra_tests() -> Result<()> { + let tests = vec![ + ("vector", "vector of x"), + // ("matrix", "matrix of x"), + ("determinant", "determinant of x"), + ("adjugate", "adjugate of x"), + ("magnitude", "magnitude of x"), + ("norm", "norm of x"), + ("span", "span of x"), + + // transpose supports both postfix and function; we test function explicitly + ("transpose", "transpose of x"), + + // dimensional product is infix + ("dimensional-product", "x by y"), + + // unit-vector is prefix + ("unit-vector", "unit vector x") + ]; + + for (intent, expected) in tests { + let expr: String = match intent { + "dimensional-product" => { + " + + x + y + + " + .to_string() + } + _ => format!( + " + + x + + " + ), + }; + + test("en", "ClearSpeak", &expr, expected)?; + } + + Ok(()) +} + +#[test] +fn nofix_set_tests() -> Result<()> { + let tests = vec![ + ("set-of-integers", "ℤ", "set of all integers"), + ("set-of-reals", "ℝ", "set of all real numbers"), + ("set-of-rationals", "ℚ", "set of all rational numbers"), + ("set-of-natural-numbers", "ℕ", "set of all natural numbers"), + ("set-of-complex-numbers", "ℂ", "set of all complex numbers"), + ("set-of-primes", "ℙ", "set of all prime numbers"), + ]; + + for (intent, symbol, expected) in tests { + let expr = format!( + " + {} + ", + intent, + symbol + ); + + test("en", "ClearSpeak", &expr, expected)?; + } + + Ok(()) +} + +#[test] +fn geometry_prefix_multi_value_tests() -> Result<()> { + let tests = vec![ + ("line-segment", "line segment x y"), + ("directed-line-segment", "directed line segment x y"), + ("line", "line x y"), + ("ray", "ray x y"), + ("arc", "arc x y"), + ("point", "point x y z"), + ]; + + for (intent, expected) in tests { + let expr = match intent{ + "point" => { + format!( + " + + x + y + z + + " + ) + } + + _ => { + format!( + " + + x + y + + " + ) + } + }; + + test("en", "ClearSpeak", &expr, expected)?; + } + + Ok(()) +} + +#[test] +fn geometry_prefix_tests() -> Result<()> { + let tests = vec![ + ("length", "length of x"), + ("area", "area of x"), + ("volume", "volume of x"), + ]; + + for (intent, expected) in tests { + let expr = format!( + " + + x + + " + ); + + test("en", "ClearSpeak", &expr, expected)?; + } + + Ok(()) +} + +#[test] +fn separator_tests() -> Result<()> { + let expr = format!( + " + + x + y + + " + ); + + test("en", "ClearSpeak", &expr, "x y")?; + Ok(()) +} + +#[test] +fn general_concepts_tests() -> Result<()> { + let tests = vec![ + // Unary structural + ("fenced-group", "fenced-group of x"), + ("highlight", "x highlighted"), + ("least-common-denominator", "least common denominator of x comma, y comma, z"), // add x, y , z ... + ("pochhammer", "permutation of x"), + ("permutation-cycle", "permutation cycle of x"), + + // Binary structural / infix-style + // ("ordered-pair", "the pair of x and y"), + ("rate", "x per y"), + + ("binomial-coefficient", "x choose y"), + ("embellished-name", "x with annotation y"), + ("indexed-by", "x indexed by y"), + // ("translation", "translation by x comma, y"), // Changes translation to comma + ("constraint", "x with constraint y"), + ]; + + for (intent, expected) in tests { + let expr = match intent { + "ordered-pair" + | "rate" + | "constraint" + | "binomial-coefficient" + | "embellished-name" + | "translation" + | "indexed-by" => { + format!( + " + + x + y + + ", + intent + ) + } + "least-common-denominator" => { + format!( + " + + x + y + z + + ", + intent + ) + } + + // unary cases + _ => { + format!( + " + + x + + ", + intent + ) + } + }; + + test("en", "ClearSpeak", &expr, expected)?; + } + + Ok(()) +} + +#[test] +fn grouping_tests() -> Result<()> { + let tests = vec![ + ("annotation", "x which is y"), + // ("braced-group", "grouped x end-grouped"), + // ("repeating-decimal", "repeating decimal of x"), + ]; + + for (intent, expected) in tests { + let expr = match intent { + "annotation" => { + format!( + " + + x + y + + ", + intent + ) + } + _ => { + format!( + " + + x + + ", + intent + ) + } + }; + + test("en", "ClearSpeak", &expr, expected)?; + } + + Ok(()) +} + +#[test] +fn function_default_fixity_tests() -> Result<()> { + let tests = vec![ + ("curl", "curl of x"), + ("divergence", "divergence of x"), + ("gradient", "gradient of x"), + ("laplacian", "laplacian of x"), + ]; + + for (intent, expected) in tests { + let expr = format!( + " + + x + + ", + intent + ); + + test("en", "ClearSpeak", &expr, expected)?; + } + + Ok(()) +} + +#[test] +fn prefix_default_fixity_tests() -> Result<()> { + let tests = vec![ + ("angle", "angle x"), + ("angle-measure", "angle measure x"), + ("change", "change in x"), + ("for-all", "for all x"), + ("measured-angle", "measured angle x"), + ("not", "not x"), + ("number-of", "number of x"), + ("partial-derivative", "partial x"), + ("right-angle", "right angle x"), + ("square-root-of", "square root of x"), + ("there-does-not-exist", "there does not exist x"), + ("there-exists", "there exists x"), + ]; + + for (intent, expected) in tests { + let expr = format!( + " + + x + + ", + intent + ); + + test("en", "ClearSpeak", &expr, expected)?; + } + + Ok(()) +} + +#[test] +fn infix_default_fixity_tests() -> Result<()> { + let tests = vec![ + ("and", "x and y"), + ("applied-to", "x applied to y"), + ("approximately", "x approximately y"), + ("congruent", "x congruent to y"), + ("cartesian-product", "x cartesian product y"), + ("composed-with", "x composed with y"), + ("cross-product", "x cross product y"), + ("defined-as", "x defined as y"), + ("divided-by", "x divided by y"), + ("divides", "x divides y"), + ("does-not-belong-to", "x does not belong to y"), + ("does-not-divide", "x does not divide y"), + ("dot-product", "x dot product y"), + ("downwards-diagonal-ellipsis", "x downwards diagonal ellipsis y"), + ("direct-product", "x direct product y"), + ("element-of", "x element of y"), + ("ellipsis", "x ellipsis y"), + ("equals", "x equals y"), + ("equivalent-to", "x equivalent to y"), + ("evaluates-to", "x evaluates to y"), + ("given", "x given y"), + ("greater-than", "x greater than y"), + ("greater-than-or-equal-to", "x greater than or equal to y"), + ("identically-equals", "x identically equals y"), + ("if-and-only-if", "x if and only if y"), + ("implies", "x implies y"), + ("inner-product", "x inner product y"), + ("intersection", "x intersection y"), + ("less-than", "x less than y"), + ("less-than-or-equal-to", "x less than or equal to y"), + ("list-separator", "x comma y"), + ("maps-to", "x maps to y"), + ("member-of", "x member of y"), + ("minus", "x minus y"), + ("minus-or-plus", "x minus or plus y"), + ("not-subset", "x not subset of y"), + ("not-superset", "x not superset of y"), + ("not-equal-to", "x not equal to y"), + ("not-member-of", "x not member of y"), + ("not-parallel-to", "x not parallel to y"), + ("obtained-from", "x obtained from y"), + ("or", "x or y"), + ("outer-product", "x outer product y"), + ("parallel-to", "x parallel to y"), + ("perpendicular", "x perpendicular to y"), + ("plus", "x plus y"), + ("plus-or-minus", "x plus or minus y"), + ("precedes", "x precedes y"), + ("proportional", "x proportional to y"), + ("range-separator", "x through y"), + ("ratio", "x ratio y"), + ("similar", "x similar to y"), + ("subset", "x subset of y"), + ("subset-or-equal", "x subset or equal to y"), + ("succeeds", "x succeeds y"), + ("such-that", "x such that y"), + ("superset", "x superset of y"), + ("superset-or-equal", "x superset or equal to y"), + ("tilde", "x tilde y"), + ("times", "x times y"), + ("union", "x union y"), + ("upwards-diagonal-ellipsis", "x upwards diagonal ellipsis y"), + ("vertical-ellipsis", "x vertical ellipsis y"), + ("xor", "x exclusive or y"), + ]; + + for (intent, expected) in tests { + let expr = format!( + " + + x + y + + ", + intent + ); + + test("en", "ClearSpeak", &expr, expected)?; + } + + Ok(()) +} + +#[test] +fn postfix_default_fixity_tests() -> Result<()> { + let tests = vec![ + ("factorial", "x factorial"), + ("percent", "x percent"), + ]; + + for (intent, expected) in tests { + let expr = format!( + " + + x + + ", + intent + ); + + test("en", "ClearSpeak", &expr, expected)?; + } + + Ok(()) +} + +#[test] +fn nofix_default_fixity_tests() -> Result<()> { + let tests = vec![ + ("diameter", "d", "diameter"), + ("distance", "D", "distance"), + ("probability", "P", "probability"), + ("radius", "r", "radius"), + ("volume", "V", "volume"), + ("exponential-e", "e", "e"), + ("imaginary-i", "i", "i"), + ("differential-d", "d", "d"), + ("golden-ratio", "φ", "golden ratio"), + ]; + + for (intent, symbol, expected) in tests { + let expr = format!( + " + {} + ", + intent, + symbol + ); + + test("en", "ClearSpeak", &expr, expected)?; + } + + Ok(()) +} \ No newline at end of file