asciimath 1.0.6 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +6 -8
  3. data/AST.adoc +457 -0
  4. data/CHANGELOG.adoc +44 -1
  5. data/README.adoc +66 -3
  6. data/asciimath.gemspec +7 -5
  7. data/dump_symbol_table.rb +46 -0
  8. data/lib/asciimath.rb +5 -4
  9. data/lib/asciimath/ast.rb +456 -0
  10. data/lib/asciimath/cli.rb +4 -1
  11. data/lib/asciimath/color_table.rb +21 -0
  12. data/lib/asciimath/html.rb +148 -119
  13. data/lib/asciimath/latex.rb +400 -0
  14. data/lib/asciimath/markup.rb +479 -0
  15. data/lib/asciimath/mathml.rb +196 -83
  16. data/lib/asciimath/parser.rb +531 -318
  17. data/lib/asciimath/symbol_table.rb +25 -0
  18. data/lib/asciimath/version.rb +1 -1
  19. data/spec/ast.rb +144 -0
  20. data/spec/customisation_spec.rb +28 -0
  21. data/spec/parser_spec.rb +598 -147
  22. data/spec/schema/mathml2/common/common-attribs.xsd +41 -0
  23. data/spec/schema/mathml2/common/math.xsd +126 -0
  24. data/spec/schema/mathml2/common/xlink-href.xsd +20 -0
  25. data/spec/schema/mathml2/content/arith.xsd +90 -0
  26. data/spec/schema/mathml2/content/calculus.xsd +146 -0
  27. data/spec/schema/mathml2/content/common-attrib.xsd +30 -0
  28. data/spec/schema/mathml2/content/constants.xsd +83 -0
  29. data/spec/schema/mathml2/content/constructs.xsd +260 -0
  30. data/spec/schema/mathml2/content/elementary-functions.xsd +117 -0
  31. data/spec/schema/mathml2/content/functions.xsd +73 -0
  32. data/spec/schema/mathml2/content/linear-algebra.xsd +173 -0
  33. data/spec/schema/mathml2/content/logic.xsd +53 -0
  34. data/spec/schema/mathml2/content/relations.xsd +55 -0
  35. data/spec/schema/mathml2/content/semantics.xsd +85 -0
  36. data/spec/schema/mathml2/content/sets.xsd +236 -0
  37. data/spec/schema/mathml2/content/statistics.xsd +136 -0
  38. data/spec/schema/mathml2/content/tokens.xsd +120 -0
  39. data/spec/schema/mathml2/content/vector-calculus.xsd +88 -0
  40. data/spec/schema/mathml2/mathml2.xsd +59 -0
  41. data/spec/schema/mathml2/presentation/action.xsd +44 -0
  42. data/spec/schema/mathml2/presentation/characters.xsd +37 -0
  43. data/spec/schema/mathml2/presentation/common-attribs.xsd +113 -0
  44. data/spec/schema/mathml2/presentation/common-types.xsd +103 -0
  45. data/spec/schema/mathml2/presentation/error.xsd +40 -0
  46. data/spec/schema/mathml2/presentation/layout.xsd +195 -0
  47. data/spec/schema/mathml2/presentation/scripts.xsd +186 -0
  48. data/spec/schema/mathml2/presentation/space.xsd +52 -0
  49. data/spec/schema/mathml2/presentation/style.xsd +69 -0
  50. data/spec/schema/mathml2/presentation/table.xsd +216 -0
  51. data/spec/schema/mathml2/presentation/tokens.xsd +124 -0
  52. data/spec/schema/mathml3/mathml3-common.xsd +99 -0
  53. data/spec/schema/mathml3/mathml3-content.xsd +684 -0
  54. data/spec/schema/mathml3/mathml3-presentation.xsd +2151 -0
  55. data/spec/schema/mathml3/mathml3-strict-content.xsd +186 -0
  56. data/spec/schema/mathml3/mathml3.xsd +9 -0
  57. metadata +108 -11
@@ -0,0 +1,25 @@
1
+ module AsciiMath
2
+ class SymbolTableBuilder
3
+ def initialize()
4
+ @table = {}
5
+ end
6
+
7
+ def add(*args)
8
+ raise 'Insufficient arguments' if args.length < 3
9
+
10
+ entry = {}
11
+ if args.last.is_a?(Hash)
12
+ entry.merge!(args.pop)
13
+ end
14
+ entry[:type] = args.pop
15
+ entry[:value] = args.pop
16
+
17
+ entry.freeze
18
+ args.each { |name| @table[name.freeze] = entry }
19
+ end
20
+
21
+ def build
22
+ @table.dup.freeze
23
+ end
24
+ end
25
+ end
@@ -1,3 +1,3 @@
1
1
  module AsciiMath
2
- VERSION = "1.0.6"
2
+ VERSION = "2.0.1"
3
3
  end
@@ -0,0 +1,144 @@
1
+ require_relative '../lib/asciimath/ast'
2
+
3
+ module AsciiMath
4
+ module ASTHelper
5
+ ACTUAL_AST = Class.new do
6
+ include ::AsciiMath::AST
7
+ end.new
8
+
9
+ def grseq(*expressions)
10
+ group(seq(*expressions))
11
+ end
12
+
13
+ def seq(*expressions)
14
+ mapped = expressions.map { |e| to_ast(e) }
15
+ ACTUAL_AST.expression(*mapped)
16
+ end
17
+
18
+ def paren(*args)
19
+ case args.length
20
+ when 1
21
+ lparen = symbol('(')
22
+ e = to_ast(args[0])
23
+ rparen = symbol(')')
24
+ when 3
25
+ lparen = args[0]
26
+ e = to_ast(args[1])
27
+ rparen = args[2]
28
+ else
29
+ raise "Incorrect argument count #{args.length}"
30
+ end
31
+ ACTUAL_AST.paren(lparen, e, rparen)
32
+ end
33
+
34
+ def group(*args)
35
+ case args.length
36
+ when 1
37
+ lparen = symbol('(')
38
+ e = to_ast(args[0])
39
+ rparen = symbol(')')
40
+ when 3
41
+ lparen = args[0]
42
+ e = to_ast(args[1])
43
+ rparen = args[2]
44
+ else
45
+ raise "Incorrect argument count #{args.length}"
46
+ end
47
+ ACTUAL_AST.group(lparen, e, rparen)
48
+ end
49
+
50
+ def subsup(e, sub, sup)
51
+ ACTUAL_AST.subsup(to_ast(e), to_ast(sub), to_ast(sup))
52
+ end
53
+
54
+ def sub(e, sub)
55
+ ACTUAL_AST.sub(to_ast(e), to_ast(sub))
56
+ end
57
+
58
+ def sup(e, sup)
59
+ ACTUAL_AST.sup(to_ast(e), to_ast(sup))
60
+ end
61
+
62
+ def unary(operator, e)
63
+ ACTUAL_AST.unary(to_ast(operator), to_ast(e))
64
+ end
65
+
66
+ def binary(operator, e1, e2)
67
+ ACTUAL_AST.binary(to_ast(operator), to_ast(e1), to_ast(e2))
68
+ end
69
+
70
+ def infix(e1, operator, e2)
71
+ ACTUAL_AST.infix(to_ast(e1), to_ast(operator), to_ast(e2))
72
+ end
73
+
74
+ def text(value)
75
+ ACTUAL_AST.text(value)
76
+ end
77
+
78
+ def identifier(value)
79
+ ACTUAL_AST.identifier(value)
80
+ end
81
+
82
+ def number(value)
83
+ ACTUAL_AST.number(value)
84
+ end
85
+
86
+ def color(r, g, b, value)
87
+ ACTUAL_AST.color(r, g, b, value)
88
+ end
89
+
90
+ def symbol(text)
91
+ symbol = ::AsciiMath::Parser::DEFAULT_PARSER_SYMBOL_TABLE[text]
92
+ if symbol
93
+ ACTUAL_AST.symbol(symbol[:value], text)
94
+ else
95
+ nil
96
+ end
97
+ end
98
+
99
+ def matrix(*args)
100
+ case args.length
101
+ when 1
102
+ lparen = symbol('(')
103
+ rows = args[0]
104
+ rparen = symbol(')')
105
+ when 3
106
+ lparen = args[0]
107
+ rows = args[1]
108
+ rparen = args[2]
109
+ else
110
+ raise "Incorrect argument count #{args.length}"
111
+ end
112
+
113
+ rows = rows.map do |row|
114
+ row.map do |col|
115
+ to_ast(col)
116
+ end
117
+ end
118
+
119
+ ACTUAL_AST.matrix(lparen, rows, rparen)
120
+ end
121
+
122
+ def to_ast(e)
123
+ case e
124
+ when String
125
+ s = symbol(e)
126
+ if s
127
+ s
128
+ elsif e =~ /[0-9]+(.[0-9]+)?/
129
+ number(e)
130
+ elsif e.length > 1
131
+ text(e)
132
+ else
133
+ identifier(e)
134
+ end
135
+ when Symbol
136
+ raise "Not supported"
137
+ when Array
138
+ seq(*e)
139
+ else
140
+ e
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,28 @@
1
+ #encoding: utf-8
2
+ require 'rspec'
3
+ require 'asciimath'
4
+ require_relative 'ast'
5
+
6
+ RSpec.configure do |c|
7
+ c.include ::AsciiMath::ASTHelper
8
+ end
9
+
10
+ describe 'AsciiMath::Parser', :variant => :ast do
11
+ it "should support custom symbols" do
12
+ my_tokens_table = AsciiMath::SymbolTableBuilder.new
13
+ AsciiMath::Parser.add_default_parser_symbols(my_tokens_table)
14
+ my_tokens_table.add('mysymbol', :mysymbol, :symbol)
15
+
16
+ parsed = AsciiMath::parse("a + mysymbol + b", my_tokens_table.build)
17
+ expect(parsed.ast).to eq(seq(identifier('a'), symbol('+'), ::AsciiMath::AST::Symbol.new(:mysymbol, 'mysymbol'), symbol('+'), identifier('b')))
18
+ end
19
+
20
+ it "should support replacing standard symbols" do
21
+ my_tokens_table = AsciiMath::SymbolTableBuilder.new
22
+ AsciiMath::Parser.add_default_parser_symbols(my_tokens_table)
23
+ my_tokens_table.add('+', :foo, :symbol)
24
+
25
+ parsed = AsciiMath::parse("a + b", my_tokens_table.build)
26
+ expect(parsed.ast).to eq(seq(identifier('a'), ::AsciiMath::AST::Symbol.new(:foo, '+'), identifier('b')))
27
+ end
28
+ end
@@ -1,162 +1,613 @@
1
1
  #encoding: utf-8
2
2
  require 'rspec'
3
3
  require 'asciimath'
4
+ require_relative 'ast'
5
+ require 'nokogiri'
4
6
 
