def grp_begin
matched = @scanner.matched
begin_pos = @scanner.pos-matched.size
en = @scanner.scan_block ? @scanner[1] : @scanner.scan_any
raise ParseError.new('Environment name not exist.') unless en
macro = @macro.environments(en)
if macro
begin
flg = @expanded_environment.include?(en)
@expanded_environment.push(en)
raise CircularReferenceEnvironment if flg
pos = @scanner.pos
option = (macro.option && @scanner.scan_option) ? @scanner[1] : nil
params = Array.new
(1..macro.num).each do
params << (@scanner.scan_block ? @scanner[1] : @scanner.scan_any)
raise ParseError.new("Need more parameter.") unless params.last
end
body = ""
grpnest = 0
until @scanner.peek_command=="end" && grpnest==0
if @scanner.eos?
@scanner.pos = pos
raise ParseError.new('Matching \end not exist.')
end
com = @scanner.peek_command
grpnest += 1 if @group_begins.has_key?(com)
grpnest -=1 if @group_ends.has_key?(com) && @group_begins[com]
raise ParseError.new("Syntax error.") if grpnest<0
body << @scanner.scan_any(true)
end
@scanner.scan_command
raise ParseError.new("Environment mismatched.", @scanner.matched) unless en==(@scanner.scan_block ? @scanner[1] : @scanner.scan_any)
begin
return parse_into(@macro.expand_environment(en, body, params, option), Array.new)
rescue CircularReferenceEnvironment
if @expanded_environment.size>1
raise
else
@scanner.pos = begin_pos
raise ParseError.new("Circular reference.")
end
rescue ParseError => e
if @expanded_environment.size>1
raise
else
@scanner.pos = begin_pos
raise ParseError.new(%[Error in macro(#{e.message} "#{e.rest.strip}").])
end
end
ensure
@expanded_environment.pop
end
end
raise ParseError.new("Undefined environment.") unless @environments.has_key?(en)
e = @environments[en]
e = en unless e
__send__("env_#{e.to_s}")
end