mathml 0.8.0

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.
@@ -0,0 +1,780 @@
1
+ # Test for math_ml.rb
2
+ #
3
+ # Copyright (C) 2005, KURODA Hiraku <hiraku@hinet.mydns.jp>
4
+ # You can redistribute it and/or modify it under GPL2.
5
+
6
+ require "test/unit"
7
+ require "math_ml"
8
+ require "math_ml_test_util"
9
+
10
+ class TC_Mathml_rb < Test::Unit::TestCase
11
+ def test_double_require
12
+ assert(require("lib/math_ml"))
13
+ assert_nothing_raised do
14
+ MathML::LaTeX::Parser.new
15
+ end
16
+ end
17
+ end
18
+
19
+ class TC_MathML_Element < Test::Unit::TestCase
20
+ include Util4TC_MathML
21
+ include MathML
22
+
23
+ def test_display_style
24
+ e = Element.new("test")
25
+ assert(!e.display_style)
26
+
27
+ e = Element.new("test").as_display_style
28
+ assert_equal(MathML::Element, e.class)
29
+ assert(e.display_style)
30
+ end
31
+
32
+ def test_pop
33
+ e = Element.new("super")
34
+ assert_equal(nil, e.pop)
35
+
36
+ s = Element.new("sub")
37
+ e << s
38
+ assert_equal(s, e.pop)
39
+ assert_equal(nil, e.pop)
40
+
41
+ e << "text"
42
+ assert_equal(MathML.pcstring("text"), e.pop)
43
+ assert_equal(nil, e.pop)
44
+ end
45
+
46
+ def test_pcstring
47
+ assert_equal("&lt;&gt;&amp;&quot;&apos;", MathML.pcstring('<>&"\'').to_s)
48
+ assert_equal('<tag>&amp;"\'</tag>', MathML.pcstring('<tag>&amp;"\'</tag>', true).to_s)
49
+ end
50
+ end
51
+
52
+ class TC_MathML_LaTeX_Scanner < Test::Unit::TestCase
53
+ include MathML::LaTeX
54
+
55
+ def test_done
56
+ s = Scanner.new("0123")
57
+ s.pos = 2
58
+ assert_equal("01", s.done)
59
+ assert_equal("23", s.rest)
60
+ end
61
+
62
+ def test__scan
63
+ s = Scanner.new(" ")
64
+ assert_equal(" ", s._scan(/\s/))
65
+ assert_equal(1, s.pos)
66
+ end
67
+
68
+ def test__check
69
+ s = Scanner.new(" ")
70
+ assert_equal(" ", s._check(/\s/))
71
+ assert_equal(0, s.pos)
72
+ end
73
+
74
+ def test_scan
75
+ s = Scanner.new(" a")
76
+ assert_equal("a", s.scan(/a/))
77
+ assert_equal(2, s.pos)
78
+
79
+ s.reset
80
+ assert_equal(nil, s.scan(/b/))
81
+ assert_equal(0, s.pos)
82
+
83
+ s = Scanner.new(" %comment\na")
84
+ assert_equal("a", s.scan(/a/))
85
+ assert_equal(11, s.pos)
86
+
87
+ s.reset
88
+ assert_equal(nil, s.scan(/b/))
89
+ assert_equal(0, s.pos)
90
+ end
91
+
92
+ def test_check
93
+ s = Scanner.new(" a")
94
+ assert_equal("a", s.check(/a/))
95
+ assert_equal(0, s.pos)
96
+
97
+ s.reset
98
+ assert_equal(nil, s.check(/b/))
99
+ assert_equal(0, s.pos)
100
+ end
101
+
102
+ def test_eos
103
+ assert(Scanner.new("").eos?)
104
+ assert(Scanner.new(" ").eos?)
105
+ assert(Scanner.new(" %test\n%test").eos?)
106
+ assert(!Scanner.new(" a").eos?)
107
+ assert(!Scanner.new(" \\command").eos?)
108
+ end
109
+
110
+
111
+ def test_check_command
112
+ assert_equal(nil, Scanner.new("test").check_command)
113
+ s = Scanner.new(' \test')
114
+ assert_equal('\test', s.check_command)
115
+ assert_equal("test", s[1])
116
+ assert_equal('\test', Scanner.new(' \test next').check_command)
117
+ assert_equal('\test', Scanner.new(' \test_a').check_command)
118
+ end
119
+
120
+ def test_scan_command
121
+ assert_equal(nil, Scanner.new("test").scan_command)
122
+
123
+ s = Scanner.new(' \test')
124
+ assert_equal('\test', s.scan_command)
125
+ assert_equal("test", s[1])
126
+ assert_equal(6, s.pos)
127
+
128
+ s = Scanner.new(' \test rest')
129
+ assert_equal('\test', s.scan_command)
130
+ assert_equal(6, s.pos)
131
+
132
+ s = Scanner.new(' \test_a')
133
+ assert_equal('\test', s.scan_command)
134
+ assert_equal(6, s.pos)
135
+
136
+ s = Scanner.new(' \_test')
137
+ assert_equal('\_', s.check_command)
138
+ assert_equal('\_', s.scan_command)
139
+ assert_equal("test", s.rest)
140
+
141
+ end
142
+
143
+ def test_scan_block
144
+ assert_equal(nil, Scanner.new(" a").scan_block)
145
+ assert_equal(nil, Scanner.new(" a").check_block)
146
+
147
+ i = " {{}{}{{}{}}} "
148
+ e = "{#{i}}"
149
+ s = Scanner.new(" #{e} test")
150
+ assert_equal(e, s.check_block)
151
+ assert_equal(e, s.matched)
152
+ assert_equal(i, s[1])
153
+ assert_equal(e, s.scan_block)
154
+ assert_equal(e, s.matched)
155
+ assert_equal(i, s[1])
156
+ assert_equal(" test", s.rest)
157
+
158
+ assert_equal(nil, Scanner.new(' \command test').scan_block)
159
+ assert_equal(nil, Scanner.new(' \command test').check_block)
160
+
161
+ assert_equal(nil, Scanner.new("").scan_block)
162
+ assert_equal(nil, Scanner.new("").check_block)
163
+
164
+ assert_equal(nil, Scanner.new(" ").scan_block)
165
+ assert_equal(nil, Scanner.new(" ").check_block)
166
+
167
+ s = Scanner.new("{test")
168
+ e = assert_raises(BlockNotClosed){s.scan_block}
169
+ end
170
+
171
+ def test_scan_any
172
+ s0 = " %comment\n "
173
+ s1 = "{}"
174
+ s = Scanner.new(s0+s1)
175
+ assert_equal(s1, s.scan_any)
176
+ s.reset
177
+ assert_equal(s0+s1, s.scan_any(true))
178
+ assert_equal(s1, s.matched)
179
+
180
+ s1 = '\command'
181
+ s = Scanner.new(s0+s1)
182
+ assert_equal(s1, s.scan_any)
183
+ s.reset
184
+ assert_equal(s0+s1, s.scan_any(true))
185
+
186
+ s1 = 'a'
187
+ s = Scanner.new(s0+s1)
188
+ assert_equal(s1, s.scan_any)
189
+ s.reset
190
+ assert_equal(s0+s1, s.scan_any(true))
191
+
192
+ s = Scanner.new(" ")
193
+ assert_equal(nil, s.scan_any)
194
+ s.reset
195
+ assert_equal(" ", s.scan_any(true))
196
+
197
+ s = Scanner.new('\begin{env}test\end{env}')
198
+ assert_equal('\begin', s.scan_any)
199
+ end
200
+
201
+ def test_peek_command
202
+ assert_equal("test", Scanner.new(' \test').peek_command)
203
+ assert_equal(nil, Scanner.new("").peek_command)
204
+ assert_equal(nil, Scanner.new(" ").peek_command)
205
+ assert_equal(nil, Scanner.new(" a").peek_command)
206
+ end
207
+
208
+ def test_scan_option
209
+ s = Scanner.new(" []")
210
+ assert_equal("[]", s.scan_option)
211
+ assert_equal("", s[1])
212
+ assert_equal(3, s.pos)
213
+
214
+ s = Scanner.new(" [ opt ]")
215
+ assert_equal("[ opt ]", s.scan_option)
216
+ assert_equal(" opt ", s[1])
217
+ assert_equal(8, s.pos)
218
+
219
+ s = Scanner.new(" [[]]")
220
+ assert_equal("[[]", s.scan_option)
221
+ assert_equal("[", s[1])
222
+
223
+ s = Scanner.new(" [{[]}]")
224
+ assert_equal("[{[]}]", s.scan_option)
225
+ assert_equal("{[]}", s[1])
226
+
227
+ assert_raises(OptionNotClosed){Scanner.new("[").scan_option}
228
+ end
229
+
230
+ def test_check_option
231
+ s = Scanner.new(" []")
232
+ assert_equal("[]", s.check_option)
233
+ assert_equal("", s[1])
234
+ assert_equal(0, s.pos)
235
+
236
+ s = Scanner.new(" [ opt ]")
237
+ assert_equal("[ opt ]", s.check_option)
238
+ assert_equal(" opt ", s[1])
239
+ assert_equal(0, s.pos)
240
+
241
+ s = Scanner.new(" [[]]")
242
+ assert_equal("[[]", s.check_option)
243
+ assert_equal("[", s[1])
244
+
245
+ s = Scanner.new(" [{[]}]")
246
+ assert_equal("[{[]}]", s.check_option)
247
+ assert_equal("{[]}", s[1])
248
+
249
+ assert_raises(OptionNotClosed){Scanner.new("[").check_option}
250
+ end
251
+ end
252
+
253
+ class TC_MathML_LaTeX_Macro < Test::Unit::TestCase
254
+ include Util4TC_MathML
255
+ include MathML::LaTeX
256
+
257
+ def setup
258
+ @src = <<'EOS'
259
+ \newcommand{\newcom}{test}
260
+ \newcommand{\paramcom}[2]{param2 #2, param1 #1.}
261
+ \newcommand\ALPHA\alpha
262
+ \newcommand\BETA[1]\beta
263
+ \newcommand{\nothing}{}
264
+ \newenvironment{newenv}{begin_newenv}{end_newenv}
265
+ \newenvironment{paramenv}[2]{begin 1:#1, 2:#2}{end 2:#2 1:#1}
266
+ \newenvironment{nothing}{}{}
267
+ \newenvironment{separated environment}{sep}{env}
268
+ \newenvironment ENV
269
+ EOS
270
+ super
271
+ end
272
+
273
+ def test_parse
274
+ m = Macro.new
275
+ assert_nothing_raised{m.parse(@src)}
276
+
277
+ assert_parse_error("Need newcommand.", '\\newcommand{', "notcommand}{}"){m.parse('\newcommand{notcommand}{}')}
278
+ assert_parse_error("Syntax error.", '\newcommand{\separated', " command}{}"){m.parse('\newcommand{\separated command}{}')}
279
+ assert_parse_error("Need parameter.", '\newcommand{\nobody}', ""){m.parse('\newcommand{\nobody}')}
280
+ assert_parse_error("Parameter \# too large.", '\newcommand{\noparam}{#', "1}"){m.parse('\newcommand{\noparam}{#1}')}
281
+ assert_parse_error("Parameter \# too large.", '\newcommand{\overopt}[1]{#1#', "2}"){m.parse('\newcommand{\overopt}[1]{#1#2}')}
282
+ assert_parse_error("Need positive number.", '\newcommand{\strangeopt}[', "-1]"){m.parse('\newcommand{\strangeopt}[-1]')}
283
+ assert_parse_error("Need positive number.", '\newcommand{\strangeopt}[', "a]"){m.parse('\newcommand{\strangeopt}[a]')}
284
+
285
+ assert_parse_error("Syntax error.", '\newenvironment{', '\command}{}{}'){m.parse('\newenvironment{\command}{}{}')}
286
+ assert_parse_error("Need begin block.", '\newenvironment{nobegin}', ""){m.parse('\newenvironment{nobegin}')}
287
+ assert_parse_error("Need end block.", '\newenvironment{noend}{}', ""){m.parse('\newenvironment{noend}{}')}
288
+ assert_parse_error("Parameter \# too large.", '\newenvironment{noparam}{#', "1}{}"){m.parse('\newenvironment{noparam}{#1}{}')}
289
+ assert_parse_error("Parameter \# too large.", '\newenvironment{overparam}[1]{#1#', "2}{}"){m.parse('\newenvironment{overparam}[1]{#1#2}{}')}
290
+ assert_parse_error("Need positive number.", '\newenvironment{strangeparam}[', "-1]{}{}"){m.parse('\newenvironment{strangeparam}[-1]{}{}')}
291
+ assert_parse_error("Need positive number.", '\newenvironment{strangeparam}[', "a]{}{}"){m.parse('\newenvironment{strangeparam}[a]{}{}')}
292
+
293
+ assert_parse_error("Syntax error.", '\newcommand{\valid}{OK} ', '\invalid{\test}{NG}'){m.parse('\newcommand{\valid}{OK} \invalid{\test}{NG}')}
294
+ assert_parse_error("Syntax error.", '\newcommand{\valid}{OK} ', 'invalid{\test}{NG}'){m.parse('\newcommand{\valid}{OK} invalid{\test}{NG}')}
295
+
296
+ assert_parse_error("Option not closed.", '\newcommand{\newcom}', '[test'){m.parse('\newcommand{\newcom}[test')}
297
+ assert_parse_error("Option not closed.", '\newcommand{\newcom}[1]', '[test'){m.parse('\newcommand{\newcom}[1][test')}
298
+ assert_parse_error("Parameter \# too large.", '\newcommand{\newcom}[1][]{#1#', '2}'){m.parse('\newcommand{\newcom}[1][]{#1#2}')}
299
+ assert_parse_error("Option not closed.", '\newenvironment{newenv}[1]', '[test'){m.parse('\newenvironment{newenv}[1][test')}
300
+ assert_parse_error("Option not closed.", '\newenvironment{newenv}[1]', '[test'){m.parse('\newenvironment{newenv}[1][test')}
301
+
302
+ assert_parse_error("Block not closed.", '\newcommand', '{\newcom'){m.parse('\newcommand{\newcom')}
303
+ assert_parse_error("Block not closed.", '\newcommand{\newcom}', '{test1{test2}{test3'){m.parse('\newcommand{\newcom}{test1{test2}{test3')}
304
+
305
+ assert_parse_error("Parameter \# too large.", '\newenvironment{newenv}[1][]{#1 #', '2}'){m.parse('\newenvironment{newenv}[1][]{#1 #2}')}
306
+ end
307
+
308
+ def test_commands
309
+ m = Macro.new
310
+ m.parse(@src)
311
+
312
+ assert_equal(0, m.commands("newcom").num)
313
+ assert_equal(2, m.commands("paramcom").num)
314
+ assert_equal(nil, m.commands("no"))
315
+ end
316
+
317
+ def test_expand_command
318
+ m = Macro.new
319
+ m.parse(@src)
320
+
321
+ assert_equal(nil, m.expand_command("not coommand", []))
322
+
323
+ assert_equal("test", m.expand_command("newcom", []))
324
+ assert_equal("test", m.expand_command("newcom", ["dummy_param"]))
325
+ assert_equal("param2 2, param1 1.", m.expand_command("paramcom", ["1", "2"]))
326
+ assert_equal("param2 34, param1 12.", m.expand_command("paramcom", ["12", "34"]))
327
+ assert_parse_error("Need more parameter.", "", ""){m.expand_command("paramcom", ["12"])}
328
+ assert_parse_error("Need more parameter.", "", ""){m.expand_command("paramcom", [])}
329
+ end
330
+
331
+ def test_environments
332
+ m = Macro.new
333
+ m.parse(@src)
334
+
335
+ assert_equal(0, m.environments("newenv").num)
336
+ assert_equal(2, m.environments("paramenv").num)
337
+ assert_equal(nil, m.environments("not_env"))
338
+ assert_equal(0, m.environments("separated environment").num)
339
+ end
340
+
341
+ def test_expand_environment
342
+ m = Macro.new
343
+ m.parse(@src)
344
+
345
+ assert_equal(nil, m.expand_environment('notregistered', "dummy", []))
346
+ assert_equal(' begin_newenv body end_newenv ', m.expand_environment("newenv", "body", []))
347
+ assert_equal(' begin 1:1, 2:2 body end 2:2 1:1 ', m.expand_environment("paramenv", "body", ["1", "2"]))
348
+ assert_equal(' begin 1:12, 2:34 body end 2:34 1:12 ', m.expand_environment("paramenv", "body", ["12", "34"]))
349
+ assert_parse_error("Need more parameter.", "", ""){m.expand_environment("paramenv", "body", ["1"])}
350
+ assert_parse_error("Need more parameter.", "", ""){m.expand_environment("paramenv", "body", [])}
351
+ assert_equal(' body ', m.expand_environment("nothing", "body", []))
352
+ assert_equal(' sep body env ', m.expand_environment("separated environment", "body", []))
353
+ assert_equal(' N body V ', m.expand_environment("E", "body", []))
354
+ end
355
+
356
+ def test_expand_with_options
357
+
358
+ src = <<'EOS'
359
+ \newcommand{\opt}[1][x]{#1}
360
+ \newcommand{\optparam}[2][]{#1#2}
361
+ \newenvironment{newenv}[1][x]{s:#1}{e:#1}
362
+ \newenvironment{optenv}[2][]{s:#1}{e:#2}
363
+ EOS
364
+
365
+ m = Macro.new
366
+ m.parse(src)
367
+
368
+ assert_equal('x', m.expand_command("opt", []))
369
+ assert_equal('1', m.expand_command("opt", [], "1"))
370
+
371
+ assert_equal('1', m.expand_command("optparam", ["1"]))
372
+ assert_equal('21', m.expand_command("optparam", ["1"], "2"))
373
+
374
+ assert_equal(" s:x test e:x ", m.expand_environment("newenv", "test", []))
375
+ assert_equal(" s:1 test e:1 ", m.expand_environment("newenv", "test", [], "1"))
376
+
377
+ assert_equal(" s: test e:1 ", m.expand_environment("optenv", "test", ["1"]))
378
+ assert_equal(" s:2 test e:1 ", m.expand_environment("optenv", "test", ["1"], "2"))
379
+ end
380
+ end
381
+
382
+ class TC_MathML_LaTeX_Parser < Test::Unit::TestCase
383
+ include MathML::LaTeX
384
+ include Util4TC_MathML
385
+
386
+ ### Sub routines ###
387
+
388
+ def check_chr(stag, etag, str, print=false)
389
+ str.each_byte do |b|
390
+ assert_equal("#{stag}#{b.chr}#{etag}", smml(b.chr))
391
+ puts smml(b.chr) if print
392
+ end
393
+ end
394
+
395
+ def check_hash(stag, etag, hash, print=false)
396
+ hash.each do |k, v|
397
+ e = "#{stag}#{v}#{etag}"
398
+ s = smml(k)
399
+ assert_equal(e, s)
400
+ puts "#{k} => #{s}" if print
401
+ end
402
+ end
403
+
404
+ def check_entity(stag, etag, hash, print=false)
405
+ h = Hash.new
406
+ hash.each do |k, v|
407
+ h[k] = "&#{v};"
408
+ end
409
+ check_hash(stag, etag, h, print)
410
+ end
411
+
412
+ ### Tests ###
413
+
414
+ def test_nobody
415
+ p = Parser.new
416
+ assert_equal("<math display='inline' xmlns='http://www.w3.org/1998/Math/MathML' />", p.parse("").to_s)
417
+ assert_equal("<math display='block' xmlns='http://www.w3.org/1998/Math/MathML' />", p.parse("", true).to_s)
418
+ assert_equal("<math display='inline' xmlns='http://www.w3.org/1998/Math/MathML' />", p.parse("", false).to_s)
419
+ end
420
+
421
+ def test_ignore_space
422
+ assert_equal("<mrow><mi>a</mi></mrow>", smml("{ a }"))
423
+ end
424
+
425
+ def test_block
426
+ assert_parse_error("Block not closed.", "test {test} ", "{test"){smml("test {test} {test")}
427
+ end
428
+
429
+ def test_parse_error
430
+ src = 'a\hoge c'
431
+ e = assert_raises(ParseError){smml(src)}
432
+ assert_equal(["Undefined command.", "a", '\hoge c'], parse_error(e))
433
+
434
+ src = '\sqrt\sqrt1'
435
+ e = assert_raises(ParseError){smml(src)}
436
+ assert_equal(["Syntax error.", '\sqrt\sqrt', "1"], parse_error(e))
437
+
438
+ src = "a{b"
439
+ e = assert_raises(ParseError){smml(src)}
440
+ assert_equal(["Block not closed.", "a", "{b"], parse_error(e))
441
+ end
442
+
443
+ def test_numerics
444
+ assert_equal("<mn>1234567890</mn>", smml('1234567890'))
445
+ assert_equal("<mn>1.2</mn>", smml('1.2'))
446
+ assert_equal("<mn>1</mn><mo>.</mo>", smml('1.'))
447
+ assert_equal("<mn>.2</mn>", smml('.2'))
448
+ assert_equal("<mn>1.2</mn><mn>.3</mn>", smml('1.2.3'))
449
+ end
450
+
451
+ def test_alphabets
452
+ check_chr("<mi>", "</mi>", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
453
+ end
454
+
455
+ def test_non_alphabet_command
456
+ assert_equal("<mspace width='0.167em' />", smml('\,'))
457
+ assert_equal("<mo>&DoubleVerticalBar;</mo>", smml('\|'))
458
+ end
459
+
460
+ def test_operators
461
+ check_chr("<mo>", "</mo>", ",.+-*=/()[]|;:!")
462
+ check_entity("<mo>", "</mo>", {"<"=>"lt", ">"=>"gt", '"'=>"quot", "'"=>"apos"})
463
+ check_hash("<mo>", "</mo>", {'\backslash'=>'\\', '\%'=>'%', '\{'=>'{', '\}'=>'}', '\$'=>'$', '\#'=>'#'})
464
+ end
465
+
466
+ def test_sqrt
467
+ assert_equal("<msqrt><mi>a</mi></msqrt>", smml('\sqrt a'))
468
+ assert_equal("<mroot><mn>3</mn><mn>2</mn></mroot>", smml('\sqrt[2]3'))
469
+ assert_equal("<mroot><mn>3</mn><mrow><mn>2</mn><mi>a</mi></mrow></mroot>", smml('\sqrt[2a]3'))
470
+ e = assert_raises(ParseError){smml('\sqrt[12')}
471
+ assert_equal(["Option not closed.", '\sqrt', "[12"], parse_error(e))
472
+ end
473
+
474
+ def test_subsup
475
+ assert_equal("<msubsup><mi>a</mi><mi>b</mi><mi>c</mi></msubsup>", smml("a_b^c"))
476
+ assert_equal("<msub><mi>a</mi><mi>b</mi></msub>", smml("a_b"))
477
+ assert_equal("<msup><mi>a</mi><mi>b</mi></msup>", smml("a^b"))
478
+ assert_equal("<msubsup><none /><mi>a</mi><mi>b</mi></msubsup>", smml("_a^b"))
479
+
480
+ e = assert_raises(ParseError){smml("a_b_c")}
481
+ assert_equal(["Double subscript.", "a_b", "_c"], parse_error(e))
482
+ e = assert_raises(ParseError){smml("a^b^c")}
483
+ assert_equal(["Double superscript.", "a^b", "^c"], parse_error(e))
484
+ e = assert_raises(ParseError){smml("a_")}
485
+ assert_equal(["Subscript not exist.", "a_", ""], parse_error(e))
486
+ e = assert_raises(ParseError){smml("a^")}
487
+ assert_equal(["Superscript not exist.", "a^", ""], parse_error(e))
488
+ end
489
+
490
+ def test_underover
491
+ assert_equal("<munderover><mo>&sum;</mo><mi>a</mi><mi>b</mi></munderover>", smml('\sum_a^b', true))
492
+ assert_equal("<msubsup><mo>&sum;</mo><mi>a</mi><mi>b</mi></msubsup>", smml('\sum_a^b'))
493
+ assert_equal("<munder><mo>&sum;</mo><mi>a</mi></munder>", smml('\sum_a', true))
494
+ assert_equal("<mover><mo>&sum;</mo><mi>a</mi></mover>", smml('\sum^a', true))
495
+ assert_equal("<msub><mo>&sum;</mo><mi>a</mi></msub>", smml('\sum_a'))
496
+ assert_equal("<msup><mo>&sum;</mo><mi>a</mi></msup>", smml('\sum^a'))
497
+ e = assert_raises(ParseError){smml('\sum_b_c')}
498
+ assert_equal(["Double subscript.", '\sum_b', "_c"], parse_error(e))
499
+ e = assert_raises(ParseError){smml('\sum^b^c')}
500
+ assert_equal(["Double superscript.", '\sum^b', "^c"], parse_error(e))
501
+ e = assert_raises(ParseError){smml('\sum_')}
502
+ assert_equal(["Subscript not exist.", '\sum_', ""], parse_error(e))
503
+ e = assert_raises(ParseError){smml('\sum^')}
504
+ assert_equal(["Superscript not exist.", '\sum^', ""], parse_error(e))
505
+ end
506
+
507
+ def test_fonts
508
+ assert_equal("<mi>a</mi><mrow><mi mathvariant='bold'>b</mi><mi mathvariant='bold'>c</mi></mrow><mi>d</mi>", smml('a{\bf b c}d'))
509
+ assert_equal("<mi mathvariant='bold'>a</mi><mrow><mi>b</mi><mi>c</mi></mrow><mi mathvariant='bold'>d</mi>", smml('\bf a{\it b c}d'))
510
+ assert_equal("<mi>a</mi><mrow><mi mathvariant='normal'>b</mi><mi mathvariant='normal'>c</mi></mrow><mi>d</mi>", smml('a{\rm b c}d'))
511
+
512
+ assert_equal("<mi>a</mi><mrow><mrow><mi mathvariant='bold'>b</mi><mi mathvariant='bold'>c</mi></mrow></mrow><mi>d</mi>", smml('a \mathbf{bc}d'))
513
+ assert_equal("<mrow><mn mathvariant='bold'>1</mn></mrow><mn>2</mn>", smml('\mathbf12'))
514
+ assert_equal("<mi mathvariant='bold'>a</mi><mrow><mrow><mi>b</mi><mi>c</mi></mrow></mrow><mi mathvariant='bold'>d</mi>", smml('\bf a \mathit{bc} d'))
515
+ assert_equal("<mi>a</mi><mrow><mrow><mi mathvariant='normal'>b</mi><mi mathvariant='normal'>c</mi></mrow></mrow><mi>d</mi>", smml('a\mathrm{bc}d'))
516
+
517
+ assert_equal("<mi>a</mi><mrow><mrow><mi>&bopf;</mi><mi>&copf;</mi></mrow></mrow><mi>d</mi>", smml('a \mathbb{b c} d'))
518
+ assert_equal("<mi>a</mi><mrow><mrow><mi>&bscr;</mi><mi>&cscr;</mi></mrow></mrow><mi>d</mi>", smml('a \mathscr{b c} d'))
519
+ assert_equal("<mi>a</mi><mrow><mrow><mi>&bfr;</mi><mi>&cfr;</mi></mrow></mrow><mi>d</mi>", smml('a \mathfrak{b c} d'))
520
+ assert_equal("<mi>a</mi><mrow><mrow><mi mathvariant='bold-italic'>b</mi><mi mathvariant='bold-italic'>c</mi></mrow></mrow><mi>d</mi>", smml('a \bm{bc}d'))
521
+ assert_equal("<mrow><mi mathvariant='bold-italic'>a</mi></mrow><mi>b</mi>", smml('\bm ab'))
522
+ e = assert_raises(ParseError){smml('\mathit')}
523
+ assert_equal(["Syntax error.", '\mathit', ""], parse_error(e))
524
+ e = assert_raises(ParseError){smml('\mathrm')}
525
+ assert_equal(["Syntax error.", '\mathrm', ""], parse_error(e))
526
+ e = assert_raises(ParseError){smml('\mathbf')}
527
+ assert_equal(["Syntax error.", '\mathbf', ""], parse_error(e))
528
+ e = assert_raises(ParseError){smml('\mathbb')}
529
+ assert_equal(["Syntax error.", '\mathbb', ""], parse_error(e))
530
+ e = assert_raises(ParseError){smml('\mathscr')}
531
+ assert_equal(["Syntax error.", '\mathscr', ""], parse_error(e))
532
+ e = assert_raises(ParseError){smml('\mathfrak')}
533
+ assert_equal(["Syntax error.", '\mathfrak', ""], parse_error(e))
534
+ end
535
+
536
+ def test_mbox
537
+ assert_equal("<mi>a</mi><mtext>b c</mtext><mi>d</mi>", smml('a\mbox{b c}d'))
538
+ assert_equal('<mtext>&lt;&gt;&apos;&quot;&amp;</mtext>', smml('\mbox{<>\'"&}'))
539
+ end
540
+
541
+ def test_frac
542
+ assert_equal("<mfrac><mi>a</mi><mi>b</mi></mfrac>", smml('\frac ab'))
543
+ assert_equal("<mfrac><mn>1</mn><mn>2</mn></mfrac>", smml('\frac12'))
544
+
545
+ e = assert_raises(ParseError){smml('\frac a')}
546
+ assert_equal(["Syntax error.", '\frac a', ""], parse_error(e))
547
+ end
548
+
549
+ def test_environment
550
+ e = assert_raises(ParseError){smml('{\begin}rest')}
551
+ assert_equal(["Environment name not exist.", '{\begin', '}rest'], parse_error(e))
552
+
553
+ e = assert_raises(ParseError){smml('{\begin{array}{c}dummy}rest')}
554
+ assert_equal(['Matching \end not exist.', '{\begin{array}{c}dummy', '}rest'], parse_error(e))
555
+
556
+ e = assert_raises(ParseError){smml('\begin{array}c dummy\end{test}')}
557
+ assert_equal(["Environment mismatched.", '\begin{array}c dummy\end', "{test}"], parse_error(e))
558
+
559
+ e = assert_raises(ParseError){smml('\left(\begin{array}\right)')}
560
+ assert_equal(["Syntax error.", '\left(\begin{array}', '\right)'], parse_error(e))
561
+ end
562
+
563
+ def test_array_env
564
+ assert_equal("<mtable columnalign='left right center'><mtr><mtd><mi>a</mi></mtd><mtd><mi>b</mi></mtd><mtd><mi>c</mi></mtd></mtr><mtr><mtd><mi>d</mi></mtd><mtd><mi>e</mi></mtd><mtd><mi>f</mi></mtd></mtr></mtable>", smml('\begin{array}{lrc} a & b & c \\\\ d & e & f \\\\ \end{array}'))
565
+
566
+ assert_equal("<mtable columnalign='left right center'><mtr><mtd><mi>a</mi></mtd><mtd><mi>b</mi></mtd><mtd><mi>c</mi></mtd></mtr><mtr><mtd><mi>d</mi></mtd><mtd><mi>e</mi></mtd><mtd><mi>f</mi></mtd></mtr></mtable>", smml('\begin{array}{lrc}a&b&c\\\\d&e&f \end{array}'))
567
+
568
+ assert_equal("<mtable />", smml('\begin{array}{c}\end{array}'))
569
+
570
+ e = assert_raises(ParseError){smml('\begin{array}\end{array}')}
571
+ assert_equal(['Syntax error.', '\begin{array}', '\end{array}'], parse_error(e))
572
+
573
+ e = assert_raises(ParseError){smml('\begin{array}{a}\end{array}')}
574
+ assert_equal(["Syntax error.", '\begin{array}{', 'a}\end{array}'], parse_error(e))
575
+
576
+ e = assert_raises(ParseError){smml('\begin{array}{cc}a\\\\b&c\end{array}')}
577
+ assert_equal(["Need more column.", '\begin{array}{cc}a', '\\\\b&c\end{array}'], parse_error(e))
578
+
579
+ e = assert_raises(ParseError){smml('\begin{array}{cc}a\end{array}')}
580
+ assert_equal(["Need more column.", '\begin{array}{cc}a', '\end{array}'], parse_error(e))
581
+
582
+ e = assert_raises(ParseError){smml('\begin{array}{c}a&\end{array}')}
583
+ assert_equal(["Too many column.", '\begin{array}{c}a', '&\end{array}'], parse_error(e))
584
+
585
+ assert_equal("<mtable><mtr><mtd /><mtd /></mtr></mtable>", smml('\begin{array}{cc}&\end{array}'))
586
+
587
+ assert_equal("<mfenced close='}' open='{'><mrow><mtable><mtr><mtd><msub><mi>a</mi><mi>b</mi></msub></mtd></mtr></mtable></mrow></mfenced>", smml('\left\{\begin{array}ca_b\end{array}\right\}'))
588
+
589
+ assert_equal("<mtable columnalign='center left center center center right center'><mtr><mtd><mrow><msub><mi>a</mi><mn>1</mn></msub></mrow></mtd><mtd><mi>A</mi></mtd><mtd><mi>b</mi></mtd><mtd><mi>B</mi></mtd><mtd><mi>c</mi></mtd><mtd><mi>C</mi></mtd><mtd><mi>d</mi></mtd></mtr></mtable>", smml('\begin{array}{@{a_1}l@bc@cr@d}A&B&C\end{array}'))
590
+
591
+ assert_equal("<mfenced close='}' open='{'><mrow><mtable><mtr><mtd><msub><mi>a</mi><mi>b</mi></msub></mtd></mtr></mtable></mrow></mfenced>", smml('\left\{\begin{array}ca_b\end{array}\right\}'))
592
+
593
+ assert_equal("<mtable columnlines='solid'><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>", smml('\begin{array}{c|c}a&b\\\\c&d\end{array}'))
594
+ assert_equal("<mtable columnlines='solid solid'><mtr><mtd /><mtd><mi>a</mi></mtd><mtd /></mtr><mtr><mtd /><mtd><mi>c</mi></mtd><mtd /></mtr></mtable>", smml('\begin{array}{|c|}a\\\\c\end{array}'))
595
+ assert_equal("<mtable rowlines='solid'><mtr /><mtr><mtd><mi>c</mi></mtd></mtr></mtable>", smml('\begin{array}{c}\hline c\end{array}'))
596
+ assert_equal("<mtable rowlines='solid'><mtr><mtd><mi>c</mi></mtd><mtd><mi>a</mi></mtd><mtd><mi>c</mi></mtd><mtd><mi>c</mi></mtd></mtr><mtr><mtd /><mtd /><mtd /><mtd /></mtr></mtable>", smml('\begin{array}{c@acc}c&c&c\\\\\hline\end{array}'))
597
+ assert_equal("<mtable rowlines='solid none solid'><mtr /><mtr><mtd><mi>a</mi></mtd></mtr><mtr><mtd><mi>b</mi></mtd></mtr><mtr><mtd /></mtr></mtable>", smml('\begin{array}{c}\hline a\\\\b\\\\\hline\end{array}'))
598
+ end
599
+
600
+ def test_leftright
601
+ assert_equal("<mfenced close=')' open='('><mrow><mfrac><mn>1</mn><mn>2</mn></mfrac></mrow></mfenced>", smml('\left(\frac12\right)'))
602
+
603
+ assert_equal("<mfenced close='&rfloor;' open='&lfloor;'><mrow><mi>a</mi></mrow></mfenced>", smml('\left \lfloor a\right \rfloor'))
604
+
605
+ assert_equal("<mfenced close='}' open='{'><mrow><mi>a</mi></mrow></mfenced>", smml('\left \{ a \right \}'))
606
+
607
+ assert_equal("<mfenced close='}' open='{'><mrow><mtable><mtr><mtd><mtable><mtr><mtd><mi>a</mi></mtd></mtr></mtable></mtd></mtr></mtable></mrow></mfenced>", smml('\left\{\begin{array}c\begin{array}ca\end{array}\end{array}\right\}'))
608
+
609
+ assert_equal("<mfenced close=')' open='('><mrow><msub><mo>&sum;</mo><mi>a</mi></msub></mrow></mfenced>", smml('\left(\sum_a\right)'))
610
+ assert_equal("<mfenced close=')' open='('><mrow><munder><mo>&sum;</mo><mi>a</mi></munder></mrow></mfenced>", smml('\left(\sum_a\right)', true))
611
+
612
+ e = assert_raises(ParseError){smml('\left(test')}
613
+ assert_equal(["Brace not closed.", '\left', '(test'], parse_error(e))
614
+
615
+ assert_equal("<mfenced close='&DoubleVerticalBar;' open='&DoubleVerticalBar;'><mrow><mi>a</mi></mrow></mfenced>", smml('\left\|a\right\|'))
616
+
617
+ e = assert_raises(ParseError){smml('\left')}
618
+ assert_equal(["Need brace here.", '\left', ""], parse_error(e))
619
+ end
620
+
621
+ def test_over
622
+ assert_equal("<mover><mi>a</mi><mo>&circ;</mo></mover>", smml('\hat a'))
623
+ assert_equal("<mover><mn>1</mn><mo>&circ;</mo></mover><mn>2</mn>", smml('\hat12'))
624
+ e = assert_raises(ParseError){smml('{\hat}a')}
625
+ assert_equal(["Syntax error.", '{\hat', '}a'], parse_error(e))
626
+ end
627
+
628
+ def test_under
629
+ assert_equal("<munder><mi>a</mi><mo>&macr;</mo></munder>", smml('\underline a'))
630
+ assert_equal("<munder><mn>1</mn><mo>&macr;</mo></munder><mn>2</mn>", smml('\underline12'))
631
+ e = assert_raises(ParseError){smml('{\underline}a')}
632
+ assert_equal(["Syntax error.", '{\underline', '}a'], parse_error(e))
633
+ end
634
+
635
+ def test_stackrel
636
+ assert_equal("<mover><mo>=</mo><mo>&rightarrow;</mo></mover>", smml('\stackrel\to='))
637
+ assert_equal("<mover><mn>2</mn><mn>1</mn></mover>", smml('\stackrel12'))
638
+ end
639
+
640
+ def test_comment
641
+ assert_equal("<mi>a</mi>", smml('a%b'))
642
+ end
643
+
644
+ def test_entity
645
+ p = Parser.new
646
+ e = assert_raises(ParseError){smml('\entity{therefore}', false, p)}
647
+ assert_equal(["Unregistered entity.", '\entity{', "therefore}"], parse_error(e))
648
+
649
+ p.unsecure_entity = true
650
+ assert_equal("<mo>&therefore;</mo>", smml('\entity{therefore}', false, p))
651
+
652
+ p.unsecure_entity = false
653
+ e = assert_raises(ParseError){smml('\entity{therefore}', false, p)}
654
+ assert_equal(["Unregistered entity.", '\entity{', "therefore}"], parse_error(e))
655
+
656
+ p.add_entity(['therefore'])
657
+ assert_equal("<mo>&therefore;</mo>", smml('\entity{therefore}', false, p))
658
+ end
659
+
660
+ def test_backslash
661
+ assert_equal("<br xmlns='http://www.w3.org/1999/xhtml' />", smml('\\\\'))
662
+ end
663
+
664
+ def test_macro
665
+ macro = <<'EOS'
666
+ \newcommand{\root}[2]{\sqrt[#1]{#2}}
667
+ \newcommand{\ROOT}[2]{\sqrt[#1]#2}
668
+ \newenvironment{braced}[2]{\left#1}{\right#2}
669
+ \newenvironment{sq}[2]{\sqrt[#2]{#1}}{\sqrt#2}
670
+ \newcommand{\R}{\mathbb R}
671
+ \newenvironment{BB}{\mathbb A}{\mathbb B}
672
+ EOS
673
+ p = Parser.new
674
+ p.macro.parse(macro)
675
+
676
+ assert_equal("<mroot><mrow><mn>2</mn></mrow><mn>1</mn></mroot>", smml('\root12', false, p))
677
+ assert_equal("<mroot><mrow><mn>34</mn></mrow><mn>12</mn></mroot>", smml('\root{12}{34}', false, p))
678
+ assert_equal("<mroot><mn>3</mn><mn>12</mn></mroot><mn>4</mn>", smml('\ROOT{12}{34}', false, p))
679
+ assert_parse_error('Error in macro(Need more parameter. "").', '', '\root'){smml('\root', false, p)}
680
+
681
+ assert_equal("<mfenced close=')' open='|'><mrow><mfrac><mn>1</mn><mn>2</mn></mfrac></mrow></mfenced>", smml('\begin{braced}{|}{)}\frac12\end{braced}', false, p))
682
+ assert_equal("<mroot><mrow><mn>12</mn></mrow><mn>34</mn></mroot><mi>a</mi><msqrt><mn>3</mn></msqrt><mn>4</mn>", smml('\begin{sq}{12}{34}a\end{sq}', false, p))
683
+ assert_parse_error("Need more parameter.", '\begin{braced}', ""){smml('\begin{braced}', false, p)}
684
+ assert_parse_error('Matching \end not exist.', '\begin{braced}', "123"){smml('\begin{braced}123', false, p)}
685
+ assert_parse_error("Environment mismatched.", '\begin{braced}123\end', '{brace}'){smml('\begin{braced}123\end{brace}', false, p)}
686
+ assert_equal("<mrow><mi>&Ropf;</mi></mrow>", smml('\R', false, p))
687
+ assert_equal("<mrow><mi>&Aopf;</mi></mrow><mrow><mi>&Bopf;</mi></mrow>", smml('\begin{BB}\end{BB}', false, p))
688
+ end
689
+
690
+ def test_macro_circular_reference
691
+ macro = <<'EOT'
692
+ \newcommand{\C}{\C}
693
+ \newenvironment{E}{\begin{E}}{\end{E}}
694
+ \newcommand{\D}{\begin{F}\end{F}}
695
+ \newenvironment{F}{\D}{}
696
+ EOT
697
+ ps = Parser.new
698
+ ps.macro.parse(macro)
699
+
700
+ e = assert_raises(ParseError){smml('\C', false, ps)}
701
+ assert_equal(["Circular reference.", "", '\C'], parse_error(e))
702
+
703
+ e = assert_raises(ParseError){smml('\begin{E}\end{E}', false, ps)}
704
+ assert_equal(["Circular reference.", "", '\begin{E}\end{E}'], parse_error(e))
705
+
706
+ e = assert_raises(ParseError){smml('\D', false, ps)}
707
+ assert_equal(["Circular reference.", "", '\D'], parse_error(e))
708
+
709
+ e = assert_raises(ParseError){smml('\begin{F}\end{F}', false, ps)}
710
+ assert_equal(["Circular reference.", "", '\begin{F}\end{F}'], parse_error(e))
711
+ end
712
+
713
+ def test_macro_non_circular_reference
714
+ macro = <<'EOT'
715
+ \newcommand{\C}{\dummy}
716
+ \newenvironment{E}{\dummy}{}
717
+ EOT
718
+ ps = Parser.new
719
+ ps.macro.parse(macro)
720
+
721
+ e = assert_raises(ParseError){smml('\C', false, ps)}
722
+ assert_equal(['Error in macro(Undefined command. "\dummy").', "", '\C'], parse_error(e))
723
+ e = assert_raises(ParseError){smml('\C', false, ps)}
724
+ assert_equal(['Error in macro(Undefined command. "\dummy").', "", '\C'], parse_error(e))
725
+
726
+ e = assert_raises(ParseError){smml('\begin{E}\end{E}', false, ps)}
727
+ assert_equal(['Error in macro(Undefined command. "\dummy").', '', '\begin{E}\end{E}'], parse_error(e))
728
+ e = assert_raises(ParseError){smml('\begin{E}\end{E}', false, ps)}
729
+ assert_equal(['Error in macro(Undefined command. "\dummy").', "", '\begin{E}\end{E}'], parse_error(e))
730
+ end
731
+
732
+ def test_macro_with_option
733
+ macro = <<'EOS'
734
+ \newcommand{\opt}[1][x]{#1}
735
+ \newcommand{\optparam}[2][]{#1#2}
736
+ \newenvironment{newenv}[1][x]{#1}{#1}
737
+ \newenvironment{optenv}[2][]{#1}{#2}
738
+ EOS
739
+
740
+ p = Parser.new
741
+ p.macro.parse(macro)
742
+
743
+ assert_equal("<mi>x</mi><mi>a</mi>", smml('\opt a', false, p))
744
+ assert_equal("<mn>0</mn><mi>a</mi>", smml('\opt[0] a', false, p))
745
+ assert_equal("<mi>a</mi>", smml('\optparam a', false, p))
746
+ assert_equal("<mn>0</mn><mi>a</mi>", smml('\optparam[0] a', false, p))
747
+
748
+ assert_equal("<mi>x</mi><mi>a</mi><mi>x</mi>", smml('\begin{newenv}a\end{newenv}', false, p))
749
+ assert_equal("<mn>0</mn><mi>a</mi><mn>0</mn>", smml('\begin{newenv}[0]a\end{newenv}', false, p))
750
+ assert_equal("<mi>a</mi><mn>0</mn>", smml('\begin{optenv}0a\end{optenv}', false, p))
751
+ assert_equal("<mn>0</mn><mi>a</mi><mn>1</mn>", smml('\begin{optenv}[0]1a\end{optenv}', false, p))
752
+ end
753
+
754
+ def test_matrix_env
755
+ assert_equal("<mtable><mtr><mtd /><mtd /><mtd /></mtr><mtr><mtd /><mtd /></mtr></mtable>", smml('\begin{matrix}&&\\\\&\end{matrix}'))
756
+ assert_parse_error("Environment mismatched.", '\begin{matrix}&&\\\\&\end', "{mat}"){smml('\begin{matrix}&&\\\\&\end{mat}')}
757
+ assert_parse_error("Matching \\end not exist.", '\begin{matrix}&&\\\\&', ''){smml('\begin{matrix}&&\\\\&')}
758
+ assert_equal("<mtable><mtr><mtd><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></mtd><mtd><mn>1</mn></mtd></mtr><mtr><mtd><mn>0</mn></mtd><mtd><mn>1</mn></mtd></mtr></mtable>", smml('\begin{matrix}\begin{matrix}a&b\\\\c&d\end{matrix}&1\\\\0&1\\\\\end{matrix}'))
759
+ assert_equal("<mtable />", smml('\begin{matrix}\end{matrix}'))
760
+ assert_equal("<mtable rowlines='solid none solid'><mtr /><mtr><mtd><mi>a</mi></mtd></mtr><mtr><mtd><mi>b</mi></mtd></mtr><mtr /></mtable>", smml('\begin{matrix}\hline a\\\\b\\\\\hline\end{matrix}'))
761
+
762
+ assert_equal("<mtable />", smml('\begin{smallmatrix}\end{smallmatrix}'))
763
+ assert_equal("<mfenced close=')' open='('><mrow><mtable /></mrow></mfenced>", smml('\begin{pmatrix}\end{pmatrix}'))
764
+ assert_equal("<mfenced close=']' open='['><mrow><mtable /></mrow></mfenced>", smml('\begin{bmatrix}\end{bmatrix}'))
765
+ assert_equal("<mfenced close='}' open='{'><mrow><mtable /></mrow></mfenced>", smml('\begin{Bmatrix}\end{Bmatrix}'))
766
+ assert_equal("<mfenced close='|' open='|'><mrow><mtable /></mrow></mfenced>", smml('\begin{vmatrix}\end{vmatrix}'))
767
+ assert_equal("<mfenced close='&DoubleVerticalBar;' open='&DoubleVerticalBar;'><mrow><mtable /></mrow></mfenced>", smml('\begin{Vmatrix}\end{Vmatrix}'))
768
+ end
769
+
770
+ def test_safe_mode
771
+ Thread.start do
772
+ $SAFE=1
773
+ assert_nothing_raised{smml('\alpha'.taint)}
774
+ end.join
775
+ end
776
+
777
+ def test_symbol
778
+ assert_equal("<mo><mfrac linethickness='0' mathsize='1%'><mo>&prec;</mo><mo>&ne;</mo></mfrac></mo>", smml('\precneqq'))
779
+ end
780
+ end