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