Object
# File lib/math_ml/latex.rb, line 365
365: def initialize(opt={})
366: @unsecure_entity = false
367: @entities = Hash.new
368: @commands = Hash.new
369: @symbols = Hash.new
370: @delimiters = Array.new
371: @group_begins = Hash.new
372: @group_ends = Hash.new
373: @macro = Macro.new
374: @macro.parse(BUILTIN_MACRO)
375: @expanded_command = Array.new
376: @expanded_environment = Array.new
377: @symbol_table = opt[:symbol] || MathML::Symbol::Default
378: @symbol_table = MathML::Symbol::MAP[@symbol_table] if @symbol_table.is_a?(::Symbol)
379:
380: super()
381: end
# File lib/math_ml/latex.rb, line 414
414: def add_commands(*a)
415: if a.size==1 && Hash===a[0]
416: @commands.merge!(a[0])
417: else
418: a.each{|i| @commands[i] = false}
419: end
420: end
# File lib/math_ml/latex.rb, line 430
430: def add_delimiter(list)
431: @delimiters.concat(list)
432: end
# File lib/math_ml/latex.rb, line 383
383: def add_entity(list)
384: list.each do |i|
385: @entities[i] = true
386: end
387: end
# File lib/math_ml/latex.rb, line 434
434: def add_group(begin_name, end_name, method=nil)
435: @group_begins[begin_name] = method
436: @group_ends[end_name] = begin_name
437: end
# File lib/math_ml/latex.rb, line 422
422: def add_multi_command(m, *a)
423: a.each{|i| @commands[i] = m}
424: end
# File lib/math_ml/latex.rb, line 410
410: def add_plugin(plugin)
411: self.extend(plugin)
412: end
# File lib/math_ml/latex.rb, line 426
426: def add_sym_cmd(hash)
427: @symbols.merge!(hash)
428: end
# File lib/math_ml/latex.rb, line 389
389: def parse(src, displaystyle=false)
390: @ds = displaystyle
391: begin
392: parse_into(src, Math.new(@ds), Font::NORMAL)
393: rescue ParseError => e
394: e.done = src[0...(src.size - e.rest.size)]
395: raise
396: end
397: end
# File lib/math_ml/latex.rb, line 399
399: def push_container(container, scanner=@scanner, font=@font)
400: data = [@container, @scanner, @font]
401: @container, @scanner, @font = [container, scanner, font]
402: begin
403: yield container
404: container
405: ensure
406: @container, @scanner, @font = data
407: end
408: end
# File lib/math_ml/latex.rb, line 588
588: def entitize(str)
589: MathML.pcstring(str.sub(/^(.*)$/){"&#{$1};"}, true)
590: end
# File lib/math_ml/latex.rb, line 466
466: def parse_any(message = "Syntax error.")
467: raise ParseError.new(message) unless @scanner.scan_any
468: s = @scanner
469: @scanner = Scanner.new(@scanner.matched)
470: begin
471: parse_to_element
472: ensure
473: @scanner = s
474: end
475: end
# File lib/math_ml/latex.rb, line 536
536: def parse_block
537: os = @scanner
538: @scanner = Scanner.new(@scanner[1])
539: begin
540: push_container(Row.new) do |r|
541: r << parse_to_element(true) until @scanner.eos?
542: end
543: rescue ParseError => e
544: e.rest << '}'
545: raise
546: ensure
547: @scanner = os
548: end
549: end
# File lib/math_ml/latex.rb, line 511
511: def parse_char
512: c = @scanner.matched
513: i = Identifier.new
514: case @font
515: when Font::ROMAN
516: i.extend(Variant).variant = Variant::NORMAL
517: when Font::BOLD
518: i.extend(Variant).variant = Variant::BOLD
519: when Font::BOLD_ITALIC
520: i.extend(Variant).variant = Variant::BOLD_ITALIC
521: when Font::BLACKBOLD
522: c = symbol_table.convert("#{c}opf")
523: when Font::SCRIPT
524: c = symbol_table.convert("#{c}scr")
525: when Font::FRAKTUR
526: c = symbol_table.convert("#{c}fr")
527: end
528: i << c
529: end
# File lib/math_ml/latex.rb, line 636
636: def parse_command
637: com = @scanner[1]
638: matched = @scanner.matched
639: pos = @scanner.pos-matched.size
640: macro = @macro.commands(com)
641: if macro
642: begin
643: flg = @expanded_command.include?(com)
644: @expanded_command.push(com)
645: raise CircularReferenceCommand if flg
646: option = (macro.option && @scanner.scan_option) ? @scanner[1] : nil
647: params = Array.new
648: (1..macro.num).each do
649: params << (@scanner.scan_block ? @scanner[1] : @scanner.scan_any)
650: raise ParseError.new("Need more parameter.") unless params.last
651: end
652: r = parse_into(@macro.expand_command(com, params, option), Array.new)
653: return r
654: rescue CircularReferenceCommand
655: if @expanded_command.size>1
656: raise
657: else
658: @scanner.pos = pos
659: raise ParseError.new("Circular reference.")
660: end
661: rescue ParseError => e
662: if @expanded_command.size>1
663: raise
664: else
665: @scanner.pos = pos
666: raise ParseError.new(%[Error in macro(#{e.message} "#{e.rest.strip}").])
667: end
668: ensure
669: @expanded_command.pop
670: end
671: elsif @commands.key?(com)
672: m = @commands[com]
673: m = com unless m
674: return __send__("cmd_#{m.to_s}")
675: end
676: parse_symbol_command(com)
677: end
# File lib/math_ml/latex.rb, line 689
689: def parse_group
690: font = @font
691: begin
692: g = @group_begins[@scanner[1]]
693: g = @scanner[1] unless g
694: __send__("grp_#{g.to_s}")
695: ensure
696: @font = font
697: end
698: end
# File lib/math_ml/latex.rb, line 440
440: def parse_into(src, parent, font=nil)
441: orig = [@scanner, @container, @font, @ds]
442: @scanner = Scanner.new(src)
443: @container = parent
444: @font = font if font
445: begin
446: until @scanner.eos?
447: @container << parse_to_element(true)
448: end
449: @container
450: rescue BlockNotClosed => e
451: raise ParseError.new("Block not closed.", @scanner.rest)
452: rescue NotEnvironment => e
453: raise ParseError.new("Not environment.", @scanner.rest)
454: rescue EnvironmentNotEnd => e
455: raise ParseError.new("Environment not end.", @scanner.rest)
456: rescue OptionNotClosed => e
457: raise ParseError.new("Option not closed.", @scanner.rest)
458: rescue ParseError => e
459: e.rest << @scanner.rest.to_s
460: raise
461: ensure
462: @scanner, @container, @font, @ds = orig
463: end
464: end
# File lib/math_ml/latex.rb, line 679
679: def parse_mathfont(font)
680: f = @font
681: @font = font
682: begin
683: push_container(Row.new){|r| r << parse_any}
684: ensure
685: @font = f
686: end
687: end
# File lib/math_ml/latex.rb, line 505
505: def parse_num
506: n = Number.new
507: n.extend(Variant).variant = Variant::BOLD if @font==Font::BOLD
508: n << @scanner.matched
509: end
# File lib/math_ml/latex.rb, line 531
531: def parse_operator
532: o = @scanner.matched
533: Operator.new << o
534: end
# File lib/math_ml/latex.rb, line 551
551: def parse_sub
552: e = @container.pop
553: e = None.new unless e
554: e = SubSup.new(@ds && e.display_style, e) unless e.is_a?(SubSup)
555: raise ParseError.new("Double subscript.", "_") if e.sub
556: e.sub = parse_any("Subscript not exist.")
557: e
558: end
# File lib/math_ml/latex.rb, line 560
560: def parse_sup
561: e = @container.pop
562: e = None.new unless e
563: e = SubSup.new(@ds && e.display_style, e) unless e.is_a?(SubSup)
564: raise ParseError.new("Double superscript.", @scanner[0]) if e.sup
565: if /'+/=~@scanner[0]
566: prime = Operator.new
567: prime << MathML.pcstring('′'*@scanner[0].size, true)
568: unless @scanner.scan(/\^/)
569: e.sup = prime
570: return e
571: end
572: end
573: sup = parse_any("Superscript not exist.")
574:
575: if prime
576: unless sup.is_a?(Row)
577: r = Row.new
578: r << sup
579: sup = r
580: end
581: sup.contents.insert(0, prime)
582: end
583:
584: e.sup = sup
585: e
586: end
# File lib/math_ml/latex.rb, line 592
592: def parse_symbol_command(com, plain=false)
593: unless @symbols.include?(com)
594: @scanner.pos = @scanner.pos-(com.size+1)
595: raise ParseError.new("Undefined command.")
596: end
597: data = @symbols[com]
598: return nil unless data
599:
600: data, s = data
601: su = data[0]
602: el = data[1]
603: el = :o unless el
604: s = com.dup.untaint.to_sym unless s
605: s = com if s.is_a?(String) && s.length==0
606:
607: case el
608: when :I
609: el = Identifier.new
610: when :i
611: el = Identifier.new
612: el.extend(Variant).variant = Variant::NORMAL unless s.is_a?(String)&&s.length>1
613: when :o
614: el = Operator.new
615: when :n
616: el = Number.new
617: else
618: raise ParseError.new("Inner data broken.")
619: end
620:
621: case s
622: when Fixnum
623: s = MathML.pcstring("&\#x#{s.to_s(16)};", true)
624: when ::Symbol
625: s = symbol_table.convert(s)
626: else
627: MathML.pcstring(s, true)
628: end
629:
630: return s if plain
631: el << s
632: el.as_display_style if su==:u
633: el
634: end
# File lib/math_ml/latex.rb, line 477
477: def parse_to_element(whole_group = false)
478: if whole_group && @group_begins.has_key?(@scanner.peek_command)
479: @scanner.scan_command
480: parse_group
481: else
482: case
483: when @scanner.scan(RE::NUMERICS)
484: parse_num
485: when @scanner.scan(RE::ALPHABETS)
486: parse_char
487: when @scanner.scan(RE::OPERATORS)
488: parse_operator
489: when @scanner.scan_block
490: parse_block
491: when @scanner.scan(/_/)
492: parse_sub
493: when @scanner.scan(/'+|\^/)
494: parse_sup
495: when @scanner.scan(/~/)
496: Space.new("1em")
497: when @scanner.scan_command
498: parse_command
499: else
500: raise ParseError.new('Syntax error.')
501: end
502: end
503: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.