5
- TEST_CASES = {
6
- 'x+b/(2a)<+-sqrt((b^2)/(4a^2)-c/a)' =>
7
- {
8
- :mathml => '<math><mi>x</mi><mo>+</mo><mfrac><mi>b</mi><mrow><mn>2</mn><mi>a</mi></mrow></mfrac><mo>&#x003C;</mo><mo>&#x00B1;</mo><msqrt><mrow><mfrac><msup><mi>b</mi><mn>2</mn></msup><mrow><mn>4</mn><msup><mi>a</mi><mn>2</mn></msup></mrow></mfrac><mo>&#x2212;</mo><mfrac><mi>c</mi><mi>a</mi></mfrac></mrow></msqrt></math>',
9
- :html => 'Unsupported',
10
- },
11
- 'a^2 + b^2 = c^2' =>
12
- {
13
- :mathml => '<math><msup><mi>a</mi><mn>2</mn></msup><mo>+</mo><msup><mi>b</mi><mn>2</mn></msup><mo>=</mo><msup><mi>c</mi><mn>2</mn></msup></math>',
14
- :html => '<span class="math-inline"><span class="math-row"><span class="math-identifier">a</span><span class="math-subsup"><span class="math-smaller"><span class="math-number">2</span></span><span class="math-smaller">&zwj;</span></span><span class="math-operator">+</span><span class="math-identifier">b</span><span class="math-subsup"><span class="math-smaller"><span class="math-number">2</span></span><span class="math-smaller">&zwj;</span></span><span class="math-operator">=</span><span class="math-identifier">c</span><span class="math-subsup"><span class="math-smaller"><span class="math-number">2</span></span><span class="math-smaller">&zwj;</span></span></span></span>',
15
- },
16
- 'x = (-b+-sqrt(b^2-4ac))/(2a)' =>
17
- {
18
- :mathml => '<math><mi>x</mi><mo>=</mo><mfrac><mrow><mo>&#x2212;</mo><mi>b</mi><mo>&#x00B1;</mo><msqrt><mrow><msup><mi>b</mi><mn>2</mn></msup><mn>-4</mn><mi>a</mi><mi>c</mi></mrow></msqrt></mrow><mrow><mn>2</mn><mi>a</mi></mrow></mfrac></math>',
19
- :html => 'Unsupported'
20
- },
21
- 'm = (y_2 - y_1)/(x_2 - x_1) = (Deltay)/(Deltax)' =>
22
- {
23
- :mathml => '<math><mi>m</mi><mo>=</mo><mfrac><mrow><msub><mi>y</mi><mn>2</mn></msub><mo>&#x2212;</mo><msub><mi>y</mi><mn>1</mn></msub></mrow><mrow><msub><mi>x</mi><mn>2</mn></msub><mo>&#x2212;</mo><msub><mi>x</mi><mn>1</mn></msub></mrow></mfrac><mo>=</mo><mfrac><mrow><mo>&#x0394;</mo><mi>y</mi></mrow><mrow><mo>&#x0394;</mo><mi>x</mi></mrow></mfrac></math>',
24
- :html => '<span class="math-inline"><span class="math-row"><span class="math-identifier">m</span><span class="math-operator">=</span><span class="math-blank">&zwj;</span><span class="math-fraction"><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-row"><span class="math-identifier">y</span><span class="math-subsup"><span class="math-smaller">&zwj;</span><span class="math-smaller"><span class="math-number">2</span></span></span><span class="math-operator">&#x2212;</span><span class="math-identifier">y</span><span class="math-subsup"><span class="math-smaller">&zwj;</span><span class="math-smaller"><span class="math-number">1</span></span></span></span></span></span></span></span><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-row"><span class="math-identifier">x</span><span class="math-subsup"><span class="math-smaller">&zwj;</span><span class="math-smaller"><span class="math-number">2</span></span></span><span class="math-operator">&#x2212;</span><span class="math-identifier">x</span><span class="math-subsup"><span class="math-smaller">&zwj;</span><span class="math-smaller"><span class="math-number">1</span></span></span></span></span></span></span></span></span><span class="math-operator">=</span><span class="math-blank">&zwj;</span><span class="math-fraction"><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-row"><span class="math-operator">&#x0394;</span><span class="math-identifier">y</span></span></span></span></span></span><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-row"><span class="math-operator">&#x0394;</span><span class="math-identifier">x</span></span></span></span></span></span></span></span></span>'
25
- },
26
- 'f\'(x) = lim_(Deltax->0)(f(x+Deltax)-f(x))/(Deltax)' =>
27
- {
28
- :mathml => '<math><mi>f</mi><mi>\'</mi><mrow><mo>(</mo><mi>x</mi><mo>)</mo></mrow><mo>=</mo><munder><mo>lim</mo><mrow><mo>&#x0394;</mo><mi>x</mi><mo>&#x2192;</mo><mn>0</mn></mrow></munder><mfrac><mrow><mi>f</mi><mrow><mo>(</mo><mi>x</mi><mo>+</mo><mo>&#x0394;</mo><mi>x</mi><mo>)</mo></mrow><mo>&#x2212;</mo><mi>f</mi><mrow><mo>(</mo><mi>x</mi><mo>)</mo></mrow></mrow><mrow><mo>&#x0394;</mo><mi>x</mi></mrow></mfrac></math>',
29
- :html => '<span class="math-inline"><span class="math-row"><span class="math-identifier">f</span><span class="math-identifier">\'</span><span class="math-row"><span class="math-brace">(</span><span class="math-row"><span class="math-identifier">x</span></span><span class="math-brace">)</span></span><span class="math-operator">=</span><span class="math-blank">&zwj;</span><span class="math-underover"><span class="math-smaller"><span class="math-blank">&zwj;</span></span><span class="math-operator">lim</span><span class="math-smaller"><span class="math-row"><span class="math-operator">&#x0394;</span><span class="math-identifier">x</span><span class="math-operator">&#x2192;</span><span class="math-number">0</span></span></span></span><span class="math-blank">&zwj;</span><span class="math-fraction"><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-row"><span class="math-identifier">f</span><span class="math-row"><span class="math-brace">(</span><span class="math-row"><span class="math-identifier">x</span><span class="math-operator">+</span><span class="math-operator">&#x0394;</span><span class="math-identifier">x</span></span><span class="math-brace">)</span></span><span class="math-operator">&#x2212;</span><span class="math-identifier">f</span><span class="math-row"><span class="math-brace">(</span><span class="math-row"><span class="math-identifier">x</span></span><span class="math-brace">)</span></span></span></span></span></span></span><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-row"><span class="math-operator">&#x0394;</span><span class="math-identifier">x</span></span></span></span></span></span></span></span></span>'
30
- },
31
- 'd/dx [x^n] = nx^(n - 1)' =>
32
- {
33
- :mathml => '<math><mfrac><mi>d</mi><mi>dx</mi></mfrac><mrow><mo>[</mo><msup><mi>x</mi><mi>n</mi></msup><mo>]</mo></mrow><mo>=</mo><mi>n</mi><msup><mi>x</mi><mrow><mi>n</mi><mo>&#x2212;</mo><mn>1</mn></mrow></msup></math>',
34
- :html => '<span class="math-inline"><span class="math-row"><span class="math-blank">&zwj;</span><span class="math-fraction"><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-identifier">d</span></span></span></span></span><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-identifier">dx</span></span></span></span></span></span><span class="math-row"><span class="math-brace">[</span><span class="math-row"><span class="math-identifier">x</span><span class="math-subsup"><span class="math-smaller"><span class="math-identifier">n</span></span><span class="math-smaller">&zwj;</span></span></span><span class="math-brace">]</span></span><span class="math-operator">=</span><span class="math-identifier">n</span><span class="math-identifier">x</span><span class="math-subsup"><span class="math-smaller"><span class="math-row"><span class="math-identifier">n</span><span class="math-operator">&#x2212;</span><span class="math-number">1</span></span></span><span class="math-smaller">&zwj;</span></span></span></span>'
35
- },
36
- 'int_a^b f(x) dx = [F(x)]_a^b = F(b) - F(a)' =>
37
- {
38
- :mathml => '<math><msubsup><mo>&#x222B;</mo><mi>a</mi><mi>b</mi></msubsup><mi>f</mi><mrow><mo>(</mo><mi>x</mi><mo>)</mo></mrow><mi>dx</mi><mo>=</mo><msubsup><mrow><mo>[</mo><mi>F</mi><mrow><mo>(</mo><mi>x</mi><mo>)</mo></mrow><mo>]</mo></mrow><mi>a</mi><mi>b</mi></msubsup><mo>=</mo><mi>F</mi><mrow><mo>(</mo><mi>b</mi><mo>)</mo></mrow><mo>&#x2212;</mo><mi>F</mi><mrow><mo>(</mo><mi>a</mi><mo>)</mo></mrow></math>',
39
- :html => '<span class="math-inline"><span class="math-row"><span class="math-operator">&#x222B;</span><span class="math-subsup"><span class="math-smaller"><span class="math-identifier">b</span></span><span class="math-smaller"><span class="math-identifier">a</span></span></span><span class="math-identifier">f</span><span class="math-row"><span class="math-brace">(</span><span class="math-row"><span class="math-identifier">x</span></span><span class="math-brace">)</span></span><span class="math-identifier">dx</span><span class="math-operator">=</span><span class="math-row"><span class="math-brace">[</span><span class="math-row"><span class="math-identifier">F</span><span class="math-row"><span class="math-brace">(</span><span class="math-row"><span class="math-identifier">x</span></span><span class="math-brace">)</span></span></span><span class="math-brace">]</span></span><span class="math-subsup"><span class="math-smaller"><span class="math-identifier">b</span></span><span class="math-smaller"><span class="math-identifier">a</span></span></span><span class="math-operator">=</span><span class="math-identifier">F</span><span class="math-row"><span class="math-brace">(</span><span class="math-row"><span class="math-identifier">b</span></span><span class="math-brace">)</span></span><span class="math-operator">&#x2212;</span><span class="math-identifier">F</span><span class="math-row"><span class="math-brace">(</span><span class="math-row"><span class="math-identifier">a</span></span><span class="math-brace">)</span></span></span></span>'
40
- },
41
- 'int_a^b f(x) dx = f(c)(b - a)' =>
42
- {
43
- :mathml => '<math><msubsup><mo>&#x222B;</mo><mi>a</mi><mi>b</mi></msubsup><mi>f</mi><mrow><mo>(</mo><mi>x</mi><mo>)</mo></mrow><mi>dx</mi><mo>=</mo><mi>f</mi><mrow><mo>(</mo><mi>c</mi><mo>)</mo></mrow><mrow><mo>(</mo><mi>b</mi><mo>&#x2212;</mo><mi>a</mi><mo>)</mo></mrow></math>',
44
- :html => '<span class="math-inline"><span class="math-row"><span class="math-operator">&#x222B;</span><span class="math-subsup"><span class="math-smaller"><span class="math-identifier">b</span></span><span class="math-smaller"><span class="math-identifier">a</span></span></span><span class="math-identifier">f</span><span class="math-row"><span class="math-brace">(</span><span class="math-row"><span class="math-identifier">x</span></span><span class="math-brace">)</span></span><span class="math-identifier">dx</span><span class="math-operator">=</span><span class="math-identifier">f</span><span class="math-row"><span class="math-brace">(</span><span class="math-row"><span class="math-identifier">c</span></span><span class="math-brace">)</span></span><span class="math-row"><span class="math-brace">(</span><span class="math-row"><span class="math-identifier">b</span><span class="math-operator">&#x2212;</span><span class="math-identifier">a</span></span><span class="math-brace">)</span></span></span></span>'
45
- },
46
- 'ax^2 + bx + c = 0' =>
47
- {
48
- :mathml => '<math><mi>a</mi><msup><mi>x</mi><mn>2</mn></msup><mo>+</mo><mi>b</mi><mi>x</mi><mo>+</mo><mi>c</mi><mo>=</mo><mn>0</mn></math>',
49
- :html => '<span class="math-inline"><span class="math-row"><span class="math-identifier">a</span><span class="math-identifier">x</span><span class="math-subsup"><span class="math-smaller"><span class="math-number">2</span></span><span class="math-smaller">&zwj;</span></span><span class="math-operator">+</span><span class="math-identifier">b</span><span class="math-identifier">x</span><span class="math-operator">+</span><span class="math-identifier">c</span><span class="math-operator">=</span><span class="math-number">0</span></span></span>'
50
- },
51
- '"average value"=1/(b-a) int_a^b f(x) dx' =>
52
- {
53
- :mathml => '<math><mtext>average value</mtext><mo>=</mo><mfrac><mn>1</mn><mrow><mi>b</mi><mo>&#x2212;</mo><mi>a</mi></mrow></mfrac><msubsup><mo>&#x222B;</mo><mi>a</mi><mi>b</mi></msubsup><mi>f</mi><mrow><mo>(</mo><mi>x</mi><mo>)</mo></mrow><mi>dx</mi></math>',
54
- :html => '<span class="math-inline"><span class="math-row"><span class="math-text">average value</span><span class="math-operator">=</span><span class="math-blank">&zwj;</span><span class="math-fraction"><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-number">1</span></span></span></span></span><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-row"><span class="math-identifier">b</span><span class="math-operator">&#x2212;</span><span class="math-identifier">a</span></span></span></span></span></span></span><span class="math-operator">&#x222B;</span><span class="math-subsup"><span class="math-smaller"><span class="math-identifier">b</span></span><span class="math-smaller"><span class="math-identifier">a</span></span></span><span class="math-identifier">f</span><span class="math-row"><span class="math-brace">(</span><span class="math-row"><span class="math-identifier">x</span></span><span class="math-brace">)</span></span><span class="math-identifier">dx</span></span></span>'
55
- },
56
- 'd/dx[int_a^x f(t) dt] = f(x)' =>
57
- {
58
- :mathml => '<math><mfrac><mi>d</mi><mi>dx</mi></mfrac><mrow><mo>[</mo><msubsup><mo>&#x222B;</mo><mi>a</mi><mi>x</mi></msubsup><mi>f</mi><mrow><mo>(</mo><mi>t</mi><mo>)</mo></mrow><mi>dt</mi><mo>]</mo></mrow><mo>=</mo><mi>f</mi><mrow><mo>(</mo><mi>x</mi><mo>)</mo></mrow></math>',
59
- :html => '<span class="math-inline"><span class="math-row"><span class="math-blank">&zwj;</span><span class="math-fraction"><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-identifier">d</span></span></span></span></span><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-identifier">dx</span></span></span></span></span></span><span class="math-row"><span class="math-brace">[</span><span class="math-row"><span class="math-operator">&#x222B;</span><span class="math-subsup"><span class="math-smaller"><span class="math-identifier">x</span></span><span class="math-smaller"><span class="math-identifier">a</span></span></span><span class="math-identifier">f</span><span class="math-row"><span class="math-brace">(</span><span class="math-row"><span class="math-identifier">t</span></span><span class="math-brace">)</span></span><span class="math-identifier">dt</span></span><span class="math-brace">]</span></span><span class="math-operator">=</span><span class="math-identifier">f</span><span class="math-row"><span class="math-brace">(</span><span class="math-row"><span class="math-identifier">x</span></span><span class="math-brace">)</span></span></span></span>'
60
- },
61
- 'hat(ab) bar(xy) ul(A) vec(v)' =>
62
- {
63
- :mathml => '<math><mover><mrow><mi>a</mi><mi>b</mi></mrow><mo>&#x005E;</mo></mover><mover><mrow><mi>x</mi><mi>y</mi></mrow><mo>&#x00AF;</mo></mover><munder><mi>A</mi><mo>_</mo></munder><mover><mi>v</mi><mo>&#x2192;</mo></mover></math>',
64
- :html => '<span class="math-inline"><span class="math-row"><span class="math-blank">&zwj;</span><span class="math-underover"><span class="math-smaller"><span class="math-operator">&#x005E;</span></span><span class="math-row"><span class="math-brace">(</span><span class="math-row"><span class="math-identifier">a</span><span class="math-identifier">b</span></span><span class="math-brace">)</span></span><span class="math-smaller"><span class="math-blank">&zwj;</span></span></span><span class="math-blank">&zwj;</span><span class="math-underover"><span class="math-smaller"><span class="math-operator">&#x00AF;</span></span><span class="math-row"><span class="math-brace">(</span><span class="math-row"><span class="math-identifier">x</span><span class="math-identifier">y</span></span><span class="math-brace">)</span></span><span class="math-smaller"><span class="math-blank">&zwj;</span></span></span><span class="math-blank">&zwj;</span><span class="math-underover"><span class="math-smaller"><span class="math-blank">&zwj;</span></span><span class="math-row"><span class="math-brace">(</span><span class="math-row"><span class="math-identifier">A</span></span><span class="math-brace">)</span></span><span class="math-smaller"><span class="math-operator">_</span></span></span><span class="math-blank">&zwj;</span><span class="math-underover"><span class="math-smaller"><span class="math-operator">&#x2192;</span></span><span class="math-row"><span class="math-brace">(</span><span class="math-row"><span class="math-identifier">v</span></span><span class="math-brace">)</span></span><span class="math-smaller"><span class="math-blank">&zwj;</span></span></span></span></span>'
65
- },
66
- 'z_12^34' =>
67
- {
68
- :mathml => '<math><msubsup><mi>z</mi><mn>12</mn><mn>34</mn></msubsup></math>',
69
- :html => '<span class="math-inline"><span class="math-row"><span class="math-identifier">z</span><span class="math-subsup"><span class="math-smaller"><span class="math-number">34</span></span><span class="math-smaller"><span class="math-number">12</span></span></span></span></span>'
70
- },
71
- 'lim_(x->c)(f(x)-f(c))/(x-c)' =>
72
- {
73
- :mathml => '<math><munder><mo>lim</mo><mrow><mi>x</mi><mo>&#x2192;</mo><mi>c</mi></mrow></munder><mfrac><mrow><mi>f</mi><mrow><mo>(</mo><mi>x</mi><mo>)</mo></mrow><mo>&#x2212;</mo><mi>f</mi><mrow><mo>(</mo><mi>c</mi><mo>)</mo></mrow></mrow><mrow><mi>x</mi><mo>&#x2212;</mo><mi>c</mi></mrow></mfrac></math>',
74
- :html => '<span class="math-inline"><span class="math-row"><span class="math-blank">&zwj;</span><span class="math-underover"><span class="math-smaller"><span class="math-blank">&zwj;</span></span><span class="math-operator">lim</span><span class="math-smaller"><span class="math-row"><span class="math-identifier">x</span><span class="math-operator">&#x2192;</span><span class="math-identifier">c</span></span></span></span><span class="math-blank">&zwj;</span><span class="math-fraction"><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-row"><span class="math-identifier">f</span><span class="math-row"><span class="math-brace">(</span><span class="math-row"><span class="math-identifier">x</span></span><span class="math-brace">)</span></span><span class="math-operator">&#x2212;</span><span class="math-identifier">f</span><span class="math-row"><span class="math-brace">(</span><span class="math-row"><span class="math-identifier">c</span></span><span class="math-brace">)</span></span></span></span></span></span></span><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-row"><span class="math-identifier">x</span><span class="math-operator">&#x2212;</span><span class="math-identifier">c</span></span></span></span></span></span></span></span></span>'
75
- },
76
- 'int_0^(pi/2) g(x) dx' =>
77
- {
78
- :mathml => '<math><msubsup><mo>&#x222B;</mo><mn>0</mn><mfrac><mi>&#x03c0;</mi><mn>2</mn></mfrac></msubsup><mi>g</mi><mrow><mo>(</mo><mi>x</mi><mo>)</mo></mrow><mi>dx</mi></math>',
79
- :html => '<span class="math-inline"><span class="math-row"><span class="math-operator">&#x222B;</span><span class="math-subsup"><span class="math-smaller"><span class="math-row"><span class="math-blank">&zwj;</span><span class="math-fraction"><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-identifier">&#x03c0;</span></span></span></span></span><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-number">2</span></span></span></span></span></span></span></span><span class="math-smaller"><span class="math-number">0</span></span></span><span class="math-identifier">g</span><span class="math-row"><span class="math-brace">(</span><span class="math-row"><span class="math-identifier">x</span></span><span class="math-brace">)</span></span><span class="math-identifier">dx</span></span></span>'
80
- },
81
- 'sum_(n=0)^oo a_n' =>
82
- {
83
- :mathml => '<math><munderover><mo>&#x2211;</mo><mrow><mi>n</mi><mo>=</mo><mn>0</mn></mrow><mo>&#x221E;</mo></munderover><msub><mi>a</mi><mi>n</mi></msub></math>',
84
- :html => '<span class="math-inline"><span class="math-row"><span class="math-blank">&zwj;</span><span class="math-underover"><span class="math-smaller"><span class="math-operator">&#x221E;</span></span><span class="math-operator">&#x2211;</span><span class="math-smaller"><span class="math-row"><span class="math-identifier">n</span><span class="math-operator">=</span><span class="math-number">0</span></span></span></span><span class="math-identifier">a</span><span class="math-subsup"><span class="math-smaller">&zwj;</span><span class="math-smaller"><span class="math-identifier">n</span></span></span></span></span>'
85
- },
86
- '((1,2,3),(4,5,6),(7,8,9))' =>
87
- {
88
- :mathml => '<math><mrow><mo>(</mo><mtable><mtr><mtd><mn>1</mn></mtd><mtd><mn>2</mn></mtd><mtd><mn>3</mn></mtd></mtr><mtr><mtd><mn>4</mn></mtd><mtd><mn>5</mn></mtd><mtd><mn>6</mn></mtd></mtr><mtr><mtd><mn>7</mn></mtd><mtd><mn>8</mn></mtd><mtd><mn>9</mn></mtd></mtr></mtable><mo>)</mo></mrow></math>',
89
- :html => '<span class="math-inline"><span class="math-row"><span class="math-row"><span class="math-brace" style="font-size: 300%;">(</span><span class="math-matrix" style="grid-template-columns:repeat(3,1fr);grid-template-rows:repeat(3,1fr);"><span class="math-row"><span class="math-number">1</span></span><span class="math-row"><span class="math-number">2</span></span><span class="math-row"><span class="math-number">3</span></span><span class="math-row"><span class="math-number">4</span></span><span class="math-row"><span class="math-number">5</span></span><span class="math-row"><span class="math-number">6</span></span><span class="math-row"><span class="math-number">7</span></span><span class="math-row"><span class="math-number">8</span></span><span class="math-row"><span class="math-number">9</span></span></span><span class="math-brace" style="font-size: 300%;">)</span></span></span></span>'
90
- },
91
- '|(a,b),(c,d)|=ad-bc' =>
92
- {
93
- :mathml => '<math><mrow><mo>|</mo><mtable><mtr><mtd><mi>a</mi></mtd><mtd><mi>b</mi></mtd></mtr><mtr><mtd><mi>c</mi></mtd><mtd><mi>d</mi></mtd></mtr></mtable><mo>|</mo></mrow><mo>=</mo><mi>a</mi><mi>d</mi><mo>&#x2212;</mo><mi>b</mi><mi>c</mi></math>',
94
- :html => '<span class="math-inline"><span class="math-row"><span class="math-row"><span class="math-brace" style="font-size: 200%;">|</span><span class="math-matrix" style="grid-template-columns:repeat(2,1fr);grid-template-rows:repeat(2,1fr);"><span class="math-row"><span class="math-identifier">a</span></span><span class="math-row"><span class="math-identifier">b</span></span><span class="math-row"><span class="math-identifier">c</span></span><span class="math-row"><span class="math-identifier">d</span></span></span><span class="math-brace" style="font-size: 200%;">|</span></span><span class="math-operator">=</span><span class="math-identifier">a</span><span class="math-identifier">d</span><span class="math-operator">&#x2212;</span><span class="math-identifier">b</span><span class="math-identifier">c</span></span></span>'
95
- },
96
- '((a_(11), cdots , a_(1n)),(vdots, ddots, vdots),(a_(m1), cdots , a_(mn)))' =>
97
- {
98
- :mathml => '<math><mrow><mo>(</mo><mtable><mtr><mtd><msub><mi>a</mi><mn>11</mn></msub></mtd><mtd><mo>&#x22EF;</mo></mtd><mtd><msub><mi>a</mi><mrow><mn>1</mn><mi>n</mi></mrow></msub></mtd></mtr><mtr><mtd><mo>&#x22EE;</mo></mtd><mtd><mo>&#x22F1;</mo></mtd><mtd><mo>&#x22EE;</mo></mtd></mtr><mtr><mtd><msub><mi>a</mi><mrow><mi>m</mi><mn>1</mn></mrow></msub></mtd><mtd><mo>&#x22EF;</mo></mtd><mtd><msub><mi>a</mi><mrow><mi>m</mi><mi>n</mi></mrow></msub></mtd></mtr></mtable><mo>)</mo></mrow></math>',
99
- :html => '<span class="math-inline"><span class="math-row"><span class="math-row"><span class="math-brace" style="font-size: 300%;">(</span><span class="math-matrix" style="grid-template-columns:repeat(3,1fr);grid-template-rows:repeat(3,1fr);"><span class="math-row"><span class="math-identifier">a</span><span class="math-subsup"><span class="math-smaller">&zwj;</span><span class="math-smaller"><span class="math-row"><span class="math-number">11</span></span></span></span></span><span class="math-row"><span class="math-operator">&#x22EF;</span></span><span class="math-row"><span class="math-identifier">a</span><span class="math-subsup"><span class="math-smaller">&zwj;</span><span class="math-smaller"><span class="math-row"><span class="math-number">1</span><span class="math-identifier">n</span></span></span></span></span><span class="math-row"><span class="math-operator">&#x22EE;</span></span><span class="math-row"><span class="math-operator">&#x22F1;</span></span><span class="math-row"><span class="math-operator">&#x22EE;</span></span><span class="math-row"><span class="math-identifier">a</span><span class="math-subsup"><span class="math-smaller">&zwj;</span><span class="math-smaller"><span class="math-row"><span class="math-identifier">m</span><span class="math-number">1</span></span></span></span></span><span class="math-row"><span class="math-operator">&#x22EF;</span></span><span class="math-row"><span class="math-identifier">a</span><span class="math-subsup"><span class="math-smaller">&zwj;</span><span class="math-smaller"><span class="math-row"><span class="math-identifier">m</span><span class="math-identifier">n</span></span></span></span></span></span><span class="math-brace" style="font-size: 300%;">)</span></span></span></span>'
100
- },
101
- 'sum_(k=1)^n k = 1+2+ cdots +n=(n(n+1))/2' =>
102
- {
103
- :mathml => '<math><munderover><mo>&#x2211;</mo><mrow><mi>k</mi><mo>=</mo><mn>1</mn></mrow><mi>n</mi></munderover><mi>k</mi><mo>=</mo><mn>1</mn><mo>+</mo><mn>2</mn><mo>+</mo><mo>&#x22EF;</mo><mo>+</mo><mi>n</mi><mo>=</mo><mfrac><mrow><mi>n</mi><mrow><mo>(</mo><mi>n</mi><mo>+</mo><mn>1</mn><mo>)</mo></mrow></mrow><mn>2</mn></mfrac></math>',
104
- :html => '<span class="math-inline"><span class="math-row"><span class="math-blank">&zwj;</span><span class="math-underover"><span class="math-smaller"><span class="math-identifier">n</span></span><span class="math-operator">&#x2211;</span><span class="math-smaller"><span class="math-row"><span class="math-identifier">k</span><span class="math-operator">=</span><span class="math-number">1</span></span></span></span><span class="math-identifier">k</span><span class="math-operator">=</span><span class="math-number">1</span><span class="math-operator">+</span><span class="math-number">2</span><span class="math-operator">+</span><span class="math-operator">&#x22EF;</span><span class="math-operator">+</span><span class="math-identifier">n</span><span class="math-operator">=</span><span class="math-blank">&zwj;</span><span class="math-fraction"><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-row"><span class="math-identifier">n</span><span class="math-row"><span class="math-brace">(</span><span class="math-row"><span class="math-identifier">n</span><span class="math-operator">+</span><span class="math-number">1</span></span><span class="math-brace">)</span></span></span></span></span></span></span><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-number">2</span></span></span></span></span></span></span></span>'
105
- },
106
- '"Скорость"=("Расстояние")/("Время")' =>
107
- {
108
- :mathml => '<math><mtext>Скорость</mtext><mo>=</mo><mfrac><mtext>Расстояние</mtext><mtext>Время</mtext></mfrac></math>',
109
- :html => '<span class="math-inline"><span class="math-row"><span class="math-text">Скорость</span><span class="math-operator">=</span><span class="math-blank">&zwj;</span><span class="math-fraction"><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-row"><span class="math-text">Расстояние</span></span></span></span></span></span><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-row"><span class="math-text">Время</span></span></span></span></span></span></span></span></span>'
110
- },
111
- 'bb (a + b) + cc c = fr (d^n)' =>
112
- {
113
- :mathml => '<math><mstyle mathvariant="bold"><mrow><mi>a</mi><mo>+</mo><mi>b</mi></mrow></mstyle><mo>+</mo><mstyle mathvariant="script"><mi>c</mi></mstyle><mo>=</mo><mstyle mathvariant="fraktur"><msup><mi>d</mi><mi>n</mi></msup></mstyle></math>',
114
- :html => 'Unsupported'
115
- },
116
- 'max()' =>
117
- {
118
- :mathml => '<math><mo>max</mo><mrow><mo>(</mo><mo>)</mo></mrow></math>',
119
- :html => '<span class="math-inline"><span class="math-row"><span class="math-operator">max</span><span class="math-row"><span class="math-brace">(</span><span class="math-brace">)</span></span></span></span>'
120
- }
121
- }
122
-
123
- version = RUBY_VERSION.split('.').map { |s| s.to_i }
124
-
125
- if version[0] > 1 || version[1] > 8
126
- TEST_CASES['Скорость=(Расстояние)/(Время)'] =
127
- {
128
- :mathml => '<math><mi>С</mi><mi>к</mi><mi>о</mi><mi>р</mi><mi>о</mi><mi>с</mi><mi>т</mi><mi>ь</mi><mo>=</mo><mfrac><mrow><mi>Р</mi><mi>а</mi><mi>с</mi><mi>с</mi><mi>т</mi><mi>о</mi><mi>я</mi><mi>н</mi><mi>и</mi><mi>е</mi></mrow><mrow><mi>В</mi><mi>р</mi><mi>е</mi><mi>м</mi><mi>я</mi></mrow></mfrac></math>',
129
- :html => '<span class="math-inline"><span class="math-row"><span class="math-identifier">С</span><span class="math-identifier">к</span><span class="math-identifier">о</span><span class="math-identifier">р</span><span class="math-identifier">о</span><span class="math-identifier">с</span><span class="math-identifier">т</span><span class="math-identifier">ь</span><span class="math-operator">=</span><span class="math-blank">&zwj;</span><span class="math-fraction"><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-row"><span class="math-identifier">Р</span><span class="math-identifier">а</span><span class="math-identifier">с</span><span class="math-identifier">с</span><span class="math-identifier">т</span><span class="math-identifier">о</span><span class="math-identifier">я</span><span class="math-identifier">н</span><span class="math-identifier">и</span><span class="math-identifier">е</span></span></span></span></span></span><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-row"><span class="math-identifier">В</span><span class="math-identifier">р</span><span class="math-identifier">е</span><span class="math-identifier">м</span><span class="math-identifier">я</span></span></span></span></span></span></span></span></span>'
130
- }
131
- end
132
7
 
