class MathML::LaTeX::Parser

Constants

BUILTIN_MACRO

Attributes

macro[R]
symbol_table[R]
unsecure_entity[RW]

Public Class Methods

new(opt={}) click to toggle source
Calls superclass method MathML::LaTeX::BuiltinCommands::new
    # File lib/math_ml/latex.rb
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

Public Instance Methods

add_commands(*a) click to toggle source
    # File lib/math_ml/latex.rb
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
add_delimiter(list) click to toggle source
    # File lib/math_ml/latex.rb
430 def add_delimiter(list)
431         @delimiters.concat(list)
432 end
add_entity(list) click to toggle source
    # File lib/math_ml/latex.rb
383 def add_entity(list)
384         list.each do |i|
385                 @entities[i] = true
386         end
387 end
add_group(begin_name, end_name, method=nil) click to toggle source
    # File lib/math_ml/latex.rb
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
add_multi_command(m, *a) click to toggle source
    # File lib/math_ml/latex.rb
422 def add_multi_command(m, *a)
423         a.each{|i| @commands[i] = m}
424 end
add_plugin(plugin) click to toggle source
    # File lib/math_ml/latex.rb
410 def add_plugin(plugin)
411         self.extend(plugin)
412 end
add_sym_cmd(hash) click to toggle source
    # File lib/math_ml/latex.rb
426 def add_sym_cmd(hash)
427         @symbols.merge!(hash)
428 end
parse(src, displaystyle=false) click to toggle source
    # File lib/math_ml/latex.rb
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
push_container(container, scanner=@scanner, font=@font) { |container| ... } click to toggle source
    # File lib/math_ml/latex.rb
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

Private Instance Methods

entitize(str) click to toggle source
    # File lib/math_ml/latex.rb
590 def entitize(str)
591         MathML.pcstring(str.sub(/^(.*)$/){"&#{$1};"}, true)
592 end
parse_any(message = "Syntax error.") click to toggle source
    # File lib/math_ml/latex.rb
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
parse_block() click to toggle source
    # File lib/math_ml/latex.rb
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
parse_char() click to toggle source
    # File lib/math_ml/latex.rb
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
parse_command() click to toggle source
    # File lib/math_ml/latex.rb
639 def parse_command
640         com = @scanner[1]
641         matched = @scanner.matched
642         pos = @scanner.pos-matched.size
643         macro = @macro.commands(com)
644         if macro
645                 begin
646                         flg = @expanded_command.include?(com)
647                         @expanded_command.push(com)
648                         raise CircularReferenceCommand if flg
649                         option = (macro.option && @scanner.scan_option) ? @scanner[1] : nil
650                         params = Array.new
651                         (1..macro.num).each do
652                                 params << (@scanner.scan_block ? @scanner[1] : @scanner.scan_any)
653                                 raise ParseError.new("Need more parameter.") unless params.last
654                         end
655                         r = parse_into(@macro.expand_command(com, params, option), Array.new)
656                         return r
657                 rescue CircularReferenceCommand
658                         if @expanded_command.size>1
659                                 raise
660                         else
661                                 @scanner.pos = pos
662                                 raise ParseError.new("Circular reference.")
663                         end
664                 rescue ParseError => e
665                         if @expanded_command.size>1
666                                 raise
667                         else
668                                 @scanner.pos = pos
669                                 raise ParseError.new(%[Error in macro(#{e.message} "#{e.rest.strip}").])
670                         end
671                 ensure
672                         @expanded_command.pop
673                 end
674         elsif @commands.key?(com)
675                 m = @commands[com]
676                 m = com unless m
677                 return __send__("cmd_#{m.to_s}")
678         end
679         parse_symbol_command(com)
680 end
parse_group() click to toggle source
    # File lib/math_ml/latex.rb
692 def parse_group
693         font = @font
694         begin
695                 g = @group_begins[@scanner[1]]
696                 g = @scanner[1] unless g
697                 __send__("grp_#{g.to_s}")
698         ensure
699                 @font = font
700         end
701 end
parse_into(src, parent, font=nil) click to toggle source
    # File lib/math_ml/latex.rb
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 = e.rest + @scanner.rest.to_s
460                 raise
461         ensure
462                 @scanner, @container, @font, @ds = orig
463         end
464 end
parse_mathfont(font) click to toggle source
    # File lib/math_ml/latex.rb
682 def parse_mathfont(font)
683         f = @font
684         @font = font
685         begin
686                 push_container(Row.new){|r| r << parse_any}
687         ensure
688                 @font = f
689         end
690 end
parse_num() click to toggle source
    # File lib/math_ml/latex.rb
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
parse_operator() click to toggle source
    # File lib/math_ml/latex.rb
531 def parse_operator
532         o = @scanner.matched
533         Operator.new.tap{|op| op[:stretchy]="false"} << o
534 end
parse_sub() click to toggle source
    # File lib/math_ml/latex.rb
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
parse_sup() click to toggle source
    # File lib/math_ml/latex.rb
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                 @scanner[0].size.times do
568                         prime << symbol_table.convert("prime")
569                 end
570                 unless @scanner.scan(/\^/)
571                         e.sup = prime
572                         return e
573                 end
574         end
575         sup = parse_any("Superscript not exist.")
576 
577         if prime
578                 unless sup.is_a?(Row)
579                         r = Row.new
580                         r << sup
581                         sup = r
582                 end
583                 sup.contents.insert(0, prime)
584         end
585 
586         e.sup = sup
587         e
588 end
parse_symbol_command(com, plain=false) click to toggle source
    # File lib/math_ml/latex.rb
594 def parse_symbol_command(com, plain=false)
595         unless @symbols.include?(com)
596                 @scanner.pos = @scanner.pos-(com.size+1)
597                 raise ParseError.new("Undefined command.")
598         end
599         data = @symbols[com]
600         return nil unless data
601 
602         data, s = data
603         su = data[0]
604         el = data[1]
605         el = :o unless el
606         s = com.dup.untaint.to_sym unless s
607         s = com if s.is_a?(String) && s.length==0
608 
609         case el
610         when :I
611                 el = Identifier.new
612         when :i
613                 el = Identifier.new
614                 el.extend(Variant).variant = Variant::NORMAL unless s.is_a?(String)&&s.length>1
615         when :o
616                 el = Operator.new
617                 el[:stretchy] = "false"
618         when :n
619                 el = Number.new
620         else
621                 raise ParseError.new("Inner data broken.")
622         end
623 
624         case s
625         when Fixnum
626                 s = MathML.pcstring("&\#x#{s.to_s(16)};", true)
627         when ::Symbol
628                 s = symbol_table.convert(s)
629         else
630                 MathML.pcstring(s, true)
631         end
632 
633         return s if plain
634         el << s
635         el.as_display_style if su==:u
636         el
637 end
parse_to_element(whole_group = false) click to toggle source
    # File lib/math_ml/latex.rb
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