# class MathML::LaTeX::Macro

### Public Class Methods

new() click to toggle source

    # File lib/math_ml/latex.rb, line 185
    def initialize
            @commands = Hash.new
            @environments = Hash.new
    end

### Public Instance Methods

check_parameter_numbers(src, opt, whole) click to toggle source

    # File lib/math_ml/latex.rb, line 228
    def check_parameter_numbers(src, opt, whole)
            s = Scanner.new(src)
            until s.eos?
                    case
                    when s.scan(/#{MBEC}*?\#(\d+|.)/)
                            raise parse_error("Need positive number.") unless s[1]=~/\d+/
                            raise parse_error("Parameter \# too large.", s[1]+s.rest, whole) if s[1].to_i>opt
                    else
                            return nil
                    end
            end
    end

commands(com) click to toggle source

    # File lib/math_ml/latex.rb, line 300
    def commands(com)
            @commands[com]
    end

environments(env) click to toggle source

    # File lib/math_ml/latex.rb, line 316
    def environments(env)
            @environments[env]
    end

expand_command(com, params, opt=nil) click to toggle source

    # File lib/math_ml/latex.rb, line 304
    def expand_command(com, params, opt=nil)
            return nil unless @commands.has_key?(com)
            c = @commands[com]
            opt = c.option if c.option && !opt
            params.unshift(opt) if c.option
            raise ParseError.new("Need more parameter.") if params.size < c.num

            c.body.gsub(/(#{MBEC}*?)\#(\d+)/) do
                    $1.to_s << params[$2.to_i-1]
            end
    end

expand_environment(env, body, params, opt=nil) click to toggle source

    # File lib/math_ml/latex.rb, line 320
    def expand_environment(env, body, params, opt=nil)
            return nil unless @environments.has_key?(env)
            e = @environments[env]
            opt = e.option if e.option && !opt
            params.unshift(opt) if e.option
            raise ParseError.new("Need more parameter.") if params.size < e.num

            bg = e.beginning.gsub(/(#{MBEC}*?)\#(\d+)/) do
                    $1.to_s << params[$2.to_i-1]
            end

            en = e.ending.gsub(/(#{MBEC}*?)\#(\d+)/) do
                    $1.to_s << params[$2.to_i-1]
            end

            " #{bg} #{body} #{en} "
    end

parse(src) click to toggle source

    # File lib/math_ml/latex.rb, line 197
    def parse(src)
            @scanner = Scanner.new(src)
            until @scanner.eos?
                    unless @scanner.scan_command
                            @scanner.scan_space
                            raise parse_error("Syntax error.")
                    end
                    case @scanner[1]
                    when "newcommand"
                            parse_newcommand
                    when "newenvironment"
                            parse_newenvironment
                    else
                            raise parse_error("Syntax error.", @scanner.matched)
                    end
            end
    rescue BlockNotClosed => e
            raise parse_error("Block not closed.")
    rescue OptionNotClosed => e
            raise parse_error("Option not closed.")
    end

parse_error(message, rest="", whole=nil) click to toggle source

    # File lib/math_ml/latex.rb, line 190
    def parse_error(message, rest="", whole=nil)
            rest = whole[/\A.*?(#{Regexp.escape(rest)}.*\z)/, 1] if whole
            rest << @scanner.rest
            done = @scanner.string[0, @scanner.string.size-rest.size]
            ParseError.new(message, rest, done)
    end

parse_newcommand() click to toggle source

    # File lib/math_ml/latex.rb, line 241
    def parse_newcommand
            case
            when @scanner.scan_block
                    s = Scanner.new(@scanner[1])
                    raise parse_error("Need newcommand.", s.rest+"}") unless s.scan_command
                    com = s[1]
                    raise parse_error("Syntax error." ,s.rest+"}") unless s.eos?
            when @scanner.scan_command
                    s = Scanner.new(@scanner[1])
                    com = s.scan_command
            else
                    raise parse_error("Need newcommand.")
            end

            optnum = scan_num_of_parameter
            opt = @scanner.scan_option ? @scanner[1] : nil

            case
            when @scanner.scan_block
                    body = @scanner[1]
            when @scanner.scan_command
                    body = @scanner.matched
            else
                    body = @scanner.scan(/./)
            end

            raise parse_error("Need parameter.") unless body

            check_parameter_numbers(body, optnum, @scanner.matched)

            optnum-=1 if opt
            @commands[com] = Command.new(optnum, body, opt)
    end

parse_newenvironment() click to toggle source

    # File lib/math_ml/latex.rb, line 275
    def parse_newenvironment
            case
            when @scanner.scan_block
                    env = @scanner[1]
            when @scanner.scan_command
                    raise ParseError.new
            when @scanner.scan(/./)
                    env = @scanner.matched
            end
            raise parse_error("Syntax error.", env[/\A.*?(\\.*\z)/, 1], @scanner.matched) if env=~/\\/

            optnum = scan_num_of_parameter
            opt = @scanner.scan_option ? @scanner[1] : nil

            b = @scanner.scan_block ? @scanner[1] : @scanner.scan_any
            raise parse_error("Need begin block.") unless b
            check_parameter_numbers(b, optnum, @scanner.matched)
            e = @scanner.scan_block ? @scanner[1] : @scanner.scan_any
            raise parse_error("Need end block.") unless e
            check_parameter_numbers(e, optnum, @scanner.matched)

            optnum -= 1 if opt
            @environments[env] = Environment.new(optnum, b, e, opt)
    end

scan_num_of_parameter() click to toggle source

    # File lib/math_ml/latex.rb, line 219
    def scan_num_of_parameter
            if @scanner.scan_option
                    raise parse_error("Need positive number.", @scanner[1]+"]") unless @scanner[1]=~/\A#{RE::SPACE}*\d+#{RE::SPACE}*\z/
                    @scanner[1].to_i
            else
                    0
            end
    end