133
- module AsciiMathHelper
134
- def expect_mathml(asciimath, mathml)
135
- expect(AsciiMath.parse(asciimath).to_mathml).to eq(mathml)
8
+ module Xml
9
+ def self.mathml2_xsd
10
+ @schema ||= File.open(File.expand_path('../schema/mathml2/mathml2.xsd', __FILE__)) { |io| Nokogiri::XML::Schema(io) }
136
11
  end
137
-
138
- def expect_html(asciimath, html)
139
- expect(AsciiMath.parse(asciimath).to_html).to eq(html)
12
+
13
+ def self.mathml3_xsd
14
+ @schema ||= File.open(File.expand_path('../schema/mathml3/mathml3.xsd', __FILE__)) { |io| Nokogiri::XML::Schema(io) }
140
15
  end
141
- end
142
16
 
143
- RSpec.configure do |c|
144
- c.include AsciiMathHelper
17
+ def self.parse(content)
18
+ Nokogiri::XML(content)
19
+ end
145
20
  end
146
21
 
147
- describe "AsciiMath::MathMLBuilder" do
148
- TEST_CASES.each_pair do |asciimath, output|
149
- it "should produce identical output to asciimathml.js for '#{asciimath}'" do
150
- expect_mathml(asciimath, output[:mathml])
151
- end
152
- if output[:html] != "Unsupported"
153
- it "should produce html that looks like the output from asciimathml.js for '#{asciimath}'" do
154
- expect_html(asciimath, output[:html])
22
+ def should_generate(expected_output)
23
+ Proc.new { |example|
24
+ parsed = AsciiMath.parse(example.description)
25
+ variant = example.metadata[:variant]
26
+ if variant
27
+ if expected_output.key?(variant)
28
+ expected = expected_output[variant]
29
+ case variant
30
+ when :ast
31
+ expect(parsed.ast).to eq(expected)
32
+ when :mathml
33
+ expect(parsed.to_mathml).to eq(expected)
34
+ xml_dom = Xml.parse(parsed.to_mathml(:xmlns => 'http://www.w3.org/1998/Math/MathML'))
35
+ Xml.mathml2_xsd.validate(xml_dom).each do |error|
36
+ fail(error.message)
37
+ end
38
+ Xml.mathml3_xsd.validate(xml_dom).each do |error|
39
+ fail(error.message)
40
+ end
41
+ when :mathml_word
42
+ expect(::AsciiMath::MathMLBuilder.new(:msword => true).append_expression(parsed.ast).to_s).to eq(expected)
43
+ when :html
44
+ expect(parsed.to_html).to eq(expected)
45
+ when :latex
46
+ expect(parsed.to_latex).to eq(expected)
47
+ else
48
+ skip("Unsupported output variant '#{variant}'")
49
+ end
50
+ else
51
+ skip("No example output provided for '#{variant}'")
155
52
  end
53
+ else
54
+ skip('No known output variant found')
156
55
  end
56
+ }
57
+ end
58
+
59
+ RSpec.shared_examples 'AsciiMath Examples' do
60
+ class << self
61
+ include ::AsciiMath::ASTHelper
157
62
  end
