mathml 0.8.1 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,9 +3,11 @@
3
3
  # Copyright (C) 2005, KURODA Hiraku <hiraku@hinet.mydns.jp>
4
4
  # You can redistribute it and/or modify it under GPL2.
5
5
 
6
- unless __FILE__ == File.expand_path(__FILE__)
7
- require File.expand_path(File.dirname(__FILE__))+"/"+File.basename(__FILE__, ".rb")
8
- else
6
+ warn "*"*60 << "\n" << <<EOT << "*"*60
7
+ [DEPRECATION]
8
+ "mathml" gem is deprecated.
9
+ Please use "math_ml" gem instead.
10
+ EOT
9
11
 
10
12
  require "strscan"
11
13
  module MathML
@@ -18,1880 +20,12 @@ module MathML
18
20
  end
19
21
 
20
22
  def self.pcstring(s, encoded=false)
21
- EimXML::PCString.new(s, encoded)
23
+ s.is_a?(EimXML::PCString) ? s : EimXML::PCString.new(s, encoded)
22
24
  end
23
25
 
24
- PCString = EimXML::PCString
25
-
26
26
  class Error < StandardError; end
27
-
28
- class Element < XMLElement
29
- attr_reader :display_style
30
-
31
- def as_display_style
32
- @display_style = true
33
- self
34
- end
35
-
36
- def <<(s)
37
- s = MathML.pcstring(s) if String===s
38
- super(s)
39
- end
40
- end
41
-
42
- module Variant
43
- NORMAL = "normal"
44
- BOLD = "bold"
45
- BOLD_ITALIC = "bold-italic"
46
- def variant=(v)
47
- self["mathvariant"] = v
48
- end
49
- end
50
-
51
- module Align
52
- CENTER = "center"
53
- LEFT = "left"
54
- RIGHT = "right"
55
- end
56
-
57
- module Line
58
- SOLID = "solid"
59
- NONE = "none"
60
- end
61
-
62
- class Math < XMLElement
63
- def initialize(display_style)
64
- super("math", "xmlns"=>"http://www.w3.org/1998/Math/MathML")
65
- self[:display] = display_style ? "block" : "inline"
66
- end
67
- end
68
-
69
- class Row < Element
70
- def initialize
71
- super("mrow")
72
- end
73
- end
74
-
75
- class None < Element
76
- def initialize
77
- super("none")
78
- end
79
- end
80
-
81
- class Space < Element
82
- def initialize(width)
83
- super("mspace", "width"=>width)
84
- end
85
- end
86
-
87
- class Fenced < Element
88
- attr_reader :open, :close
89
-
90
- def initialize
91
- super("mfenced")
92
- end
93
-
94
- def open=(o)
95
- o = "" if o.to_s=="." || !o
96
- o = "{" if o.to_s=="\\{"
97
- self[:open] = MathML.pcstring(o, true)
98
- end
99
-
100
- def close=(c)
101
- c = "" if c.to_s=="." || !c
102
- c = "}" if c.to_s=="\\}"
103
- self[:close] = MathML.pcstring(c, true)
104
- end
105
- end
106
-
107
- class Frac < Element
108
- def initialize(numerator, denominator)
109
- super("mfrac")
110
- self << numerator
111
- self << denominator
112
- end
113
- end
114
-
115
- class SubSup < Element
116
- attr_reader :sub, :sup, :body
117
-
118
- def initialize(display_style, body)
119
- super("mrow")
120
- as_display_style if display_style
121
- @body = body
122
-
123
- update_name
124
- end
125
-
126
- def update_name
127
- if @sub || @sup
128
- name = "m"
129
- name << (@sub ? (@display_style ? "under" : "sub") : "")
130
- name << (@sup ? (@display_style ? "over" : "sup") : "")
131
- else
132
- name = "mrow"
133
- end
134
- self.name = name
135
- end
136
- protected :update_name
137
-
138
- def update_contents
139
- contents.clear
140
- contents << @body
141
- contents << @sub if @sub
142
- contents << @sup if @sup
143
- end
144
- protected :update_contents
145
-
146
- def sub=(sub)
147
- @sub = sub
148
- update_name
149
- end
150
-
151
- def sup=(sup)
152
- @sup = sup
153
- update_name
154
- end
155
-
156
- def to_xml_with_indent(dst=String.new, level=0, is_head=true)
157
- update_contents
158
- super
159
- end
160
- end
161
-
162
- class Over < Element
163
- def initialize(base, over)
164
- super("mover")
165
- self << base << over
166
- end
167
- end
168
-
169
- class Under < Element
170
- def initialize(base, under)
171
- super("munder")
172
- self << base << under
173
- end
174
- end
175
-
176
- class Number < Element
177
- def initialize
178
- super("mn")
179
- end
180
- end
181
-
182
- class Identifier < Element
183
- def initialize
184
- super("mi")
185
- end
186
- end
187
-
188
- class Operator < Element
189
- def initialize
190
- super("mo")
191
- end
192
- end
193
-
194
- class Text < Element
195
- def initialize
196
- super("mtext")
197
- end
198
- end
199
-
200
- class Sqrt < Element
201
- def initialize
202
- super("msqrt")
203
- end
204
- end
205
-
206
- class Root < Element
207
- def initialize(index, base)
208
- super("mroot")
209
- self << base
210
- self << index
211
- end
212
- end
213
-
214
- class Table < Element
215
- def initialize
216
- super("mtable")
217
- end
218
-
219
- def set_align_attribute(name, a, default)
220
- if a.is_a?(Array) && a.size>0
221
- value = ""
222
- a.each do |i|
223
- value << " "+i
224
- end
225
- if value =~ /^( #{default})*$/
226
- @attributes.delete(name)
227
- else
228
- @attributes[name] = value.strip
229
- end
230
- else
231
- @attributes.delete(name)
232
- end
233
- end
234
-
235
- def aligns=(a)
236
- set_align_attribute("columnalign", a, Align::CENTER)
237
- end
238
-
239
- def vlines=(a)
240
- set_align_attribute("columnlines", a, Line::NONE)
241
- end
242
-
243
- def hlines=(a)
244
- set_align_attribute("rowlines", a, Line::NONE)
245
- end
246
- end
247
-
248
- class Tr < Element
249
- def initialize
250
- super("mtr")
251
- end
252
- end
253
-
254
- class Td < Element
255
- def initialize
256
- super("mtd")
257
- end
258
- end
259
-
260
- module LaTeX
261
- MBEC = /\\.|[^\\]/m
262
-
263
- module RE
264
- SPACE = /(?:\s|%.*$)/
265
- NUMERICS = /(?:\.\d+)|(?:\d+(\.\d+)?)/
266
- OPERATORS = /[,\.\+\-\*=\/\(\)\[\]<>"|;:!]/
267
- ALPHABETS = /[a-zA-Z]/
268
- BLOCK = /\A\{(.*?)\}\z/m
269
- OPTION = /\A\[(.*)\]\z/m
270
- COMMANDS = /\\([a-zA-Z]+|[^a-zA-Z])/
271
- WBSLASH = /\\\\/
272
- BRACES = /\A([.|\[\]\(\)<>])\z/
273
- end
274
-
275
- module Font
276
- NORMAL = 0
277
- BOLD = 1
278
- BLACKBOLD = 2
279
- SCRIPT = 3
280
- FRAKTUR = 4
281
- ROMAN = 5
282
- BOLD_ITALIC = 6
283
- end
284
-
285
- class BlockNotClosed < StandardError; end
286
- class NotEnvironment < StandardError; end
287
- class EnvironmentNotEnd < StandardError; end
288
- class NeedParameter < StandardError; end
289
- class EndMismatchToBegin < StandardError; end
290
- class OptionNotClosed < StandardError; end
291
-
292
- class Scanner < StringScanner
293
- def done
294
- self.string[0, pos]
295
- end
296
-
297
- def scan_space
298
- _scan(/#{RE::SPACE}+/)
299
- end
300
-
301
- def skip_space_and(check_mode)
302
- opos = pos
303
- scan_space
304
- r = yield
305
- self.pos = opos if check_mode || !r
306
- r
307
- end
308
-
309
- alias :_check :check
310
- def check(re)
311
- skip_space_and(true){_check(re)}
312
- end
313
-
314
- alias :_scan :scan
315
- def scan(re)
316
- skip_space_and(false){_scan(re)}
317
- end
318
-
319
- alias :_eos? :eos?
320
- def eos?
321
- _eos? || _check(/#{RE::SPACE}+\z/)
322
- end
323
-
324
- def check_command
325
- check(RE::COMMANDS)
326
- end
327
-
328
- def scan_command
329
- scan(RE::COMMANDS)
330
- end
331
-
332
- def peek_command
333
- check_command ? self[1] : nil
334
- end
335
-
336
- def check_block
337
- skip_space_and(true){scan_block}
338
- end
339
-
340
- def scan_block
341
- return nil unless scan(/\{/)
342
- block = "{"
343
- bpos = pos-1
344
- nest = 1
345
- while _scan(/(#{MBEC}*?)([\{\}])/)
346
- block << matched
347
- case self[2]
348
- when "{"
349
- nest+=1
350
- when "}"
351
- nest-=1
352
- break if nest==0
353
- end
354
- end
355
- if nest>0
356
- self.pos = bpos
357
- raise BlockNotClosed
358
- end
359
- self.pos = bpos
360
- _scan(/\A\{(#{Regexp.escape(block[RE::BLOCK, 1].to_s)})\}/)
361
- end
362
-
363
- def check_any(remain_space=false)
364
- skip_space_and(true){scan_any(remain_space)}
365
- end
366
-
367
- def scan_any(remain_space=false)
368
- p = pos
369
- scan_space
370
- r = remain_space ? matched.to_s : ""
371
- case
372
- when s = scan_block
373
- when s = scan_command
374
- else
375
- unless _scan(/./) || remain_space
376
- self.pos = p
377
- return nil
378
- end
379
- s = matched.to_s
380
- end
381
- r << s
382
- end
383
-
384
- def scan_option
385
- return nil unless scan(/\[/)
386
- opt = "["
387
- p = pos-1
388
- until (s=scan_any(true)) =~ /\A#{RE::SPACE}*\]\z/
389
- opt << s
390
- if eos?
391
- self.pos = p
392
- raise OptionNotClosed
393
- end
394
- end
395
- opt << s
396
- self.pos = p
397
- _scan(/\A\[(#{Regexp.escape(opt[RE::OPTION, 1].to_s)})\]/)
398
- end
399
-
400
- def check_option
401
- skip_space_and(true){scan_option}
402
- end
403
- end
404
-
405
- class ParseError < StandardError
406
- attr_accessor :rest, :done
407
- def initialize(message, rest = "", done = "")
408
- @done = done
409
- @rest = rest
410
- super(message)
411
- end
412
-
413
- def inspect
414
- "#{message} : '#{@done}' / '#{@rest}'\n"+backtrace[0..5].join("\n")
415
- end
416
- end
417
-
418
- class Macro
419
- class Command
420
- attr_reader :num, :body, :option
421
- def initialize(n, b, o)
422
- @num = n
423
- @body = b
424
- @option = o
425
- end
426
- end
427
-
428
- class Environment
429
- attr_reader :num, :beginning, :ending, :option
430
- def initialize(n, b, e, o)
431
- @num = n
432
- @beginning = b
433
- @ending = e
434
- @option = o
435
- end
436
- end
437
-
438
- def initialize
439
- @commands = Hash.new
440
- @environments = Hash.new
441
- end
442
-
443
- def parse_error(message, rest="", whole=nil)
444
- rest = whole[/\A.*?(#{Regexp.escape(rest)}.*\z)/, 1] if whole
445
- rest << @scanner.rest
446
- done = @scanner.string[0, @scanner.string.size-rest.size]
447
- ParseError.new(message, rest, done)
448
- end
449
-
450
- def parse(src)
451
- @scanner = Scanner.new(src)
452
- until @scanner.eos?
453
- unless @scanner.scan_command
454
- @scanner.scan_space
455
- raise parse_error("Syntax error.")
456
- end
457
- case @scanner[1]
458
- when "newcommand"
459
- parse_newcommand
460
- when "newenvironment"
461
- parse_newenvironment
462
- else
463
- raise parse_error("Syntax error.", @scanner.matched)
464
- end
465
- end
466
- rescue BlockNotClosed => e
467
- raise parse_error("Block not closed.")
468
- rescue OptionNotClosed => e
469
- raise parse_error("Option not closed.")
470
- end
471
-
472
- def scan_num_of_parameter
473
- if @scanner.scan_option
474
- raise parse_error("Need positive number.", @scanner[1]+"]") unless @scanner[1]=~/\A#{RE::SPACE}*\d+#{RE::SPACE}*\z/
475
- @scanner[1].to_i
476
- else
477
- 0
478
- end
479
- end
480
-
481
- def check_parameter_numbers(src, opt, whole)
482
- s = Scanner.new(src)
483
- until s.eos?
484
- case
485
- when s.scan(/#{MBEC}*?\#(\d+|.)/)
486
- raise parse_error("Need positive number.") unless s[1]=~/\d+/
487
- raise parse_error("Parameter \# too large.", s[1]+s.rest, whole) if s[1].to_i>opt
488
- else
489
- return nil
490
- end
491
- end
492
- end
493
-
494
- def parse_newcommand
495
- case
496
- when @scanner.scan_block
497
- s = Scanner.new(@scanner[1])
498
- raise parse_error("Need newcommand.", s.rest+"}") unless s.scan_command
499
- com = s[1]
500
- raise parse_error("Syntax error." ,s.rest+"}") unless s.eos?
501
- when @scanner.scan_command
502
- s = Scanner.new(@scanner[1])
503
- com = s.scan_command
504
- else
505
- raise parse_error("Need newcommand.")
506
- end
507
-
508
- optnum = scan_num_of_parameter
509
- opt = @scanner.scan_option ? @scanner[1] : nil
510
-
511
- case
512
- when @scanner.scan_block
513
- body = @scanner[1]
514
- when @scanner.scan_command
515
- body = @scanner.matched
516
- else
517
- body = @scanner.scan(/./)
518
- end
519
-
520
- raise parse_error("Need parameter.") unless body
521
-
522
- check_parameter_numbers(body, optnum, @scanner.matched)
523
-
524
- optnum-=1 if opt
525
- @commands[com] = Command.new(optnum, body, opt)
526
- end
527
-
528
- def parse_newenvironment
529
- case
530
- when @scanner.scan_block
531
- env = @scanner[1]
532
- when @scanner.scan_command
533
- raise ParseError.new
534
- when @scanner.scan(/./)
535
- env = @scanner.matched
536
- end
537
- raise parse_error("Syntax error.", env[/\A.*?(\\.*\z)/, 1], @scanner.matched) if env=~/\\/
538
-
539
- optnum = scan_num_of_parameter
540
- opt = @scanner.scan_option ? @scanner[1] : nil
541
-
542
- b = @scanner.scan_block ? @scanner[1] : @scanner.scan_any
543
- raise parse_error("Need begin block.") unless b
544
- check_parameter_numbers(b, optnum, @scanner.matched)
545
- e = @scanner.scan_block ? @scanner[1] : @scanner.scan_any
546
- raise parse_error("Need end block.") unless e
547
- check_parameter_numbers(e, optnum, @scanner.matched)
548
-
549
- optnum -= 1 if opt
550
- @environments[env] = Environment.new(optnum, b, e, opt)
551
- end
552
-
553
- def commands(com)
554
- @commands[com]
555
- end
556
-
557
- def expand_command(com, params, opt=nil)
558
- return nil unless @commands.has_key?(com)
559
- c = @commands[com]
560
- opt = c.option if c.option && !opt
561
- params.unshift(opt) if c.option
562
- raise ParseError.new("Need more parameter.") if params.size < c.num
563
-
564
- c.body.gsub(/(#{MBEC}*?)\#(\d+)/) do
565
- $1.to_s << params[$2.to_i-1]
566
- end
567
- end
568
-
569
- def environments(env)
570
- @environments[env]
571
- end
572
-
573
- def expand_environment(env, body, params, opt=nil)
574
- return nil unless @environments.has_key?(env)
575
- e = @environments[env]
576
- opt = e.option if e.option && !opt
577
- params.unshift(opt) if e.option
578
- raise ParseError.new("Need more parameter.") if params.size < e.num
579
-
580
- bg = e.beginning.gsub(/(#{MBEC}*?)\#(\d+)/) do
581
- $1.to_s << params[$2.to_i-1]
582
- end
583
-
584
- en = e.ending.gsub(/(#{MBEC}*?)\#(\d+)/) do
585
- $1.to_s << params[$2.to_i-1]
586
- end
587
-
588
- " #{bg} #{body} #{en} "
589
- end
590
- end
591
-
592
- module BuiltinCommands; end
593
- module BuiltinGroups; end
594
- module BuiltinEnvironments; end
595
-
596
- class Parser
597
- class CircularReferenceCommand < StandardError; end
598
-
599
- include LaTeX
600
-
601
- include BuiltinEnvironments
602
- include BuiltinGroups
603
- include BuiltinCommands
604
-
605
- BUILTIN_MACRO = <<'EOS'
606
- \newenvironment{smallmatrix}{\begin{matrix}}{\end{matrix}}
607
- \newenvironment{pmatrix}{\left(\begin{matrix}}{\end{matrix}\right)}
608
- \newenvironment{bmatrix}{\left[\begin{matrix}}{\end{matrix}\right]}
609
- \newenvironment{Bmatrix}{\left\{\begin{matrix}}{\end{matrix}\right\}}
610
- \newenvironment{vmatrix}{\left|\begin{matrix}}{\end{matrix}\right|}
611
- \newenvironment{Vmatrix}{\left\|\begin{matrix}}{\end{matrix}\right\|}
612
- EOS
613
-
614
- attr_accessor :unsecure_entity
615
- attr_reader :macro
616
- def initialize
617
- @unsecure_entity = false
618
- @entities = Hash.new
619
- @commands = Hash.new
620
- @symbols = Hash.new
621
- @delimiters = Array.new
622
- @group_begins = Hash.new
623
- @group_ends = Hash.new
624
- @macro = Macro.new
625
- @macro.parse(BUILTIN_MACRO)
626
- @expanded_command = Array.new
627
- @expanded_environment = Array.new
628
-
629
- super
630
- end
631
-
632
- def add_entity(list)
633
- list.each do |i|
634
- @entities[i] = true
635
- end
636
- end
637
-
638
- def parse(src, displaystyle=false)
639
- @ds = displaystyle
640
- begin
641
- parse_into(src, Math.new(@ds), Font::NORMAL)
642
- rescue ParseError => e
643
- e.done = src[0...(src.size - e.rest.size)]
644
- raise
645
- end
646
- end
647
-
648
- def push_container(container, scanner=@scanner, font=@font)
649
- data = [@container, @scanner, @font]
650
- @container, @scanner, @font = [container, scanner, font]
651
- begin
652
- yield container
653
- container
654
- ensure
655
- @container, @scanner, @font = data
656
- end
657
- end
658
-
659
- def add_plugin(plugin)
660
- self.extend(plugin)
661
- end
662
-
663
- def add_commands(*a)
664
- if a.size==1 && Hash===a[0]
665
- @commands.merge!(a[0])
666
- else
667
- a.each{|i| @commands[i] = false}
668
- end
669
- end
670
-
671
- def add_multi_command(m, *a)
672
- a.each{|i| @commands[i] = m}
673
- end
674
-
675
- def add_sym_cmd(hash)
676
- @symbols.merge!(hash)
677
- end
678
-
679
- def add_delimiter(list)
680
- @delimiters.concat(list)
681
- end
682
-
683
- def add_group(begin_name, end_name, method=nil)
684
- @group_begins[begin_name] = method
685
- @group_ends[end_name] = begin_name
686
- end
687
-
688
- private
689
- def parse_into(src, parent, font=nil)
690
- orig = [@scanner, @container, @font, @ds]
691
- @scanner = Scanner.new(src)
692
- @container = parent
693
- @font = font if font
694
- begin
695
- until @scanner.eos?
696
- @container << parse_to_element(true)
697
- end
698
- @container
699
- rescue BlockNotClosed => e
700
- raise ParseError.new("Block not closed.", @scanner.rest)
701
- rescue NotEnvironment => e
702
- raise ParseError.new("Not environment.", @scanner.rest)
703
- rescue EnvironmentNotEnd => e
704
- raise ParseError.new("Environment not end.", @scanner.rest)
705
- rescue OptionNotClosed => e
706
- raise ParseError.new("Option not closed.", @scanner.rest)
707
- rescue ParseError => e
708
- e.rest << @scanner.rest.to_s
709
- raise
710
- ensure
711
- @scanner, @container, @font, @ds = orig
712
- end
713
- end
714
-
715
- def parse_any(message = "Syntax error.")
716
- raise ParseError.new(message) unless @scanner.scan_any
717
- s = @scanner
718
- @scanner = Scanner.new(@scanner.matched)
719
- begin
720
- parse_to_element
721
- ensure
722
- @scanner = s
723
- end
724
- end
725
-
726
- def parse_to_element(whole_group = false)
727
- if whole_group && @group_begins.has_key?(@scanner.peek_command)
728
- @scanner.scan_command
729
- parse_group
730
- else
731
- case
732
- when @scanner.scan(RE::NUMERICS)
733
- parse_num
734
- when @scanner.scan(RE::ALPHABETS)
735
- parse_char
736
- when @scanner.scan(RE::OPERATORS)
737
- parse_operator
738
- when @scanner.scan_block
739
- parse_block
740
- when @scanner.scan(/_/)
741
- parse_sub
742
- when @scanner.scan(/'+|\^/)
743
- parse_sup
744
- when @scanner.scan_command
745
- parse_command
746
- else
747
- raise ParseError.new('Syntax error.')
748
- end
749
- end
750
- end
751
-
752
- def parse_num
753
- n = Number.new
754
- n.extend(Variant).variant = Variant::BOLD if @font==Font::BOLD
755
- n << @scanner.matched
756
- end
757
-
758
- def parse_char
759
- c = @scanner.matched
760
- i = Identifier.new
761
- case @font
762
- when Font::ROMAN
763
- i.extend(Variant).variant = Variant::NORMAL
764
- when Font::BOLD
765
- i.extend(Variant).variant = Variant::BOLD
766
- when Font::BOLD_ITALIC
767
- i.extend(Variant).variant = Variant::BOLD_ITALIC
768
- when Font::BLACKBOLD
769
- c = MathML.pcstring(%Q[&#{c}opf;], true)
770
- when Font::SCRIPT
771
- c = MathML.pcstring(%Q[&#{c}scr;], true)
772
- when Font::FRAKTUR
773
- c = MathML.pcstring(%Q[&#{c}fr;], true)
774
- end
775
- i << c
776
- end
777
-
778
- def parse_operator
779
- o = @scanner.matched
780
- Operator.new << o
781
- end
782
-
783
- def parse_block
784
- os = @scanner
785
- @scanner = Scanner.new(@scanner[1])
786
- begin
787
- push_container(Row.new) do |r|
788
- r << parse_to_element(true) until @scanner.eos?
789
- end
790
- rescue ParseError => e
791
- e.rest << '}'
792
- raise
793
- ensure
794
- @scanner = os
795
- end
796
- end
797
-
798
- def parse_sub
799
- e = @container.pop
800
- e = None.new unless e
801
- e = SubSup.new(@ds && e.display_style, e) unless e.is_a?(SubSup)
802
- raise ParseError.new("Double subscript.", "_") if e.sub
803
- e.sub = parse_any("Subscript not exist.")
804
- e
805
- end
806
-
807
- def parse_sup
808
- e = @container.pop
809
- e = None.new unless e
810
- e = SubSup.new(@ds && e.display_style, e) unless e.is_a?(SubSup)
811
- raise ParseError.new("Double superscript.", @scanner[0]) if e.sup
812
- if /'+/=~@scanner[0]
813
- prime = Operator.new
814
- prime << MathML.pcstring('&prime;'*@scanner[0].size, true)
815
- unless @scanner.scan(/\^/)
816
- e.sup = prime
817
- return e
818
- end
819
- end
820
- sup = parse_any("Superscript not exist.")
821
-
822
- if prime
823
- unless sup.is_a?(Row)
824
- r = Row.new
825
- r << sup
826
- sup = r
827
- end
828
- sup.contents.insert(0, prime)
829
- end
830
-
831
- e.sup = sup
832
- e
833
- end
834
-
835
- def entitize(str)
836
- MathML.pcstring(str.sub(/^(.*)$/){"&#{$1};"}, true)
837
- end
838
-
839
- def parse_symbol_command(com, plain=false)
840
- unless @symbols.include?(com)
841
- @scanner.pos = @scanner.pos-(com.size+1)
842
- raise ParseError.new("Undefined command.")
843
- end
844
- data = @symbols[com]
845
- return nil unless data
846
-
847
- su = data[0]
848
- el = data[1]
849
- el = :o unless el
850
- s = data[2]
851
- s = com.dup.untaint.to_sym unless s
852
- s = com if s.is_a?(String) && s.length==0
853
-
854
- case el
855
- when :I
856
- el = Identifier.new
857
- when :i
858
- el = Identifier.new
859
- el.extend(Variant).variant = Variant::NORMAL unless s.is_a?(String)&&s.length>1
860
- when :o
861
- el = Operator.new
862
- when :n
863
- el = Number.new
864
- else
865
- raise ParseError.new("Inner data broken.")
866
- end
867
-
868
- case s
869
- when String
870
- when Fixnum
871
- s = "&\#x#{s.to_s(16)};"
872
- when Symbol
873
- s = "&#{s.to_s};"
874
- end
875
-
876
- return s if plain
877
- el << MathML.pcstring(s, true)
878
- el.as_display_style if su==:u
879
- el
880
- end
881
-
882
- def parse_command
883
- com = @scanner[1]
884
- matched = @scanner.matched
885
- pos = @scanner.pos-matched.size
886
- macro = @macro.commands(com)
887
- if macro
888
- begin
889
- flg = @expanded_command.include?(com)
890
- @expanded_command.push(com)
891
- raise CircularReferenceCommand if flg
892
- option = (macro.option && @scanner.scan_option) ? @scanner[1] : nil
893
- params = Array.new
894
- (1..macro.num).each do
895
- params << (@scanner.scan_block ? @scanner[1] : @scanner.scan_any)
896
- raise ParseError.new("Need more parameter.") unless params.last
897
- end
898
- r = parse_into(@macro.expand_command(com, params, option), Array.new)
899
- return r
900
- rescue CircularReferenceCommand
901
- if @expanded_command.size>1
902
- raise
903
- else
904
- @scanner.pos = pos
905
- raise ParseError.new("Circular reference.")
906
- end
907
- rescue ParseError => e
908
- if @expanded_command.size>1
909
- raise
910
- else
911
- @scanner.pos = pos
912
- raise ParseError.new(%[Error in macro(#{e.message} "#{e.rest.strip}").])
913
- end
914
- ensure
915
- @expanded_command.pop
916
- end
917
- elsif @commands.key?(com)
918
- m = @commands[com]
919
- m = com unless m
920
- return __send__("cmd_#{m.to_s}")
921
- end
922
- parse_symbol_command(com)
923
- end
924
-
925
- def parse_mathfont(font)
926
- f = @font
927
- @font = font
928
- begin
929
- push_container(Row.new){|r| r << parse_any}
930
- ensure
931
- @font = f
932
- end
933
- end
934
-
935
- def parse_group
936
- font = @font
937
- begin
938
- g = @group_begins[@scanner[1]]
939
- g = @scanner[1] unless g
940
- __send__("grp_#{g.to_s}")
941
- ensure
942
- @font = font
943
- end
944
- end
945
- end
946
-
947
- module BuiltinCommands
948
- OVERS = {'hat'=>'circ', 'breve'=>'smile', 'grave'=>'grave',
949
- 'acute'=>'acute', 'dot'=>'sdot', 'ddot'=>'nldr', 'tilde'=>'tilde',
950
- 'bar'=>'macr', 'vec'=>'rightarrow', 'check'=>'vee', 'widehat'=>'circ',
951
- 'overline'=>'macr', 'widetilde'=>'tilde', 'overbrace'=>'OverBrace'}
952
- UNDERS = {'underbrace'=>'UnderBrace', 'underline'=>'macr'}
953
-
954
- def initialize
955
- add_commands("\\"=>:backslash)
956
- add_commands("entity", "stackrel", "frac", "sqrt", "mbox")
957
- add_multi_command(:hat_etc, 'hat', 'breve', 'grave', 'acute', 'dot', 'ddot', 'tilde', 'bar', 'vec', 'check', 'widehat', 'overline', 'widetilde', 'overbrace')
958
- add_multi_command(:underbrace_etc, 'underbrace', 'underline')
959
- add_multi_command(:quad_etc, "quad", "qquad", ",", ":", ";")
960
- add_multi_command(:it_etc, "it", "rm", "bf")
961
- add_multi_command(:mathit_etc, "mathit", "mathrm", "mathbf", "bm", "mathbb", "mathscr", "mathfrak")
962
- add_sym_cmd(SymbolCommands)
963
- add_delimiter(Delimiters)
964
-
965
- super
966
- end
967
-
968
- def cmd_backslash
969
- @ds ? nil : XMLElement.new("br", "xmlns"=>"http://www.w3.org/1999/xhtml")
970
- end
971
-
972
- def cmd_hat_etc
973
- com = @scanner[1]
974
- Over.new(parse_any, Operator.new << entitize(OVERS[com]))
975
- end
976
-
977
- def cmd_underbrace_etc
978
- com = @scanner[1]
979
- Under.new(parse_any, Operator.new << entitize(UNDERS[com]))
980
- end
981
-
982
- def cmd_entity
983
- param = @scanner.scan_block ? @scanner[1] : @scanner.scan(/./)
984
- raise ParseError.new("Need parameter.") unless param
985
- unless @unsecure_entity || @entities[param]
986
- param =@scanner.matched[/\A\{#{RE::SPACE}*(.*\})\z/, 1] if @scanner.matched=~RE::BLOCK
987
- @scanner.pos = @scanner.pos-(param.size)
988
- raise ParseError.new("Unregistered entity.")
989
- end
990
- Operator.new << entitize(param)
991
- end
992
-
993
- def cmd_stackrel
994
- o = parse_any; b = parse_any
995
- Over.new(b, o)
996
- end
997
-
998
- def cmd_quad_etc
999
- case @scanner[1]
1000
- when 'quad'
1001
- Space.new("1em")
1002
- when 'qquad'
1003
- Space.new("2em")
1004
- when ','
1005
- Space.new("0.167em")
1006
- when ':'
1007
- Space.new("0.222em")
1008
- when ';'
1009
- Space.new("0.278em")
1010
- end
1011
- end
1012
-
1013
- def cmd_it_etc
1014
- case @scanner[1]
1015
- when 'it'
1016
- @font = Font::NORMAL
1017
- when 'rm'
1018
- @font = Font::ROMAN
1019
- when 'bf'
1020
- @font = Font::BOLD
1021
- end
1022
- nil
1023
- end
1024
-
1025
- def cmd_mathit_etc
1026
- case @scanner[1]
1027
- when 'mathit'
1028
- parse_mathfont(Font::NORMAL)
1029
- when 'mathrm'
1030
- parse_mathfont(Font::ROMAN)
1031
- when 'mathbf'
1032
- parse_mathfont(Font::BOLD)
1033
- when 'bm'
1034
- parse_mathfont(Font::BOLD_ITALIC)
1035
- when 'mathbb'
1036
- parse_mathfont(Font::BLACKBOLD)
1037
- when 'mathscr'
1038
- parse_mathfont(Font::SCRIPT)
1039
- when 'mathfrak'
1040
- parse_mathfont(Font::FRAKTUR)
1041
- end
1042
- end
1043
-
1044
- def cmd_frac
1045
- n = parse_any; d = parse_any
1046
- Frac.new(n, d)
1047
- end
1048
-
1049
- def cmd_sqrt
1050
- if @scanner.scan_option
1051
- i = parse_into(@scanner[1], Array.new)
1052
- i = i.size==1 ? i[0] : (Row.new << i)
1053
- b = parse_any
1054
- Root.new(i, b)
1055
- else
1056
- Sqrt.new << parse_any
1057
- end
1058
- end
1059
-
1060
- def cmd_mbox
1061
- @scanner.scan_any
1062
- Text.new << (@scanner.matched =~ RE::BLOCK ? @scanner[1] : @scanner.matched)
1063
- end
1064
- end
1065
-
1066
- module BuiltinGroups
1067
- class CircularReferenceEnvironment < StandardError; end
1068
-
1069
- def initialize
1070
- add_group("begin", "end")
1071
- add_group("left", "right", :left_etc)
1072
- add_group("bigg", "bigg", :left_etc)
1073
- @environments = Hash.new
1074
-
1075
- super
1076
- end
1077
-
1078
- def add_environment(*a)
1079
- @environments = Hash.new unless @environments
1080
- if a.size==1 && Hash===a[0]
1081
- @environments.merge!(hash)
1082
- else
1083
- a.each{|i| @environments[i] = false}
1084
- end
1085
- end
1086
-
1087
- def grp_begin
1088
- matched = @scanner.matched
1089
- begin_pos = @scanner.pos-matched.size
1090
- en = @scanner.scan_block ? @scanner[1] : @scanner.scan_any
1091
- raise ParseError.new('Environment name not exist.') unless en
1092
-
1093
- macro = @macro.environments(en)
1094
- if macro
1095
- begin
1096
- flg = @expanded_environment.include?(en)
1097
- @expanded_environment.push(en)
1098
- raise CircularReferenceEnvironment if flg
1099
-
1100
- pos = @scanner.pos
1101
- option = (macro.option && @scanner.scan_option) ? @scanner[1] : nil
1102
- params = Array.new
1103
- (1..macro.num).each do
1104
- params << (@scanner.scan_block ? @scanner[1] : @scanner.scan_any)
1105
- raise ParseError.new("Need more parameter.") unless params.last
1106
- end
1107
- body = ""
1108
- grpnest = 0
1109
- until @scanner.peek_command=="end" && grpnest==0
1110
- if @scanner.eos?
1111
- @scanner.pos = pos
1112
- raise ParseError.new('Matching \end not exist.')
1113
- end
1114
- com = @scanner.peek_command
1115
- grpnest += 1 if @group_begins.has_key?(com)
1116
- grpnest -=1 if @group_ends.has_key?(com) && @group_begins[com]
1117
- raise ParseError.new("Syntax error.") if grpnest<0
1118
-
1119
- body << @scanner.scan_any(true)
1120
- end
1121
- @scanner.scan_command
1122
- raise ParseError.new("Environment mismatched.", @scanner.matched) unless en==(@scanner.scan_block ? @scanner[1] : @scanner.scan_any)
1123
- begin
1124
- return parse_into(@macro.expand_environment(en, body, params, option), Array.new)
1125
- rescue CircularReferenceEnvironment
1126
- if @expanded_environment.size>1
1127
- raise
1128
- else
1129
- @scanner.pos = begin_pos
1130
- raise ParseError.new("Circular reference.")
1131
- end
1132
- rescue ParseError => e
1133
- if @expanded_environment.size>1
1134
- raise
1135
- else
1136
- @scanner.pos = begin_pos
1137
- raise ParseError.new(%[Error in macro(#{e.message} "#{e.rest.strip}").])
1138
- end
1139
- end
1140
- ensure
1141
- @expanded_environment.pop
1142
- end
1143
- end
1144
-
1145
- raise ParseError.new("Undefined environment.") unless @environments.has_key?(en)
1146
- e = @environments[en]
1147
- e = en unless e # default method name
1148
- __send__("env_#{e.to_s}")
1149
- end
1150
-
1151
- def grp_left_etc
1152
- right =
1153
- case @scanner[1]
1154
- when "left"
1155
- "right"
1156
- when "bigg"
1157
- "bigg"
1158
- end
1159
-
1160
- f = Fenced.new
1161
- p = @scanner.pos
1162
- o = @scanner.scan_any
1163
- raise ParseError.new('Need brace here.') unless o && (o=~RE::BRACES || @delimiters.include?(o[RE::COMMANDS, 1]))
1164
-
1165
- f.open = (o=~RE::BRACES ? o : parse_symbol_command(o[RE::COMMANDS, 1], true))
1166
- f << push_container(Row.new) do |r|
1167
- until @scanner.peek_command==right
1168
- if @scanner.eos?
1169
- @scanner.pos = p
1170
- raise ParseError.new('Brace not closed.')
1171
- end
1172
- r << parse_to_element(true)
1173
- end
1174
- end
1175
- @scanner.scan_command # skip right
1176
- c = @scanner.scan_any
1177
- raise ParseError.new('Need brace here.') unless c=~RE::BRACES || @delimiters.include?(c[RE::COMMANDS, 1])
1178
- f.close = (c=~RE::BRACES ? c : parse_symbol_command(c[RE::COMMANDS, 1], true))
1179
- f
1180
- end
1181
- end
1182
-
1183
- module BuiltinEnvironments
1184
- def initialize
1185
- add_environment("array", "matrix")
1186
-
1187
- super
1188
- end
1189
-
1190
- def env_array
1191
- layout = @scanner.scan_block ? @scanner.matched : @scanner.scan(/./)
1192
- l = Scanner.new(layout=~RE::BLOCK ? layout[RE::BLOCK, 1] : layout)
1193
- t = Table.new
1194
- aligns = Array.new
1195
- vlines = Array.new
1196
- vlined = l.check(/\|/)
1197
- columned = false
1198
- until l.eos?
1199
- c = l.scan_any
1200
- raise ParseError.new("Syntax error.", layout[/\A.*(#{Regexp.escape(c+l.rest)}.*\z)/m, 1]) unless c=~/[clr\|@]/
1201
-
1202
- if c=='|'
1203
- aligns << Align::CENTER if vlined
1204
- vlines << Line::SOLID
1205
- vlined = true
1206
- columned = false
1207
- else
1208
- vlines << Line::NONE if columned
1209
- vlined = false
1210
- columned = true
1211
- case c
1212
- when 'l'
1213
- aligns << Align::LEFT
1214
- when 'c'
1215
- aligns << Align::CENTER
1216
- when 'r'
1217
- aligns << Align::RIGHT
1218
- when '@'
1219
- aligns << Align::CENTER
1220
- l.scan_any
1221
- end
1222
- end
1223
- end
1224
- t.aligns = aligns
1225
- t.vlines = vlines
1226
-
1227
- layout = layout[RE::BLOCK, 1] if layout=~RE::BLOCK
1228
- raise ParseError.new('Need parameter here.') if layout==""
1229
-
1230
- hlines = Array.new
1231
- row_parsed = false
1232
- hlined = false
1233
- until @scanner.peek_command=="end"
1234
- raise ParseError.new('Matching \end not exist.') if @scanner.eos?
1235
- if @scanner.peek_command=="hline"
1236
- @scanner.scan_command
1237
- t << Tr.new unless row_parsed
1238
- hlines << Line::SOLID
1239
- row_parsed = false
1240
- hlined = true
1241
- else
1242
- hlines << Line::NONE if row_parsed
1243
- t << env_array_row(l.string)
1244
- @scanner.scan(RE::WBSLASH)
1245
- row_parsed = true
1246
- hlined = false
1247
- end
1248
- end
1249
- t.hlines = hlines
1250
-
1251
- if hlined
1252
- tr = Tr.new
1253
- (0..vlines.size).each {|i| tr << Td.new}
1254
- t << tr
1255
- end
1256
-
1257
- @scanner.scan_command
1258
- raise ParseError.new("Environment mismatched.") unless @scanner.check_block && @scanner[1]=="array"
1259
- @scanner.scan_block
1260
- t
1261
- end
1262
-
1263
- def env_array_row(layout)
1264
- l = Scanner.new(layout)
1265
- r = Tr.new
1266
- first_column = true
1267
- vlined = l.check(/\|/)
1268
- until l.eos?
1269
- c = l.scan(/./)
1270
- if c=='|'
1271
- r << Td.new if vlined
1272
- vlined = true
1273
- next
1274
- else
1275
- vlined = false
1276
- case c
1277
- when 'r', 'l', 'c'
1278
- when '@'
1279
- r << parse_into(l.scan_any, Td.new)
1280
- next
1281
- end
1282
- if first_column
1283
- first_column = false
1284
- else
1285
- raise ParseError.new("Need more column.", @scanner.matched.to_s) unless @scanner.scan(/&/)
1286
- end
1287
- r << push_container(Td.new) do |td|
1288
- td << parse_to_element(true) until @scanner.peek_command=="end" || @scanner.check(/(&|\\\\)/) || @scanner.eos?
1289
- end
1290
- end
1291
- end
1292
- r << Td.new if vlined
1293
- raise ParseError.new("Too many column.") if @scanner.check(/&/)
1294
- r
1295
- end
1296
-
1297
- def env_matrix
1298
- t = Table.new
1299
- hlines = Array.new
1300
- hlined = false
1301
- row_parsed = false
1302
- until @scanner.peek_command=="end"
1303
- raise ParseError.new('Matching \end not exist.') if @scanner.eos?
1304
- if @scanner.peek_command=="hline"
1305
- @scanner.scan_command
1306
- t << Tr.new unless row_parsed
1307
- hlines << Line::SOLID
1308
- row_parsed = false
1309
- hlined = true
1310
- else
1311
- hlines << Line::NONE if row_parsed
1312
- t << (r = Tr.new)
1313
- r << (td=Td.new)
1314
- until @scanner.check(RE::WBSLASH) || @scanner.peek_command=="end" || @scanner.eos?
1315
- push_container(td) do |e|
1316
- e << parse_to_element(true) until @scanner.peek_command=="end" || @scanner.check(/(&|\\\\)/) || @scanner.eos?
1317
- end
1318
- r << (td=Td.new) if @scanner.scan(/&/)
1319
- end
1320
- @scanner.scan(RE::WBSLASH)
1321
- row_parsed = true
1322
- hlined = false
1323
- end
1324
- end
1325
- t.hlines = hlines
1326
-
1327
- t << Tr.new if hlined
1328
-
1329
- raise ParseError.new("Need \\end{array}.") unless @scanner.peek_command=="end"
1330
- @scanner.scan_command
1331
- raise ParseError.new("Environment mismatched.") unless @scanner.check_block && @scanner[1]=="matrix"
1332
- @scanner.scan_block
1333
- t
1334
- end
1335
-
1336
- def env_matrix_row
1337
- r = Tr.new
1338
- until @scanner.check(RE::WBSLASH) || @scanner.peek_command=="end"
1339
- r << push_container(Td.new) do |td|
1340
- td << parse_to_element(true) until @scanner.peek_command=="end" || @scanner.check(/(&|\\\\)/) || @scanner.eos?
1341
- end
1342
- end
1343
-
1344
- end
1345
- end
1346
- end
1347
27
  end
1348
28
 
1349
- # Automatically generated constants
1350
- module MathML::LaTeX::BuiltinCommands
1351
- SymbolCommands={
1352
- "{"=>[:s,:o,""],
1353
- "}"=>[:s,:o,""],
1354
- "#"=>[:s,:o,""],
1355
- "$"=>[:s,:o,""],
1356
- "&"=>[:s,:o,:amp],
1357
- "_"=>[:s,:o,""],
1358
- "%"=>[:s,:o,""],
1359
- ","=>nil,
1360
- "varepsilon"=>[:s,:I],
1361
- "mathdollar"=>[:s,:o,"$"],
1362
- "lbrace"=>[:s],
1363
- "rbrace"=>[:s],
1364
- "P"=>[:s,:o,:para],
1365
- "mathparagraph"=>[:s,:o,:para],
1366
- "S"=>[:s,:o,:sect],
1367
- "mathsection"=>[:s,:o,:sect],
1368
- "dag"=>[:s,:o,:dagger],
1369
- "dagger"=>[:s],
1370
- "ddag"=>[:s,:o,:ddagger],
1371
- "ddagger"=>[:s],
1372
- "copyright"=>[:s,:o,:copy],
1373
- "pounds"=>[:s,:o,:pound],
1374
- "mathsterling"=>[:s,:o,:pound],
1375
- "dots"=>[:s,:o,:mldr],
1376
- "mathellipsis"=>[:s,:o,:mldr],
1377
- "ldots"=>[:s,:o,:mldr],
1378
- "ensuremath"=>nil,
1379
- "|"=>[:s,:o,:DoubleVerticalBar],
1380
- "mho"=>[:s],
1381
- "Join"=>[:s,:o,:bowtie],
1382
- "Box"=>[:s,:o,:square],
1383
- "Diamond"=>[:s],
1384
- "leadsto"=>[:s,:o,:zigrarr],
1385
- "sqsubset"=>[:s],
1386
- "sqsupset"=>[:s],
1387
- "lhd"=>[:s,:o,:vltri],
1388
- "unlhd"=>[:s,:o,:ltrie],
1389
- "rhd"=>[:s,:o,:vrtri],
1390
- "unrhd"=>[:s,:o,:rtrie],
1391
- "log"=>[:s,:i,""],
1392
- "lg"=>[:s,:i,""],
1393
- "ln"=>[:s,:i,""],
1394
- "lim"=>[:u,:i,""],
1395
- "limsup"=>[:u,:i,"lim sup"],
1396
- "liminf"=>[:u,:i,"lim inf"],
1397
- "sin"=>[:s,:i,""],
1398
- "arcsin"=>[:s,:i,""],
1399
- "sinh"=>[:s,:i,""],
1400
- "cos"=>[:s,:i,""],
1401
- "arccos"=>[:s,:i,""],
1402
- "cosh"=>[:s,:i,""],
1403
- "tan"=>[:s,:i,""],
1404
- "arctan"=>[:s,:i,""],
1405
- "tanh"=>[:s,:i,""],
1406
- "cot"=>[:s,:i,""],
1407
- "coth"=>[:s,:i,""],
1408
- "sec"=>[:s,:i,""],
1409
- "csc"=>[:s,:i,""],
1410
- "max"=>[:u,:i,""],
1411
- "min"=>[:u,:i,""],
1412
- "sup"=>[:u,:i,""],
1413
- "inf"=>[:u,:i,""],
1414
- "arg"=>[:s,:i,""],
1415
- "ker"=>[:s,:i,""],
1416
- "dim"=>[:s,:i,""],
1417
- "hom"=>[:s,:i,""],
1418
- "det"=>[:u,:i,""],
1419
- "exp"=>[:s,:i,""],
1420
- "Pr"=>[:u,:i,""],
1421
- "gcd"=>[:u,:i,""],
1422
- "deg"=>[:s,:i,""],
1423
- "prime"=>[:s],
1424
- "alpha"=>[:s,:I],
1425
- "beta"=>[:s,:I],
1426
- "gamma"=>[:s,:I],
1427
- "delta"=>[:s,:I],
1428
- "epsilon"=>[:s,:I],
1429
- "zeta"=>[:s,:I],
1430
- "eta"=>[:s,:I],
1431
- "theta"=>[:s,:I],
1432
- "iota"=>[:s,:I],
1433
- "kappa"=>[:s,:I],
1434
- "lambda"=>[:s,:I],
1435
- "mu"=>[:s,:I],
1436
- "nu"=>[:s,:I],
1437
- "xi"=>[:s,:I],
1438
- "pi"=>[:s,:I],
1439
- "rho"=>[:s,:I],
1440
- "sigma"=>[:s,:I],
1441
- "tau"=>[:s,:I],
1442
- "upsilon"=>[:s,:I],
1443
- "phi"=>[:s,:I],
1444
- "chi"=>[:s,:I],
1445
- "psi"=>[:s,:I],
1446
- "omega"=>[:s,:I],
1447
- "vartheta"=>[:s,:I],
1448
- "varpi"=>[:s,:I],
1449
- "varrho"=>[:s,:I],
1450
- "varsigma"=>[:s,:I],
1451
- "varphi"=>[:s,:I],
1452
- "Gamma"=>[:s,:i],
1453
- "Delta"=>[:s,:i],
1454
- "Theta"=>[:s,:i],
1455
- "Lambda"=>[:s,:i],
1456
- "Xi"=>[:s,:i],
1457
- "Pi"=>[:s,:i],
1458
- "Sigma"=>[:s,:i],
1459
- "Upsilon"=>[:s,:i,:Upsi],
1460
- "Phi"=>[:s,:i],
1461
- "Psi"=>[:s,:i],
1462
- "Omega"=>[:s,:i],
1463
- "aleph"=>[:s,:i],
1464
- "hbar"=>[:s,:i,:hslash],
1465
- "imath"=>[:s,:i],
1466
- "jmath"=>[:s,:i],
1467
- "ell"=>[:s],
1468
- "wp"=>[:s],
1469
- "Re"=>[:s,:i],
1470
- "Im"=>[:s,:i],
1471
- "partial"=>[:s,:o,:part],
1472
- "infty"=>[:s,:n,:infin],
1473
- "emptyset"=>[:s,:i,:empty],
1474
- "nabla"=>[:s,:i],
1475
- "surd"=>[:s,:o,:Sqrt],
1476
- "top"=>[:s],
1477
- "bot"=>[:s],
1478
- "angle"=>[:s],
1479
- "not"=>[:s],
1480
- "triangle"=>[:s],
1481
- "forall"=>[:s],
1482
- "exists"=>[:s,:o,:exist],
1483
- "neg"=>[:s,:o,:not],
1484
- "lnot"=>[:s,:o,:not],
1485
- "flat"=>[:s],
1486
- "natural"=>[:s],
1487
- "sharp"=>[:s],
1488
- "clubsuit"=>[:s],
1489
- "diamondsuit"=>[:s],
1490
- "heartsuit"=>[:s],
1491
- "spadesuit"=>[:s],
1492
- "coprod"=>[:u],
1493
- "bigvee"=>[:u],
1494
- "bigwedge"=>[:u],
1495
- "biguplus"=>[:u],
1496
- "bigcap"=>[:u],
1497
- "bigcup"=>[:u],
1498
- "intop"=>[:u,:o,:int],
1499
- "int"=>[:s,:o],
1500
- "prod"=>[:u],
1501
- "sum"=>[:u],
1502
- "bigotimes"=>[:u],
1503
- "bigoplus"=>[:u],
1504
- "bigodot"=>[:u],
1505
- "ointop"=>[:u,:o,:oint],
1506
- "oint"=>[:s],
1507
- "bigsqcup"=>[:u],
1508
- "smallint"=>[:u,:o,:int],
1509
- "triangleleft"=>[:s],
1510
- "triangleright"=>[:s],
1511
- "bigtriangleup"=>[:s],
1512
- "bigtriangledown"=>[:s],
1513
- "wedge"=>[:s],
1514
- "land"=>[:s,:o,:wedge],
1515
- "vee"=>[:s],
1516
- "lor"=>[:s,:o,:vee],
1517
- "cap"=>[:s],
1518
- "cup"=>[:s],
1519
- "sqcap"=>[:s],
1520
- "sqcup"=>[:s],
1521
- "uplus"=>[:s],
1522
- "amalg"=>[:s],
1523
- "diamond"=>[:s],
1524
- "bullet"=>[:s],
1525
- "wr"=>[:s],
1526
- "div"=>[:s],
1527
- "odot"=>[:s],
1528
- "oslash"=>[:s],
1529
- "otimes"=>[:s],
1530
- "ominus"=>[:s],
1531
- "oplus"=>[:s],
1532
- "mp"=>[:s],
1533
- "pm"=>[:s],
1534
- "circ"=>[:s,:o,:cir],
1535
- "bigcirc"=>[:s],
1536
- "setminus"=>[:s],
1537
- "cdot"=>[:s,:o,:sdot],
1538
- "ast"=>[:s],
1539
- "times"=>[:s],
1540
- "star"=>[:s],
1541
- "propto"=>[:s],
1542
- "sqsubseteq"=>[:s],
1543
- "sqsupseteq"=>[:s],
1544
- "parallel"=>[:s],
1545
- "mid"=>[:s],
1546
- "dashv"=>[:s],
1547
- "vdash"=>[:s],
1548
- "nearrow"=>[:s],
1549
- "searrow"=>[:s],
1550
- "nwarrow"=>[:s],
1551
- "swarrow"=>[:s],
1552
- "Leftrightarrow"=>[:s],
1553
- "Leftarrow"=>[:s],
1554
- "Rightarrow"=>[:s],
1555
- "neq"=>[:s,:o,:ne],
1556
- "ne"=>[:s],
1557
- "leq"=>[:s],
1558
- "le"=>[:s],
1559
- "geq"=>[:s],
1560
- "ge"=>[:s],
1561
- "succ"=>[:s],
1562
- "prec"=>[:s],
1563
- "approx"=>[:s],
1564
- "succeq"=>[:s,:o,:sccue],
1565
- "preceq"=>[:s,:o,:prcue],
1566
- "supset"=>[:s],
1567
- "subset"=>[:s],
1568
- "supseteq"=>[:s],
1569
- "subseteq"=>[:s],
1570
- "in"=>[:s],
1571
- "ni"=>[:s],
1572
- "owns"=>[:s,:o,:ni],
1573
- "gg"=>[:s],
1574
- "ll"=>[:s],
1575
- "leftrightarrow"=>[:s],
1576
- "leftarrow"=>[:s],
1577
- "gets"=>[:s,:o,:leftarrow],
1578
- "rightarrow"=>[:s],
1579
- "to"=>[:s,:o,:rightarrow],
1580
- "mapstochar"=>[:s,:o,:vdash],
1581
- "mapsto"=>[:s],
1582
- "sim"=>[:s],
1583
- "simeq"=>[:s],
1584
- "perp"=>[:s],
1585
- "equiv"=>[:s],
1586
- "asymp"=>[:s],
1587
- "smile"=>[:s],
1588
- "frown"=>[:s],
1589
- "leftharpoonup"=>[:s],
1590
- "leftharpoondown"=>[:s],
1591
- "rightharpoonup"=>[:s],
1592
- "rightharpoondown"=>[:s],
1593
- "cong"=>[:s],
1594
- "notin"=>[:s],
1595
- "rightleftharpoons"=>[:s],
1596
- "doteq"=>[:s],
1597
- "joinrel"=>nil,
1598
- "relbar"=>[:s,:o,"-"],
1599
- "Relbar"=>[:s,:o,"="],
1600
- "lhook"=>[:s,:o,:sub],
1601
- "hookrightarrow"=>[:s],
1602
- "rhook"=>[:s,:o,:sup],
1603
- "hookleftarrow"=>[:s],
1604
- "bowtie"=>[:s],
1605
- "models"=>[:s],
1606
- "Longrightarrow"=>[:s],
1607
- "longrightarrow"=>[:s],
1608
- "longleftarrow"=>[:s],
1609
- "Longleftarrow"=>[:s],
1610
- "longmapsto"=>[:s,:o,:mapsto],
1611
- "longleftrightarrow"=>[:s],
1612
- "Longleftrightarrow"=>[:s],
1613
- "iff"=>[:s],
1614
- "ldotp"=>[:s,:o,"."],
1615
- "cdotp"=>[:s,:o,:cdot],
1616
- "colon"=>[:s],
1617
- "cdots"=>[:s,:o,:ctdot],
1618
- "vdots"=>[:s,:o,:vellip],
1619
- "ddots"=>[:s,:o,:dtdot],
1620
- "braceld"=>[:s,:o,0x25dc],
1621
- "bracerd"=>[:s,:o,0x25dd],
1622
- "bracelu"=>[:s,:o,0x25df],
1623
- "braceru"=>[:s,:o,0x25de],
1624
- "lmoustache"=>[:s],
1625
- "rmoustache"=>[:s],
1626
- "arrowvert"=>[:s,:o,:vert],
1627
- "Arrowvert"=>[:s,:o,:DoubleVerticalBar],
1628
- "Vert"=>[:s,:o,:DoubleVerticalBar],
1629
- "vert"=>[:s],
1630
- "uparrow"=>[:s],
1631
- "downarrow"=>[:s],
1632
- "updownarrow"=>[:s],
1633
- "Uparrow"=>[:s],
1634
- "Downarrow"=>[:s],
1635
- "Updownarrow"=>[:s],
1636
- "backslash"=>[:s,:o,"\\"],
1637
- "rangle"=>[:s],
1638
- "langle"=>[:s],
1639
- "rceil"=>[:s],
1640
- "lceil"=>[:s],
1641
- "rfloor"=>[:s],
1642
- "lfloor"=>[:s],
1643
- "lgroup"=>[:s,:o,0x2570],
1644
- "rgroup"=>[:s,:o,0x256f],
1645
- "bracevert"=>[:s,:o,:vert],
1646
- "mathunderscore"=>[:s,:o,"_"],
1647
- "square"=>[:s],
1648
- "rightsquigarrow"=>[:s],
1649
- "lozenge"=>[:s],
1650
- "vartriangleright"=>[:s],
1651
- "vartriangleleft"=>[:s],
1652
- "trianglerighteq"=>[:s],
1653
- "trianglelefteq"=>[:s],
1654
- "boxdot"=>[:s,:o,:dotsquare],
1655
- "boxplus"=>[:s],
1656
- "boxtimes"=>[:s],
1657
- "blacksquare"=>[:s],
1658
- "centerdot"=>[:s],
1659
- "blacklozenge"=>[:s],
1660
- "circlearrowright"=>[:s],
1661
- "circlearrowleft"=>[:s],
1662
- "leftrightharpoons"=>[:s],
1663
- "boxminus"=>[:s],
1664
- "Vdash"=>[:s],
1665
- "Vvdash"=>[:s],
1666
- "vDash"=>[:s],
1667
- "twoheadrightarrow"=>[:s],
1668
- "twoheadleftarrow"=>[:s],
1669
- "leftleftarrows"=>[:s],
1670
- "rightrightarrows"=>[:s],
1671
- "upuparrows"=>[:s],
1672
- "downdownarrows"=>[:s],
1673
- "upharpoonright"=>[:s],
1674
- "restriction"=>[:s,:o,:upharpoonright],
1675
- "downharpoonright"=>[:s],
1676
- "upharpoonleft"=>[:s],
1677
- "downharpoonleft"=>[:s],
1678
- "rightarrowtail"=>[:s],
1679
- "leftarrowtail"=>[:s],
1680
- "leftrightarrows"=>[:s],
1681
- "rightleftarrows"=>[:s],
1682
- "Lsh"=>[:s],
1683
- "Rsh"=>[:s],
1684
- "leftrightsquigarrow"=>[:s],
1685
- "looparrowleft"=>[:s],
1686
- "looparrowright"=>[:s],
1687
- "circeq"=>[:s],
1688
- "succsim"=>[:s],
1689
- "gtrsim"=>[:s],
1690
- "gtrapprox"=>[:s],
1691
- "multimap"=>[:s],
1692
- "therefore"=>[:s],
1693
- "because"=>[:s],
1694
- "doteqdot"=>[:s],
1695
- "Doteq"=>[:s,:o,:doteqdot],
1696
- "triangleq"=>[:s],
1697
- "precsim"=>[:s],
1698
- "lesssim"=>[:s],
1699
- "lessapprox"=>[:s],
1700
- "eqslantless"=>[:s],
1701
- "eqslantgtr"=>[:s],
1702
- "curlyeqprec"=>[:s],
1703
- "curlyeqsucc"=>[:s],
1704
- "preccurlyeq"=>[:s],
1705
- "leqq"=>[:s],
1706
- "leqslant"=>[:s,:o,:leq],
1707
- "lessgtr"=>[:s],
1708
- "backprime"=>[:s],
1709
- "risingdotseq"=>[:s],
1710
- "fallingdotseq"=>[:s],
1711
- "succcurlyeq"=>[:s],
1712
- "geqq"=>[:s],
1713
- "geqslant"=>[:s,:o,:geq],
1714
- "gtrless"=>[:s],
1715
- "bigstar"=>[:s],
1716
- "between"=>[:s],
1717
- "blacktriangledown"=>[:s],
1718
- "blacktriangleright"=>[:s],
1719
- "blacktriangleleft"=>[:s],
1720
- "vartriangle"=>[:s,:o,:triangle],
1721
- "blacktriangle"=>[:s],
1722
- "triangledown"=>[:s],
1723
- "eqcirc"=>[:s],
1724
- "lesseqgtr"=>[:s],
1725
- "gtreqless"=>[:s],
1726
- "lesseqqgtr"=>[:s],
1727
- "gtreqqless"=>[:s],
1728
- "Rrightarrow"=>[:s],
1729
- "Lleftarrow"=>[:s],
1730
- "veebar"=>[:s],
1731
- "barwedge"=>[:s],
1732
- "doublebarwedge"=>[:s],
1733
- "measuredangle"=>[:s],
1734
- "sphericalangle"=>[:s,:o,:angsph],
1735
- "varpropto"=>[:s],
1736
- "smallsmile"=>[:s,:o,:smile],
1737
- "smallfrown"=>[:s,:o,:frown],
1738
- "Subset"=>[:s],
1739
- "Supset"=>[:s],
1740
- "Cup"=>[:s],
1741
- "doublecup"=>[:s,:o,:Cup],
1742
- "Cap"=>[:s],
1743
- "doublecap"=>[:s,:o,:Cap],
1744
- "curlywedge"=>[:s],
1745
- "curlyvee"=>[:s],
1746
- "leftthreetimes"=>[:s],
1747
- "rightthreetimes"=>[:s],
1748
- "subseteqq"=>[:s],
1749
- "supseteqq"=>[:s],
1750
- "bumpeq"=>[:s],
1751
- "Bumpeq"=>[:s],
1752
- "lll"=>[:s,:o,:Ll],
1753
- "llless"=>[:s,:o,:Ll],
1754
- "ggg"=>[:s],
1755
- "gggtr"=>[:s,:o,:ggg],
1756
- "circledS"=>[:s],
1757
- "pitchfork"=>[:s],
1758
- "dotplus"=>[:s],
1759
- "backsim"=>[:s],
1760
- "backsimeq"=>[:s],
1761
- "complement"=>[:s],
1762
- "intercal"=>[:s],
1763
- "circledcirc"=>[:s],
1764
- "circledast"=>[:s],
1765
- "circleddash"=>[:s],
1766
- "lvertneqq"=>[:s,:o,:lneqq],
1767
- "gvertneqq"=>[:s,:o,:gneqq],
1768
- "nleq"=>[:s,:o,0x2270],
1769
- "ngeq"=>[:s,:o,0x2271],
1770
- "nless"=>[:s],
1771
- "ngtr"=>[:s],
1772
- "nprec"=>[:s],
1773
- "nsucc"=>[:s],
1774
- "lneqq"=>[:s],
1775
- "gneqq"=>[:s],
1776
- "nleqslant"=>[:s],
1777
- "ngeqslant"=>[:s],
1778
- "lneq"=>[:s],
1779
- "gneq"=>[:s],
1780
- "npreceq"=>[:s,:o,:nprcue],
1781
- "nsucceq"=>[:s,:o,:nsccue],
1782
- "precnsim"=>[:s],
1783
- "succnsim"=>[:s],
1784
- "lnsim"=>[:s],
1785
- "gnsim"=>[:s],
1786
- "nleqq"=>[:s],
1787
- "ngeqq"=>[:s],
1788
- "precneqq"=>[:s,:o,"<mfrac linethickness='0' mathsize='1%'><mo>&prec;</mo><mo>&ne;</mo></mfrac>"],
1789
- "succneqq"=>[:s,:o,"<mfrac linethickness='0' mathsize='1%'><mo>&succ;</mo><mo>&ne;</mo></mfrac>"],
1790
- "precnapprox"=>[:s],
1791
- "succnapprox"=>[:s],
1792
- "lnapprox"=>[:s,:o,"<mfrac linethickness='0' mathsize='1%'><mo>&lt;</mo><mo>&nap;</mo></mfrac>"],
1793
- "gnapprox"=>[:s,:o,"<mfrac linethickness='0' mathsize='1%'><mo>&gt;</mo><mo>&nap;</mo></mfrac>"],
1794
- "nsim"=>[:s],
1795
- "ncong"=>[:s],
1796
- "diagup"=>[:s,:o,0x2571],
1797
- "diagdown"=>[:s,:o,0x2572],
1798
- "varsubsetneq"=>[:s,:o,:subsetneq],
1799
- "varsupsetneq"=>[:s,:o,:supsetneq],
1800
- "nsubseteqq"=>[:s],
1801
- "nsupseteqq"=>[:s],
1802
- "subsetneqq"=>[:s],
1803
- "supsetneqq"=>[:s],
1804
- "varsubsetneqq"=>[:s,:o,:subsetneqq],
1805
- "varsupsetneqq"=>[:s,:o,:supsetneqq],
1806
- "subsetneq"=>[:s],
1807
- "supsetneq"=>[:s],
1808
- "nsubseteq"=>[:s],
1809
- "nsupseteq"=>[:s],
1810
- "nparallel"=>[:s],
1811
- "nmid"=>[:s],
1812
- "nshortmid"=>[:s,:o,:nmid],
1813
- "nshortparallel"=>[:s,:o,:nparallel],
1814
- "nvdash"=>[:s],
1815
- "nVdash"=>[:s],
1816
- "nvDash"=>[:s],
1817
- "nVDash"=>[:s],
1818
- "ntrianglerighteq"=>[:s],
1819
- "ntrianglelefteq"=>[:s],
1820
- "ntriangleleft"=>[:s],
1821
- "ntriangleright"=>[:s],
1822
- "nleftarrow"=>[:s],
1823
- "nrightarrow"=>[:s],
1824
- "nLeftarrow"=>[:s],
1825
- "nRightarrow"=>[:s],
1826
- "nLeftrightarrow"=>[:s],
1827
- "nleftrightarrow"=>[:s],
1828
- "divideontimes"=>[:s],
1829
- "varnothing"=>[:s],
1830
- "nexists"=>[:s],
1831
- "Finv"=>[:s,:o,0x2132],
1832
- "Game"=>[:s,:o,"G"],
1833
- "eth"=>[:s],
1834
- "eqsim"=>[:s],
1835
- "beth"=>[:s],
1836
- "gimel"=>[:s],
1837
- "daleth"=>[:s],
1838
- "lessdot"=>[:s],
1839
- "gtrdot"=>[:s],
1840
- "ltimes"=>[:s],
1841
- "rtimes"=>[:s],
1842
- "shortmid"=>[:s,:o,:mid],
1843
- "shortparallel"=>[:s],
1844
- "smallsetminus"=>[:s,:o,:setminus],
1845
- "thicksim"=>[:s,:o,:sim],
1846
- "thickapprox"=>[:s,:o,:approx],
1847
- "approxeq"=>[:s],
1848
- "succapprox"=>[:s],
1849
- "precapprox"=>[:s],
1850
- "curvearrowleft"=>[:s],
1851
- "curvearrowright"=>[:s],
1852
- "digamma"=>[:s],
1853
- "varkappa"=>[:s],
1854
- "Bbbk"=>[:s,:i,:kopf],
1855
- "hslash"=>[:s],
1856
- "backepsilon"=>[:s],
1857
- "ulcorner"=>[:s,:o,:boxdr],
1858
- "urcorner"=>[:s,:o,:boxdl],
1859
- "llcorner"=>[:s,:o,:boxur],
1860
- "lrcorner"=>[:s,:o,:boxul],
1861
- }
1862
- Delimiters=[
1863
- "lmoustache",
1864
- "rmoustache",
1865
- "arrowvert",
1866
- "Arrowvert",
1867
- "Vert",
1868
- "vert",
1869
- "uparrow",
1870
- "downarrow",
1871
- "updownarrow",
1872
- "Uparrow",
1873
- "Downarrow",
1874
- "Updownarrow",
1875
- "backslash",
1876
- "rangle",
1877
- "langle",
1878
- "rbrace",
1879
- "lbrace",
1880
- "rceil",
1881
- "lceil",
1882
- "rfloor",
1883
- "lfloor",
1884
- "lgroup",
1885
- "rgroup",
1886
- "bracevert",
1887
- "ulcorner",
1888
- "urcorner",
1889
- "llcorner",
1890
- "lrcorner",
1891
- "{",
1892
- "|",
1893
- "}",
1894
- ]
1895
- end
1896
-
1897
- end
29
+ require "math_ml/element"
30
+ require "math_ml/symbol/entity_reference"
31
+ require "math_ml/latex"