158
63
 
159
- it 'should not generate mo elements for {: and :}' do
160
- expect_mathml '{:(a,b),(c,d):}', '<math><mrow><mtable><mtr><mtd><mi>a</mi></mtd><mtd><mi>b</mi></mtd></mtr><mtr><mtd><mi>c</mi></mtd><mtd><mi>d</mi></mtd></mtr></mtable></mrow></math>'
64
+ example('underset(_)(hat A) = hat A exp j vartheta_0', &should_generate(
65
+ :ast => seq(
66
+ binary(
67
+ symbol('underset'),
68
+ group(symbol('_')),
69
+ group(unary(symbol('hat'), 'A'))
70
+ ),
71
+ symbol('='),
72
+ unary(symbol('hat'), 'A'),
73
+ symbol('exp'),
74
+ 'j',
75
+ sub(symbol('vartheta'), '0')
76
+ ),
77
+ :mathml => '<math><munder><mover><mi>A</mi><mo>^</mo></mover><mo>_</mo></munder><mo>=</mo><mover><mi>A</mi><mo>^</mo></mover><mi>exp</mi><mi>j</mi><msub><mi>&#x3D1;</mi><mn>0</mn></msub></math>',
78
+ :mathml_word => '<math><munder><mrow><mover><mrow><mi>A</mi></mrow><mrow><mo>^</mo></mrow></mover></mrow><mrow><mo>_</mo></mrow></munder><mo>=</mo><mover><mrow><mi>A</mi></mrow><mrow><mo>^</mo></mrow></mover><mi>exp</mi><mi>j</mi><msub><mrow><mi>&#x3D1;</mi></mrow><mrow><mn>0</mn></mrow></msub></math>',
79
+ :latex => '\\underset{\\text{–}}{\\hat{A}} = \\hat{A} \\exp j \\vartheta_0'
80
+ ))
81
+
82
+ example('x+b/(2a)<+-sqrt((b^2)/(4a^2)-c/a)', &should_generate(
83
+ :ast => seq(
84
+ 'x',
85
+ symbol('+'),
86
+ infix('b', symbol('/'), grseq('2', 'a')),
87
+ symbol('<'),
88
+ symbol('+-'),
89
+ unary(
90
+ symbol('sqrt'),
91
+ grseq(
92
+ infix(
93
+ group(sup('b', '2')),
94
+ symbol('/'),
95
+ grseq('4', sup('a', '2'))
96
+ ),
97
+ symbol('-'),
98
+ infix('c', symbol('/'), 'a')
99
+ )
100
+ )
101
+ ),
102
+ :mathml => '<math><mi>x</mi><mo>+</mo><mfrac><mi>b</mi><mrow><mn>2</mn><mi>a</mi></mrow></mfrac><mo>&lt;</mo><mo>&#xB1;</mo><msqrt><mrow><mfrac><msup><mi>b</mi><mn>2</mn></msup><mrow><mn>4</mn><msup><mi>a</mi><mn>2</mn></msup></mrow></mfrac><mo>&#x2212;</mo><mfrac><mi>c</mi><mi>a</mi></mfrac></mrow></msqrt></math>',
103
+ :latex => 'x + \\frac{b}{2 a} < \\pm \\sqrt{\\frac{b^2}{4 a^2} - \\frac{c}{a}}',
104
+ ))
105
+
106
+ example('a^2 + b^2 = c^2', &should_generate(
107
+ :ast => seq(
108
+ sup('a', '2'),
109
+ symbol('+'),
110
+ sup('b', '2'),
111
+ symbol('='),
112
+ sup('c', '2')
113
+ ),
114
+ :mathml => '<math><msup><mi>a</mi><mn>2</mn></msup><mo>+</mo><msup><mi>b</mi><mn>2</mn></msup><mo>=</mo><msup><mi>c</mi><mn>2</mn></msup></math>',
115
+ :html => '<span class="math-inline"><span class="math-identifier">a</span><span class="math-subsup"><span class="math-smaller"><span class="math-number">2</span></span><span class="math-smaller">&#x200D;</span></span><span class="math-operator">+</span><span class="math-identifier">b</span><span class="math-subsup"><span class="math-smaller"><span class="math-number">2</span></span><span class="math-smaller">&#x200D;</span></span><span class="math-operator">=</span><span class="math-identifier">c</span><span class="math-subsup"><span class="math-smaller"><span class="math-number">2</span></span><span class="math-smaller">&#x200D;</span></span></span>',
116
+ :latex => 'a^2 + b^2 = c^2',
117
+
118
+ ))
119
+
120
+ example('x = (-b+-sqrt(b^2-4ac))/(2a)', &should_generate(
121
+ :ast => seq(
122
+ 'x',
123
+ symbol('='),
124
+ infix(
125
+ grseq(
126
+ symbol('-'), 'b',
127
+ symbol('+-'),
128
+ unary(symbol('sqrt'), grseq(sup('b', '2'), symbol('-'), '4', 'a', 'c'))
129
+ ),
130
+ symbol('/'),
131
+ grseq('2', 'a'),
132
+ )
133
+ ),
134
+ :mathml => '<math><mi>x</mi><mo>=</mo><mfrac><mrow><mo>&#x2212;</mo><mi>b</mi><mo>&#xB1;</mo><msqrt><mrow><msup><mi>b</mi><mn>2</mn></msup><mo>&#x2212;</mo><mn>4</mn><mi>a</mi><mi>c</mi></mrow></msqrt></mrow><mrow><mn>2</mn><mi>a</mi></mrow></mfrac></math>',
135
+ :latex => 'x = \\frac{- b \\pm \\sqrt{b^2 - 4 a c}}{2 a}',
136
+ ))
137
+
138
+ example('m = (y_2 - y_1)/(x_2 - x_1) = (Deltay)/(Deltax)', &should_generate(
139
+ :ast => seq(
140
+ 'm',
141
+ symbol('='),
142
+ infix(grseq(sub('y', '2'), symbol('-'), sub('y', '1')), symbol('/'), grseq(sub('x', '2'), symbol('-'), sub('x', '1'))),
143
+ symbol('='),
144
+ infix(grseq(symbol('Delta'), 'y'), symbol('/'), grseq(symbol('Delta'), 'x')),
145
+ ),
146
+ :mathml => '<math><mi>m</mi><mo>=</mo><mfrac><mrow><msub><mi>y</mi><mn>2</mn></msub><mo>&#x2212;</mo><msub><mi>y</mi><mn>1</mn></msub></mrow><mrow><msub><mi>x</mi><mn>2</mn></msub><mo>&#x2212;</mo><msub><mi>x</mi><mn>1</mn></msub></mrow></mfrac><mo>=</mo><mfrac><mrow><mo>&#x394;</mo><mi>y</mi></mrow><mrow><mo>&#x394;</mo><mi>x</mi></mrow></mfrac></math>',
147
+ :html => '<span class="math-inline"><span class="math-identifier">m</span><span class="math-operator">=</span><span class="math-blank">&#x200D;</span><span class="math-fraction"><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-row"><span class="math-identifier">y</span><span class="math-subsup"><span class="math-smaller">&#x200D;</span><span class="math-smaller"><span class="math-number">2</span></span></span><span class="math-operator">&#x2212;</span><span class="math-identifier">y</span><span class="math-subsup"><span class="math-smaller">&#x200D;</span><span class="math-smaller"><span class="math-number">1</span></span></span></span></span></span></span></span><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-row"><span class="math-identifier">x</span><span class="math-subsup"><span class="math-smaller">&#x200D;</span><span class="math-smaller"><span class="math-number">2</span></span></span><span class="math-operator">&#x2212;</span><span class="math-identifier">x</span><span class="math-subsup"><span class="math-smaller">&#x200D;</span><span class="math-smaller"><span class="math-number">1</span></span></span></span></span></span></span></span></span><span class="math-operator">=</span><span class="math-blank">&#x200D;</span><span class="math-fraction"><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-row"><span class="math-operator">&#x394;</span><span class="math-identifier">y</span></span></span></span></span></span><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-row"><span class="math-operator">&#x394;</span><span class="math-identifier">x</span></span></span></span></span></span></span></span>',
148
+ :latex => 'm = \\frac{y_2 - y_1}{x_2 - x_1} = \\frac{\\Delta y}{\\Delta x}',
149
+ ))
150
+
151
+ example('f\'(x) = lim_(Deltax->0)(f(x+Deltax)-f(x))/(Deltax)', &should_generate(
152
+ :ast => seq(
153
+ symbol('f'),
154
+ symbol('\''),
155
+ paren('x'),
156
+ symbol('='),
157
+ sub(
158
+ symbol('lim'),
159
+ grseq(symbol('Delta'), 'x', symbol('->'), '0')
160
+ ),
161
+ infix(
162
+ grseq(symbol('f'), paren(seq('x', symbol('+'), symbol('Delta'), 'x')), symbol('-'), symbol('f'), paren('x')),
163
+ symbol('/'),
164
+ grseq(symbol('Delta'), 'x')
165
+ )
166
+ ),
167
+ :mathml => '<math><mi>f</mi><mo>&#x2032;</mo><mrow><mo>(</mo><mi>x</mi><mo>)</mo></mrow><mo>=</mo><munder><mo>lim</mo><mrow><mo>&#x394;</mo><mi>x</mi><mo>&#x2192;</mo><mn>0</mn></mrow></munder><mfrac><mrow><mi>f</mi><mrow><mo>(</mo><mrow><mi>x</mi><mo>+</mo><mo>&#x394;</mo><mi>x</mi></mrow><mo>)</mo></mrow><mo>&#x2212;</mo><mi>f</mi><mrow><mo>(</mo><mi>x</mi><mo>)</mo></mrow></mrow><mrow><mo>&#x394;</mo><mi>x</mi></mrow></mfrac></math>',
168
+ :html => '<span class="math-inline"><span class="math-identifier">f</span><span class="math-operator">&#x2032;</span><span class="math-row"><span class="math-brace">(</span><span class="math-identifier">x</span><span class="math-brace">)</span></span><span class="math-operator">=</span><span class="math-blank">&#x200D;</span><span class="math-underover"><span class="math-smaller"><span class="math-blank">&#x200D;</span></span><span class="math-operator">lim</span><span class="math-smaller"><span class="math-row"><span class="math-operator">&#x394;</span><span class="math-identifier">x</span><span class="math-operator">&#x2192;</span><span class="math-number">0</span></span></span></span><span class="math-blank">&#x200D;</span><span class="math-fraction"><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-row"><span class="math-identifier">f</span><span class="math-row"><span class="math-brace">(</span><span class="math-identifier">x</span><span class="math-operator">+</span><span class="math-operator">&#x394;</span><span class="math-identifier">x</span><span class="math-brace">)</span></span><span class="math-operator">&#x2212;</span><span class="math-identifier">f</span><span class="math-row"><span class="math-brace">(</span><span class="math-identifier">x</span><span class="math-brace">)</span></span></span></span></span></span></span><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-row"><span class="math-operator">&#x394;</span><span class="math-identifier">x</span></span></span></span></span></span></span></span>',
169
+ :latex => 'f \' ( x ) = \\lim_{\\Delta x \\rightarrow 0} \\frac{f \\left ( x + \\Delta x \\right ) - f ( x )}{\\Delta x}',
170
+ ))
171
+
172
+ example('d/dx [x^n] = nx^(n - 1)', &should_generate(
173
+ :ast => seq(
174
+ infix('d', symbol('/'), symbol('dx')),
175
+ paren(symbol('['), sup('x', 'n'), symbol(']')),
176
+ symbol('='),
177
+ 'n',
178
+ sup('x', grseq('n', symbol('-'), '1'))
179
+ ),
180
+ :mathml => '<math><mfrac><mi>d</mi><mi>dx</mi></mfrac><mrow><mo>[</mo><msup><mi>x</mi><mi>n</mi></msup><mo>]</mo></mrow><mo>=</mo><mi>n</mi><msup><mi>x</mi><mrow><mi>n</mi><mo>&#x2212;</mo><mn>1</mn></mrow></msup></math>',
181
+ :html => '<span class="math-inline"><span class="math-blank">&#x200D;</span><span class="math-fraction"><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-identifier">d</span></span></span></span></span><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-identifier">dx</span></span></span></span></span></span><span class="math-row"><span class="math-brace">[</span><span class="math-identifier">x</span><span class="math-subsup"><span class="math-smaller"><span class="math-identifier">n</span></span><span class="math-smaller">&#x200D;</span></span><span class="math-brace">]</span></span><span class="math-operator">=</span><span class="math-identifier">n</span><span class="math-identifier">x</span><span class="math-subsup"><span class="math-smaller"><span class="math-row"><span class="math-identifier">n</span><span class="math-operator">&#x2212;</span><span class="math-number">1</span></span></span><span class="math-smaller">&#x200D;</span></span></span>',
182
+ :latex => '\\frac{d}{dx} [ x^n ] = n x^{n - 1}',
183
+ ))
184
+
185
+ example('int_a^b f(x) dx = [F(x)]_a^b = F(b) - F(a)', &should_generate(
186
+ :ast => seq(
187
+ subsup(symbol('int'), 'a', 'b'),
188
+ symbol('f'),
189
+ paren('x'),
190
+ symbol('dx'),
191
+ symbol('='),
192
+ subsup(paren(symbol('['), seq('F', paren('x')), symbol(']')), 'a', 'b'),
193
+ symbol('='),
194
+ 'F', paren('b'),
195
+ symbol('-'),
196
+ 'F', paren('a')
197
+ ),
198
+ :mathml => '<math><msubsup><mo>&#x222B;</mo><mi>a</mi><mi>b</mi></msubsup><mi>f</mi><mrow><mo>(</mo><mi>x</mi><mo>)</mo></mrow><mi>dx</mi><mo>=</mo><msubsup><mrow><mo>[</mo><mrow><mi>F</mi><mrow><mo>(</mo><mi>x</mi><mo>)</mo></mrow></mrow><mo>]</mo></mrow><mi>a</mi><mi>b</mi></msubsup><mo>=</mo><mi>F</mi><mrow><mo>(</mo><mi>b</mi><mo>)</mo></mrow><mo>&#x2212;</mo><mi>F</mi><mrow><mo>(</mo><mi>a</mi><mo>)</mo></mrow></math>',
199
+ :html => '<span class="math-inline"><span class="math-operator">&#x222B;</span><span class="math-subsup"><span class="math-smaller"><span class="math-identifier">b</span></span><span class="math-smaller"><span class="math-identifier">a</span></span></span><span class="math-identifier">f</span><span class="math-row"><span class="math-brace">(</span><span class="math-identifier">x</span><span class="math-brace">)</span></span><span class="math-identifier">dx</span><span class="math-operator">=</span><span class="math-row"><span class="math-brace">[</span><span class="math-identifier">F</span><span class="math-row"><span class="math-brace">(</span><span class="math-identifier">x</span><span class="math-brace">)</span></span><span class="math-brace">]</span></span><span class="math-subsup"><span class="math-smaller"><span class="math-identifier">b</span></span><span class="math-smaller"><span class="math-identifier">a</span></span></span><span class="math-operator">=</span><span class="math-identifier">F</span><span class="math-row"><span class="math-brace">(</span><span class="math-identifier">b</span><span class="math-brace">)</span></span><span class="math-operator">&#x2212;</span><span class="math-identifier">F</span><span class="math-row"><span class="math-brace">(</span><span class="math-identifier">a</span><span class="math-brace">)</span></span></span>',
200
+ :latex => '\\int_a^b f ( x ) dx = {\\left [ F ( x ) \\right ]}_a^b = F ( b ) - F ( a )',
201
+ ))
202
+
203
+ example('int_a^b f(x) dx = f(c)(b - a)', &should_generate(
204
+ :ast => seq(
205
+ subsup(symbol('int'), 'a', 'b'),
206
+ symbol('f'),
207
+ paren('x'),
208
+ symbol('dx'),
209
+ symbol('='),
210
+ symbol('f'),
211
+ paren('c'),
212
+ paren(seq('b', symbol('-'), 'a')),
213
+ ),
214
+ :mathml => '<math><msubsup><mo>&#x222B;</mo><mi>a</mi><mi>b</mi></msubsup><mi>f</mi><mrow><mo>(</mo><mi>x</mi><mo>)</mo></mrow><mi>dx</mi><mo>=</mo><mi>f</mi><mrow><mo>(</mo><mi>c</mi><mo>)</mo></mrow><mrow><mo>(</mo><mrow><mi>b</mi><mo>&#x2212;</mo><mi>a</mi></mrow><mo>)</mo></mrow></math>',
215
+ :html => '<span class="math-inline"><span class="math-operator">&#x222B;</span><span class="math-subsup"><span class="math-smaller"><span class="math-identifier">b</span></span><span class="math-smaller"><span class="math-identifier">a</span></span></span><span class="math-identifier">f</span><span class="math-row"><span class="math-brace">(</span><span class="math-identifier">x</span><span class="math-brace">)</span></span><span class="math-identifier">dx</span><span class="math-operator">=</span><span class="math-identifier">f</span><span class="math-row"><span class="math-brace">(</span><span class="math-identifier">c</span><span class="math-brace">)</span></span><span class="math-row"><span class="math-brace">(</span><span class="math-identifier">b</span><span class="math-operator">&#x2212;</span><span class="math-identifier">a</span><span class="math-brace">)</span></span></span>',
216
+ :latex => '\\int_a^b f ( x ) dx = f ( c ) ( b - a )',
217
+ ))
218
+
219
+ example('ax^2 + bx + c = 0', &should_generate(
220
+ :ast => seq(
221
+ 'a',
222
+ sup('x', '2'),
223
+ symbol('+'),
224
+ 'b',
225
+ 'x',
226
+ symbol('+'),
227
+ 'c',
228
+ symbol('='),
229
+ '0'
230
+ ),
231
+ :mathml => '<math><mi>a</mi><msup><mi>x</mi><mn>2</mn></msup><mo>+</mo><mi>b</mi><mi>x</mi><mo>+</mo><mi>c</mi><mo>=</mo><mn>0</mn></math>',
232
+ :html => '<span class="math-inline"><span class="math-identifier">a</span><span class="math-identifier">x</span><span class="math-subsup"><span class="math-smaller"><span class="math-number">2</span></span><span class="math-smaller">&#x200D;</span></span><span class="math-operator">+</span><span class="math-identifier">b</span><span class="math-identifier">x</span><span class="math-operator">+</span><span class="math-identifier">c</span><span class="math-operator">=</span><span class="math-number">0</span></span>',
233
+ :latex => 'a x^2 + b x + c = 0',
234
+ ))
235
+
236
+ example('"average value"=1/(b-a) int_a^b f(x) dx', &should_generate(
237
+ :ast => seq(
238
+ 'average value',
239
+ symbol('='),
240
+ infix('1', symbol('/'), grseq('b', symbol('-'), 'a')),
241
+ subsup(symbol('int'), 'a', 'b'),
242
+ symbol('f'),
243
+ paren('x'),
244
+ symbol('dx')
245
+ ),
246
+ :mathml => '<math><mtext>average value</mtext><mo>=</mo><mfrac><mn>1</mn><mrow><mi>b</mi><mo>&#x2212;</mo><mi>a</mi></mrow></mfrac><msubsup><mo>&#x222B;</mo><mi>a</mi><mi>b</mi></msubsup><mi>f</mi><mrow><mo>(</mo><mi>x</mi><mo>)</mo></mrow><mi>dx</mi></math>',
247
+ :html => '<span class="math-inline"><span class="math-text">average value</span><span class="math-operator">=</span><span class="math-blank">&#x200D;</span><span class="math-fraction"><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-number">1</span></span></span></span></span><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-row"><span class="math-identifier">b</span><span class="math-operator">&#x2212;</span><span class="math-identifier">a</span></span></span></span></span></span></span><span class="math-operator">&#x222B;</span><span class="math-subsup"><span class="math-smaller"><span class="math-identifier">b</span></span><span class="math-smaller"><span class="math-identifier">a</span></span></span><span class="math-identifier">f</span><span class="math-row"><span class="math-brace">(</span><span class="math-identifier">x</span><span class="math-brace">)</span></span><span class="math-identifier">dx</span></span>',
248
+ :latex => '\\text{average value} = \\frac{1}{b - a} \\int_a^b f ( x ) dx',
249
+ ))
250
+
251
+ example('d/dx[int_a^x f(t) dt] = f(x)', &should_generate(
252
+ :ast => seq(
253
+ infix('d', symbol('/'), symbol('dx')),
254
+ paren(
255
+ symbol('['),
256
+ seq(subsup(symbol('int'), 'a', 'x'), symbol('f'), paren('t'), symbol('dt')),
257
+ symbol(']')
258
+ ),
259
+ symbol('='),
260
+ symbol('f'),
261
+ paren('x'),
262
+ ),
263
+ :mathml => '<math><mfrac><mi>d</mi><mi>dx</mi></mfrac><mrow><mo>[</mo><mrow><msubsup><mo>&#x222B;</mo><mi>a</mi><mi>x</mi></msubsup><mi>f</mi><mrow><mo>(</mo><mi>t</mi><mo>)</mo></mrow><mi>dt</mi></mrow><mo>]</mo></mrow><mo>=</mo><mi>f</mi><mrow><mo>(</mo><mi>x</mi><mo>)</mo></mrow></math>',
264
+ :html => '<span class="math-inline"><span class="math-blank">&#x200D;</span><span class="math-fraction"><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-identifier">d</span></span></span></span></span><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-identifier">dx</span></span></span></span></span></span><span class="math-row"><span class="math-brace">[</span><span class="math-operator">&#x222B;</span><span class="math-subsup"><span class="math-smaller"><span class="math-identifier">x</span></span><span class="math-smaller"><span class="math-identifier">a</span></span></span><span class="math-identifier">f</span><span class="math-row"><span class="math-brace">(</span><span class="math-identifier">t</span><span class="math-brace">)</span></span><span class="math-identifier">dt</span><span class="math-brace">]</span></span><span class="math-operator">=</span><span class="math-identifier">f</span><span class="math-row"><span class="math-brace">(</span><span class="math-identifier">x</span><span class="math-brace">)</span></span></span>',
265
+ :latex => '\\frac{d}{dx} \\left [ \\int_a^x f ( t ) dt \\right ] = f ( x )',
266
+ ))
267
+
268
+ example('hat(ab) bar(xy) ul(A) vec(v)', &should_generate(
269
+ :ast => seq(
270
+ unary(symbol('hat'), grseq('a', 'b')),
271
+ unary(symbol('bar'), grseq('x', 'y')),
272
+ unary(symbol('ul'), group('A')),
273
+ unary(symbol('vec'), group('v')),
274
+ ),
275
+ :mathml => '<math><mover><mrow><mi>a</mi><mi>b</mi></mrow><mo>^</mo></mover><mover><mrow><mi>x</mi><mi>y</mi></mrow><mo>&#xAF;</mo></mover><munder><mi>A</mi><mo>_</mo></munder><mover><mi>v</mi><mo>&#x2192;</mo></mover></math>',
276
+ :html => '<span class="math-inline"><span class="math-blank">&#x200D;</span><span class="math-underover"><span class="math-smaller"><span class="math-operator">^</span></span><span class="math-row"><span class="math-identifier">a</span><span class="math-identifier">b</span></span><span class="math-smaller"><span class="math-blank">&#x200D;</span></span></span><span class="math-blank">&#x200D;</span><span class="math-underover"><span class="math-smaller"><span class="math-operator">&#xAF;</span></span><span class="math-row"><span class="math-identifier">x</span><span class="math-identifier">y</span></span><span class="math-smaller"><span class="math-blank">&#x200D;</span></span></span><span class="math-blank">&#x200D;</span><span class="math-underover"><span class="math-smaller"><span class="math-blank">&#x200D;</span></span><span class="math-identifier">A</span><span class="math-smaller"><span class="math-operator">_</span></span></span><span class="math-blank">&#x200D;</span><span class="math-underover"><span class="math-smaller"><span class="math-operator">&#x2192;</span></span><span class="math-identifier">v</span><span class="math-smaller"><span class="math-blank">&#x200D;</span></span></span></span>',
277
+ :latex => '\\hat{a b} \\overline{x y} \\underline{A} \\vec{v}',
278
+ ))
279
+
280
+ example('z_12^34', &should_generate(
281
+ :ast => subsup('z', '12', '34'),
282
+ :mathml => '<math><msubsup><mi>z</mi><mn>12</mn><mn>34</mn></msubsup></math>',
283
+ :html => '<span class="math-inline"><span class="math-identifier">z</span><span class="math-subsup"><span class="math-smaller"><span class="math-number">34</span></span><span class="math-smaller"><span class="math-number">12</span></span></span></span>',
284
+ :latex => 'z_{12}^{34}',
285
+ ))
286
+
287
+ example('lim_(x->c)(f(x)-f(c))/(x-c)', &should_generate(
288
+ :ast => seq(
289
+ sub(symbol('lim'), grseq('x', symbol('->'), 'c')),
290
+ infix(
291
+ grseq(symbol('f'), paren('x'), symbol('-'), symbol('f'), paren('c')),
292
+ symbol('/'),
293
+ grseq('x', symbol('-'), 'c')
294
+ )
295
+ ),
296
+ :mathml => '<math><munder><mo>lim</mo><mrow><mi>x</mi><mo>&#x2192;</mo><mi>c</mi></mrow></munder><mfrac><mrow><mi>f</mi><mrow><mo>(</mo><mi>x</mi><mo>)</mo></mrow><mo>&#x2212;</mo><mi>f</mi><mrow><mo>(</mo><mi>c</mi><mo>)</mo></mrow></mrow><mrow><mi>x</mi><mo>&#x2212;</mo><mi>c</mi></mrow></mfrac></math>',
297
+ :html => '<span class="math-inline"><span class="math-blank">&#x200D;</span><span class="math-underover"><span class="math-smaller"><span class="math-blank">&#x200D;</span></span><span class="math-operator">lim</span><span class="math-smaller"><span class="math-row"><span class="math-identifier">x</span><span class="math-operator">&#x2192;</span><span class="math-identifier">c</span></span></span></span><span class="math-blank">&#x200D;</span><span class="math-fraction"><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-row"><span class="math-identifier">f</span><span class="math-row"><span class="math-brace">(</span><span class="math-identifier">x</span><span class="math-brace">)</span></span><span class="math-operator">&#x2212;</span><span class="math-identifier">f</span><span class="math-row"><span class="math-brace">(</span><span class="math-identifier">c</span><span class="math-brace">)</span></span></span></span></span></span></span><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-row"><span class="math-identifier">x</span><span class="math-operator">&#x2212;</span><span class="math-identifier">c</span></span></span></span></span></span></span></span>',
298
+ :latex => '\\lim_{x \\rightarrow c} \\frac{f ( x ) - f ( c )}{x - c}',
299
+ ))
300
+
301
+ example('int_0^(pi/2) g(x) dx', &should_generate(
302
+ :ast => seq(
303
+ subsup(symbol('int'), '0', group(infix(symbol('pi'), symbol('/'), '2'))),
304
+ symbol('g'), paren('x'),
305
+ symbol('dx')
306
+ ),
307
+ :mathml => '<math><msubsup><mo>&#x222B;</mo><mn>0</mn><mfrac><mi>&#x3C0;</mi><mn>2</mn></mfrac></msubsup><mi>g</mi><mrow><mo>(</mo><mi>x</mi><mo>)</mo></mrow><mi>dx</mi></math>',
308
+ :html => '<span class="math-inline"><span class="math-operator">&#x222B;</span><span class="math-subsup"><span class="math-smaller"><span class="math-blank">&#x200D;</span><span class="math-fraction"><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-identifier">&#x3C0;</span></span></span></span></span><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-number">2</span></span></span></span></span></span></span><span class="math-smaller"><span class="math-number">0</span></span></span><span class="math-identifier">g</span><span class="math-row"><span class="math-brace">(</span><span class="math-identifier">x</span><span class="math-brace">)</span></span><span class="math-identifier">dx</span></span>',
309
+ :latex => '\\int_0^{\\frac{\\pi}{2}} g ( x ) dx',
310
+ ))
311
+
312
+ example('sum_(n=0)^oo a_n', &should_generate(
313
+ :ast => seq(
314
+ subsup(symbol('sum'), grseq('n', symbol('='), '0'), symbol('oo'),),
315
+ sub('a', 'n')
316
+ ),
317
+ :mathml => '<math><munderover><mo>&#x2211;</mo><mrow><mi>n</mi><mo>=</mo><mn>0</mn></mrow><mo>&#x221E;</mo></munderover><msub><mi>a</mi><mi>n</mi></msub></math>',
318
+ :html => '<span class="math-inline"><span class="math-blank">&#x200D;</span><span class="math-underover"><span class="math-smaller"><span class="math-operator">&#x221E;</span></span><span class="math-operator">&#x2211;</span><span class="math-smaller"><span class="math-row"><span class="math-identifier">n</span><span class="math-operator">=</span><span class="math-number">0</span></span></span></span><span class="math-identifier">a</span><span class="math-subsup"><span class="math-smaller">&#x200D;</span><span class="math-smaller"><span class="math-identifier">n</span></span></span></span>',
319
+ :latex => '\\sum_{n = 0}^\\infty a_n',
320
+ ))
321
+
322
+ example('((1),(42))', &should_generate(
323
+ :ast => matrix([%w[1], %w[42]]),
324
+ :mathml => '<math><mrow><mo>(</mo><mtable><mtr><mtd><mn>1</mn></mtd></mtr><mtr><mtd><mn>42</mn></mtd></mtr></mtable><mo>)</mo></mrow></math>',
325
+ :html => '<span class="math-inline"><span class="math-row"><span class="math-brace" style="font-size: 200%;">(</span><span class="math-matrix" style="grid-template-columns:repeat(1,1fr);grid-template-rows:repeat(2,1fr);"><span class="math-row"><span class="math-number">1</span></span><span class="math-row"><span class="math-number">42</span></span></span><span class="math-brace" style="font-size: 200%;">)</span></span></span>',
326
+ :latex => '\\left ( \\begin{matrix} 1 \\\\ 42 \\end{matrix} \\right )',
327
+ ))
328
+
329
+ example('((1,2,3),(4,5,6),(7,8,9))', &should_generate(
330
+ :ast => matrix([%w[1 2 3], %w[4 5 6], %w[7 8 9]]),
331
+ :mathml => '<math><mrow><mo>(</mo><mtable><mtr><mtd><mn>1</mn></mtd><mtd><mn>2</mn></mtd><mtd><mn>3</mn></mtd></mtr><mtr><mtd><mn>4</mn></mtd><mtd><mn>5</mn></mtd><mtd><mn>6</mn></mtd></mtr><mtr><mtd><mn>7</mn></mtd><mtd><mn>8</mn></mtd><mtd><mn>9</mn></mtd></mtr></mtable><mo>)</mo></mrow></math>',
332
+ :html => '<span class="math-inline"><span class="math-row"><span class="math-brace" style="font-size: 300%;">(</span><span class="math-matrix" style="grid-template-columns:repeat(3,1fr);grid-template-rows:repeat(3,1fr);"><span class="math-row"><span class="math-number">1</span></span><span class="math-row"><span class="math-number">2</span></span><span class="math-row"><span class="math-number">3</span></span><span class="math-row"><span class="math-number">4</span></span><span class="math-row"><span class="math-number">5</span></span><span class="math-row"><span class="math-number">6</span></span><span class="math-row"><span class="math-number">7</span></span><span class="math-row"><span class="math-number">8</span></span><span class="math-row"><span class="math-number">9</span></span></span><span class="math-brace" style="font-size: 300%;">)</span></span></span>',
333
+ :latex => '\\left ( \\begin{matrix} 1 & 2 & 3 \\\\ 4 & 5 & 6 \\\\ 7 & 8 & 9 \\end{matrix} \\right )',
334
+ ))
335
+
336
+ example('|(a,b),(c,d)|=ad-bc', &should_generate(
337
+ :ast => seq(
338
+ matrix(symbol('|'), [%w(a b), %w(c d)], symbol('|'),),
339
+ symbol('='),
340
+ 'a', 'd',
341
+ symbol('-'),
342
+ 'b', 'c'
343
+ ),
344
+ :mathml => '<math><mrow><mo>|</mo><mtable><mtr><mtd><mi>a</mi></mtd><mtd><mi>b</mi></mtd></mtr><mtr><mtd><mi>c</mi></mtd><mtd><mi>d</mi></mtd></mtr></mtable><mo>|</mo></mrow><mo>=</mo><mi>a</mi><mi>d</mi><mo>&#x2212;</mo><mi>b</mi><mi>c</mi></math>',
345
+ :mathml_word => '<math><mfenced open="|" close="|"><mtable><mtr><mtd><mi>a</mi></mtd><mtd><mi>b</mi></mtd></mtr><mtr><mtd><mi>c</mi></mtd><mtd><mi>d</mi></mtd></mtr></mtable></mfenced><mo>=</mo><mi>a</mi><mi>d</mi><mo>&#x2212;</mo><mi>b</mi><mi>c</mi></math>',
346
+ :html => '<span class="math-inline"><span class="math-row"><span class="math-brace" style="font-size: 200%;">|</span><span class="math-matrix" style="grid-template-columns:repeat(2,1fr);grid-template-rows:repeat(2,1fr);"><span class="math-row"><span class="math-identifier">a</span></span><span class="math-row"><span class="math-identifier">b</span></span><span class="math-row"><span class="math-identifier">c</span></span><span class="math-row"><span class="math-identifier">d</span></span></span><span class="math-brace" style="font-size: 200%;">|</span></span><span class="math-operator">=</span><span class="math-identifier">a</span><span class="math-identifier">d</span><span class="math-operator">&#x2212;</span><span class="math-identifier">b</span><span class="math-identifier">c</span></span>',
347
+ :latex => '\\left | \\begin{matrix} a & b \\\\ c & d \\end{matrix} \\right | = a d - b c',
348
+ ))
349
+
350
+ example('((a_(11), cdots , a_(1n)),(vdots, ddots, vdots),(a_(m1), cdots , a_(mn)))', &should_generate(
351
+ :ast => matrix([
352
+ [sub('a', group('11')), symbol('cdots'), sub('a', grseq('1', 'n'))],
353
+ [symbol('vdots'), symbol('ddots'), symbol('vdots')],
354
+ [sub('a', grseq('m', '1')), symbol('cdots'), sub('a', grseq('m', 'n'))]
355
+ ]),
356
+ :mathml => '<math><mrow><mo>(</mo><mtable><mtr><mtd><msub><mi>a</mi><mn>11</mn></msub></mtd><mtd><mo>&#x22EF;</mo></mtd><mtd><msub><mi>a</mi><mrow><mn>1</mn><mi>n</mi></mrow></msub></mtd></mtr><mtr><mtd><mo>&#x22EE;</mo></mtd><mtd><mo>&#x22F1;</mo></mtd><mtd><mo>&#x22EE;</mo></mtd></mtr><mtr><mtd><msub><mi>a</mi><mrow><mi>m</mi><mn>1</mn></mrow></msub></mtd><mtd><mo>&#x22EF;</mo></mtd><mtd><msub><mi>a</mi><mrow><mi>m</mi><mi>n</mi></mrow></msub></mtd></mtr></mtable><mo>)</mo></mrow></math>',
357
+ :html => '<span class="math-inline"><span class="math-row"><span class="math-brace" style="font-size: 300%;">(</span><span class="math-matrix" style="grid-template-columns:repeat(3,1fr);grid-template-rows:repeat(3,1fr);"><span class="math-row"><span class="math-identifier">a</span><span class="math-subsup"><span class="math-smaller">&#x200D;</span><span class="math-smaller"><span class="math-number">11</span></span></span></span><span class="math-row"><span class="math-operator">&#x22EF;</span></span><span class="math-row"><span class="math-identifier">a</span><span class="math-subsup"><span class="math-smaller">&#x200D;</span><span class="math-smaller"><span class="math-row"><span class="math-number">1</span><span class="math-identifier">n</span></span></span></span></span><span class="math-row"><span class="math-operator">&#x22EE;</span></span><span class="math-row"><span class="math-operator">&#x22F1;</span></span><span class="math-row"><span class="math-operator">&#x22EE;</span></span><span class="math-row"><span class="math-identifier">a</span><span class="math-subsup"><span class="math-smaller">&#x200D;</span><span class="math-smaller"><span class="math-row"><span class="math-identifier">m</span><span class="math-number">1</span></span></span></span></span><span class="math-row"><span class="math-operator">&#x22EF;</span></span><span class="math-row"><span class="math-identifier">a</span><span class="math-subsup"><span class="math-smaller">&#x200D;</span><span class="math-smaller"><span class="math-row"><span class="math-identifier">m</span><span class="math-identifier">n</span></span></span></span></span></span><span class="math-brace" style="font-size: 300%;">)</span></span></span>',
358
+ :latex => '\\left ( \\begin{matrix} a_{11} & \\cdots & a_{1 n} \\\\ \\vdots & \\ddots & \\vdots \\\\ a_{m 1} & \\cdots & a_{m n} \\end{matrix} \\right )',
359
+ ))
360
+
361
+ example('sum_(k=1)^n k = 1+2+ cdots +n=(n(n+1))/2', &should_generate(
362
+ :ast => seq(
363
+ subsup(symbol('sum'), grseq('k', symbol('='), '1'), 'n'),
364
+ 'k',
365
+ symbol('='),
366
+ '1', symbol('+'), '2', symbol('+'), symbol('cdots'), symbol('+'), 'n',
367
+ symbol('='),
368
+ infix(
369
+ grseq('n', paren(seq('n', symbol('+'), '1'))),
370
+ symbol('/'),
371
+ '2'
372
+ )
373
+ ),
374
+ :mathml => '<math><munderover><mo>&#x2211;</mo><mrow><mi>k</mi><mo>=</mo><mn>1</mn></mrow><mi>n</mi></munderover><mi>k</mi><mo>=</mo><mn>1</mn><mo>+</mo><mn>2</mn><mo>+</mo><mo>&#x22EF;</mo><mo>+</mo><mi>n</mi><mo>=</mo><mfrac><mrow><mi>n</mi><mrow><mo>(</mo><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow><mo>)</mo></mrow></mrow><mn>2</mn></mfrac></math>',
375
+ :html => '<span class="math-inline"><span class="math-blank">&#x200D;</span><span class="math-underover"><span class="math-smaller"><span class="math-identifier">n</span></span><span class="math-operator">&#x2211;</span><span class="math-smaller"><span class="math-row"><span class="math-identifier">k</span><span class="math-operator">=</span><span class="math-number">1</span></span></span></span><span class="math-identifier">k</span><span class="math-operator">=</span><span class="math-number">1</span><span class="math-operator">+</span><span class="math-number">2</span><span class="math-operator">+</span><span class="math-operator">&#x22EF;</span><span class="math-operator">+</span><span class="math-identifier">n</span><span class="math-operator">=</span><span class="math-blank">&#x200D;</span><span class="math-fraction"><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-row"><span class="math-identifier">n</span><span class="math-row"><span class="math-brace">(</span><span class="math-identifier">n</span><span class="math-operator">+</span><span class="math-number">1</span><span class="math-brace">)</span></span></span></span></span></span></span><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-number">2</span></span></span></span></span></span></span>',
376
+ :latex => '\\sum_{k = 1}^n k = 1 + 2 + \\cdots + n = \\frac{n ( n + 1 )}{2}',
377
+ ))
378
+
379
+ example('"Скорость"=("Расстояние")/("Время")', &should_generate(
380
+ :ast => seq(
381
+ 'Скорость',
382
+ symbol('='),
383
+ infix(group('Расстояние'), symbol('/'), group('Время'))
384
+ ),
385
+ :mathml => '<math><mtext>&#x421;&#x43A;&#x43E;&#x440;&#x43E;&#x441;&#x442;&#x44C;</mtext><mo>=</mo><mfrac><mtext>&#x420;&#x430;&#x441;&#x441;&#x442;&#x43E;&#x44F;&#x43D;&#x438;&#x435;</mtext><mtext>&#x412;&#x440;&#x435;&#x43C;&#x44F;</mtext></mfrac></math>',
386
+ :html => '<span class="math-inline"><span class="math-text">&#x421;&#x43A;&#x43E;&#x440;&#x43E;&#x441;&#x442;&#x44C;</span><span class="math-operator">=</span><span class="math-blank">&#x200D;</span><span class="math-fraction"><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-text">&#x420;&#x430;&#x441;&#x441;&#x442;&#x43E;&#x44F;&#x43D;&#x438;&#x435;</span></span></span></span></span><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-text">&#x412;&#x440;&#x435;&#x43C;&#x44F;</span></span></span></span></span></span></span>',
387
+ :latex => '\\text{Скорость} = \\frac{\\text{Расстояние}}{\\text{Время}}',
388
+ ))
389
+
390
+ example('bb (a + b) + cc c = fr (d^n)', &should_generate(
391
+ :ast => seq(
392
+ unary(symbol('bb'), grseq('a', symbol('+'), 'b')),
393
+ symbol('+'),
394
+ unary(symbol('cc'), 'c'),
395
+ symbol('='),
396
+ unary(symbol('fr'), group(sup('d', 'n')))
397
+ ),
398
+ :mathml => '<math><mstyle mathvariant="bold"><mrow><mi>a</mi><mo>+</mo><mi>b</mi></mrow></mstyle><mo>+</mo><mstyle mathvariant="script"><mi>c</mi></mstyle><mo>=</mo><mstyle mathvariant="fraktur"><msup><mi>d</mi><mi>n</mi></msup></mstyle></math>',
399
+ :latex => '\\mathbf{a + b} + \\mathscr{c} = \\mathfrak{d^n}',
400
+ ))
401
+
402
+ example('max()', &should_generate(
403
+ :ast => seq(symbol('max'), paren(nil)),
404
+ :mathml => '<math><mo>max</mo><mrow><mo>(</mo><mo>)</mo></mrow></math>',
405
+ :html => '<span class="math-inline"><span class="math-operator">max</span><span class="math-row"><span class="math-brace">(</span><span class="math-brace">)</span></span></span>',
406
+ :latex => '\\max ( )',
407
+ ))
408
+
409
+ example('text("foo")', &should_generate(
410
+ :ast => text('"foo"'),
411
+ :mathml => '<math><mtext>"foo"</mtext></math>',
412
+ :html => '<span class="math-inline"><span class="math-text">"foo"</span></span>',
413
+ :latex => '\\text{"foo"}',
414
+ ))
415
+
416
+ example('ubrace(1 + 2) obrace(3 + 4', &should_generate(
417
+ :ast => seq(
418
+ unary(symbol('ubrace'), grseq('1', symbol('+'), '2')),
419
+ unary(symbol('obrace'), group(symbol('('), seq('3', symbol('+'), '4'), nil))
420
+ ),
421
+ :mathml => '<math><munder><mrow><mn>1</mn><mo>+</mo><mn>2</mn></mrow><mo>&#x23DF;</mo></munder><mover><mrow><mn>3</mn><mo>+</mo><mn>4</mn></mrow><mo>&#x23DE;</mo></mover></math>',
422
+ :latex => '\\underbrace{1 + 2} \\overbrace{3 + 4}',
423
+ ))
424
+
425
+ example('s\'_i = {(- 1, if s_i > s_(i + 1)),( + 1, if s_i <= s_(i + 1)):}', &should_generate(
426
+ :ast => seq(
427
+ 's',
428
+ sub(symbol('\''), 'i'),
429
+ symbol('='),
430
+ matrix(
431
+ symbol('{'),
432
+ [
433
+ [seq(symbol('-'), '1'), seq(symbol('if'), sub('s', 'i'), symbol('>'), sub('s', grseq('i', symbol('+'), '1')))],
434
+ [seq(symbol('+'), '1'), seq(symbol('if'), sub('s', 'i'), symbol('<='), sub('s', grseq('i', symbol('+'), '1')))]
435
+ ],
436
+ symbol(':}'),
437
+ )
438
+ ),
439
+ :mathml => '<math><mi>s</mi><msub><mo>&#x2032;</mo><mi>i</mi></msub><mo>=</mo><mrow><mo>{</mo><mtable><mtr><mtd><mrow><mo>&#x2212;</mo><mn>1</mn></mrow></mtd><mtd><mrow><mo>if</mo><msub><mi>s</mi><mi>i</mi></msub><mo>&gt;</mo><msub><mi>s</mi><mrow><mi>i</mi><mo>+</mo><mn>1</mn></mrow></msub></mrow></mtd></mtr><mtr><mtd><mrow><mo>+</mo><mn>1</mn></mrow></mtd><mtd><mrow><mo>if</mo><msub><mi>s</mi><mi>i</mi></msub><mo>&#x2264;</mo><msub><mi>s</mi><mrow><mi>i</mi><mo>+</mo><mn>1</mn></mrow></msub></mrow></mtd></mtr></mtable></mrow></math>',
440
+ :latex => 's \'_i = \\left \\{ \\begin{matrix} - 1 & \\operatorname{if} s_i > s_{i + 1} \\\\ + 1 & \\operatorname{if} s_i \\le s_{i + 1} \\end{matrix} \\right .',
441
+ ))
442
+
443
+ example('s\'_i = {(, if s_i > s_(i + 1)),( + 1,):}', &should_generate(
444
+ :ast => seq(
445
+ 's',
446
+ sub(symbol('\''), 'i'),
447
+ symbol('='),
448
+ matrix(
449
+ symbol('{'),
450
+ [
451
+ [[], [symbol('if'), sub('s', 'i'), symbol('>'), sub('s', grseq('i', symbol('+'), '1'))]],
452
+ [[symbol('+'), '1'], []]
453
+ ],
454
+ symbol(':}')
455
+ )
456
+ ),
457
+ :mathml => '<math><mi>s</mi><msub><mo>&#x2032;</mo><mi>i</mi></msub><mo>=</mo><mrow><mo>{</mo><mtable><mtr><mtd></mtd><mtd><mrow><mo>if</mo><msub><mi>s</mi><mi>i</mi></msub><mo>&gt;</mo><msub><mi>s</mi><mrow><mi>i</mi><mo>+</mo><mn>1</mn></mrow></msub></mrow></mtd></mtr><mtr><mtd><mrow><mo>+</mo><mn>1</mn></mrow></mtd><mtd></mtd></mtr></mtable></mrow></math>',
458
+ :latex => 's \'_i = \\left \\{ \\begin{matrix} & \\operatorname{if} s_i > s_{i + 1} \\\\ + 1 & \\end{matrix} \\right .',
459
+ ))
460
+
461
+ example('{:(a,b),(c,d):}', &should_generate(
462
+ :ast => matrix(
463
+ symbol('{:'),
464
+ [%w(a b), %w(c d)],
465
+ symbol(':}')
466
+ ),
467
+ :mathml => '<math><mtable><mtr><mtd><mi>a</mi></mtd><mtd><mi>b</mi></mtd></mtr><mtr><mtd><mi>c</mi></mtd><mtd><mi>d</mi></mtd></mtr></mtable></math>',
468
+ :latex => '\\begin{matrix} a & b \\\\ c & d \\end{matrix}',
469
+ ))
470
+
471
+ example('overset (a + b) (c + d)', &should_generate(
472
+ :ast => binary(
473
+ symbol('overset'),
474
+ grseq('a', symbol('+'), 'b'),
475
+ grseq('c', symbol('+'), 'd')
476
+ ),
477
+ :mathml => '<math><mover><mrow><mi>c</mi><mo>+</mo><mi>d</mi></mrow><mrow><mi>a</mi><mo>+</mo><mi>b</mi></mrow></mover></math>',
478
+ :html => '<span class="math-inline"><span class="math-blank">&#x200D;</span><span class="math-underover"><span class="math-smaller"><span class="math-row"><span class="math-identifier">a</span><span class="math-operator">+</span><span class="math-identifier">b</span></span></span><span class="math-row"><span class="math-identifier">c</span><span class="math-operator">+</span><span class="math-identifier">d</span></span><span class="math-smaller"><span class="math-blank">&#x200D;</span></span></span></span>',
479
+ :latex => '\\overset{a + b}{c + d}',
480
+ ))
481
+
482
+ example('underset a b', &should_generate(
483
+ :ast => binary(
484
+ symbol('underset'),
485
+ 'a',
486
+ 'b'
487
+ ),
488
+ :mathml => '<math><munder><mi>b</mi><mi>a</mi></munder></math>',
489
+ :html => '<span class="math-inline"><span class="math-blank">&#x200D;</span><span class="math-underover"><span class="math-smaller"><span class="math-blank">&#x200D;</span></span><span class="math-identifier">b</span><span class="math-smaller"><span class="math-identifier">a</span></span></span></span>',
490
+ :latex => '\\underset{a}{b}',
491
+ ))
492
+
493
+ example('sin a_c^b', &should_generate(
494
+ :ast => seq(
495
+ symbol('sin'),
496
+ subsup('a', 'c', 'b')
497
+ ),
498
+ :mathml => '<math><mi>sin</mi><msubsup><mi>a</mi><mi>c</mi><mi>b</mi></msubsup></math>',
499
+ :html => '<span class="math-inline"><span class="math-identifier">sin</span><span class="math-identifier">a</span><span class="math-subsup"><span class="math-smaller"><span class="math-identifier">b</span></span><span class="math-smaller"><span class="math-identifier">c</span></span></span></span>',
500
+ :latex => '\\sin a_c^b',
501
+ ))
502
+
503
+ example('max a_c^b', &should_generate(
504
+ :ast => seq(
505
+ symbol('max'),
506
+ subsup('a', 'c', 'b')
507
+ ),
508
+ :mathml => '<math><mo>max</mo><msubsup><mi>a</mi><mi>c</mi><mi>b</mi></msubsup></math>',
509
+ :html => '<span class="math-inline"><span class="math-operator">max</span><span class="math-identifier">a</span><span class="math-subsup"><span class="math-smaller"><span class="math-identifier">b</span></span><span class="math-smaller"><span class="math-identifier">c</span></span></span></span>',
510
+ :latex => '\\max a_c^b',
511
+ ))
512
+
513
+ example('norm a_c^b', &should_generate(
514
+ :ast => subsup(unary(symbol('norm'), 'a'), 'c', 'b'),
515
+ :mathml => '<math><msubsup><mrow><mo>&#x2225;</mo><mi>a</mi><mo>&#x2225;</mo></mrow><mi>c</mi><mi>b</mi></msubsup></math>',
516
+ :html => '<span class="math-inline"><span class="math-row"><span class="math-brace">&#x2225;</span><span class="math-identifier">a</span><span class="math-brace">&#x2225;</span></span><span class="math-subsup"><span class="math-smaller"><span class="math-identifier">b</span></span><span class="math-smaller"><span class="math-identifier">c</span></span></span></span>',
517
+ :latex => '{\\lVert a \\rVert}_c^b',
518
+ ))
519
+
520
+ example('overarc a_b^c', &should_generate(
521
+ :ast => subsup(unary(symbol('overarc'), 'a'), 'b', 'c'),
522
+ :mathml => '<math><msubsup><mover><mi>a</mi><mo>&#x23DC;</mo></mover><mi>b</mi><mi>c</mi></msubsup></math>',
523
+ :latex => '{\\overset{\\frown}{a}}_b^c'
524
+ ))
525
+
526
+ example('frown a_b^c', &should_generate(
527
+ :ast => seq(symbol('frown'), subsup('a', 'b', 'c')),
528
+ :mathml => '<math><mo>&#x2322;</mo><msubsup><mi>a</mi><mi>b</mi><mi>c</mi></msubsup></math>',
529
+ :latex => '\\frown a_b^c',
530
+ ))
531
+
532
+ example('sin(a_c^b)', &should_generate(
533
+ :ast => seq(symbol('sin'), paren(subsup('a', 'c', 'b'))),
534
+ :mathml => '<math><mi>sin</mi><mrow><mo>(</mo><msubsup><mi>a</mi><mi>c</mi><mi>b</mi></msubsup><mo>)</mo></mrow></math>',
535
+ :latex => '\\sin ( a_c^b )',
536
+ ))
537
+
538
+ example('text(a)a2)', &should_generate(
539
+ :ast => seq(text('a'), identifier('a'), number('2'), symbol(')')),
540
+ :mathml => '<math><mtext>a</mtext><mi>a</mi><mn>2</mn><mo>)</mo></math>',
541
+ :html => '<span class="math-inline"><span class="math-text">a</span><span class="math-identifier">a</span><span class="math-number">2</span><span class="math-operator">)</span></span>',
542
+ :latex => '\\text{a} a 2 )',
543
+ ))
544
+
545
+ example('cancel(a_b^c) cancel a_b^c', &should_generate(
546
+ :ast => seq(
547
+ unary(symbol('cancel'), group(subsup('a', 'b', 'c'))),
548
+ subsup(unary(symbol('cancel'), 'a'), 'b', 'c')
549
+ ),
550
+ :mathml => '<math><menclose notation="updiagonalstrike"><msubsup><mi>a</mi><mi>b</mi><mi>c</mi></msubsup></menclose><msubsup><menclose notation="updiagonalstrike"><mi>a</mi></menclose><mi>b</mi><mi>c</mi></msubsup></math>',
551
+ :latex => '\\cancel{a_b^c} {\\cancel{a}}_b^c',
552
+ ))
553
+
554
+ example('color(red)(x) color(#123)(y) color(#1234ab)(z) colortext(blue)(a_b^c)', &should_generate(
555
+ :ast => seq(
556
+ binary(symbol('color'), color(255, 0, 0, 'red'), group('x')),
557
+ binary(symbol('color'), color(17, 34, 51, '#123'), group('y')),
558
+ binary(symbol('color'), color(18, 52, 171, '#1234ab'), group('z')),
559
+ binary(symbol('color'), color(0, 0, 255, 'blue'), group(subsup('a', 'b', 'c')))
560
+ ),
561
+ :mathml => '<math><mstyle mathcolor="#ff0000"><mi>x</mi></mstyle><mstyle mathcolor="#112233"><mi>y</mi></mstyle><mstyle mathcolor="#1234ab"><mi>z</mi></mstyle><mstyle mathcolor="#0000ff"><msubsup><mi>a</mi><mi>b</mi><mi>c</mi></msubsup></mstyle></math>',
562
+ :latex => '{\\color{red} x} {\\color[RGB]{17,34,51} y} {\\color[RGB]{18,52,171} z} {\\color{blue} a_b^c}',
563
+ ))
564
+
565
+ example('{ x\ : \ x in A ^^ x in B }', &should_generate(
566
+ :ast => paren(
567
+ symbol('{'),
568
+ seq('x', symbol('\ '), ':', symbol('\ '), 'x', symbol('in'), 'A', symbol('^^'), 'x', symbol('in'), 'B'),
569
+ symbol('}')
570
+ ),
571
+ :mathml => '<math><mrow><mo>{</mo><mrow><mi>x</mi><mo>&#xA0;</mo><mi>:</mi><mo>&#xA0;</mo><mi>x</mi><mo>&#x2208;</mo><mi>A</mi><mo>&#x2227;</mo><mi>x</mi><mo>&#x2208;</mo><mi>B</mi></mrow><mo>}</mo></mrow></math>',
572
+ :latex => '\\left \\{ x \\; : \\; x \\in A \\wedge x \\in B \\right \\}',
573
+ ))
574
+
575
+ version = RUBY_VERSION.split('.').map { |s| s.to_i }
576
+
577
+ if version[0] > 1 || version[1] > 8
578
+ example('Скорость=(Расстояние)/(Время)', &should_generate(
579
+ :ast => seq(
580
+ 'С', 'к', 'о', 'р', 'о', 'с', 'т', 'ь',
581
+ symbol('='),
582
+ infix(
583
+ grseq('Р', 'а', 'с', 'с', 'т', 'о', 'я', 'н', 'и', 'е'),
584
+ symbol('/'),
585
+ grseq('В', 'р', 'е', 'м', 'я')
586
+ )
587
+ ),
588
+ :mathml => '<math><mi>&#x421;</mi><mi>&#x43A;</mi><mi>&#x43E;</mi><mi>&#x440;</mi><mi>&#x43E;</mi><mi>&#x441;</mi><mi>&#x442;</mi><mi>&#x44C;</mi><mo>=</mo><mfrac><mrow><mi>&#x420;</mi><mi>&#x430;</mi><mi>&#x441;</mi><mi>&#x441;</mi><mi>&#x442;</mi><mi>&#x43E;</mi><mi>&#x44F;</mi><mi>&#x43D;</mi><mi>&#x438;</mi><mi>&#x435;</mi></mrow><mrow><mi>&#x412;</mi><mi>&#x440;</mi><mi>&#x435;</mi><mi>&#x43C;</mi><mi>&#x44F;</mi></mrow></mfrac></math>',
589
+ :html => '<span class="math-inline"><span class="math-identifier">&#x421;</span><span class="math-identifier">&#x43A;</span><span class="math-identifier">&#x43E;</span><span class="math-identifier">&#x440;</span><span class="math-identifier">&#x43E;</span><span class="math-identifier">&#x441;</span><span class="math-identifier">&#x442;</span><span class="math-identifier">&#x44C;</span><span class="math-operator">=</span><span class="math-blank">&#x200D;</span><span class="math-fraction"><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-row"><span class="math-identifier">&#x420;</span><span class="math-identifier">&#x430;</span><span class="math-identifier">&#x441;</span><span class="math-identifier">&#x441;</span><span class="math-identifier">&#x442;</span><span class="math-identifier">&#x43E;</span><span class="math-identifier">&#x44F;</span><span class="math-identifier">&#x43D;</span><span class="math-identifier">&#x438;</span><span class="math-identifier">&#x435;</span></span></span></span></span></span><span class="math-fraction_row"><span class="math-fraction_cell"><span class="math-smaller"><span class="math-row"><span class="math-row"><span class="math-identifier">&#x412;</span><span class="math-identifier">&#x440;</span><span class="math-identifier">&#x435;</span><span class="math-identifier">&#x43C;</span><span class="math-identifier">&#x44F;</span></span></span></span></span></span></span></span>',
590
+ :latex => 'С к о р о с т ь = \\frac{Р а с с т о я н и е}{В р е м я}'
591
+ ))
161
592
  end
162
- end
593
+ end
594
+
595
+ describe 'AsciiMath::Parser', :variant => :ast do
596
+ include_examples 'AsciiMath Examples'
597
+ end
598
+
599
+ describe 'AsciiMath::MathMLBuilder', :variant => :mathml do
600
+ include_examples 'AsciiMath Examples'
601
+ end
602
+
603
+ describe 'AsciiMath::MathMLBuilder Microsoft Office', :variant => :mathml_word do
604
+ include_examples 'AsciiMath Examples'
605
+ end
606
+
607
+ describe 'AsciiMath::HTMLBuilder', :variant => :html do
608
+ include_examples 'AsciiMath Examples', :html
609
+ end
610
+
611
+ describe 'AsciiMath::LatexBuilder', :variant => :latex do
612
+ include_examples 'AsciiMath Examples'
613
+ end