def initialize source
parser = REXML::Parsers::BaseParser.new( source )
@root = @current = State.new(0)
previous = @current
branches = []
slinker = [ ]
elinker = [ ]
zps = nil
zpe = nil
ssequence = lambda {|e|
zps = previous = previous[ e ] = State.new
}
esequence = lambda {|e|
zpe = e
previous = previous[ e ] = State.new
}
oneplus = lambda {|e|
slinker.pop
s = slinker[-1].call( e )
branches << [e, s]
s
}
schoice = lambda {|e|
if e.single?
branches[-2][e] = branches[-1]
else
previous = branches[-2]
ssequence.call( e )
end
}
echoice = lambda {|e|
previous[e] = branches[-1]
previous = branches[-2]
}
eoptional = lambda {|e|
ns = State.new
elinker.pop
previous = branches.pop[e] = previous[e] = ns
}
slinker << ssequence
elinker << esequence
element_names = []
valevt = nil
begin
event = parser.pull
case event[0]
when :start_element
case event[1]
when "empty"
when "element", "attribute"
element_names << event[2]["name"]
etype = event[1] == "attribute" ? :start_attribute : event[0]
evt = Event.new( etype, event[2]["name"] )
slinker[-1].call( evt )
slinker << ssequence
elinker << esequence
when "text"
evt = Event.new( :text )
slinker[-1].call(evt)
when "optional"
branches << previous
when "choice"
branches << previous
branches << State.new
slinker << schoice
elinker << echoice
when "oneOrMore"
slinker << oneplus
when "zeroOrMore"
branches << previous
slinker << ssequence
elinker << esequence
when "group"
slinker << ssequence
elinker << esequence
when "value"
valevt = evt = Event.new( :text )
slinker[-1].call(evt)
when "ref"
when "interleave"
when "mixed"
when "grammar"
when "start"
when "define"
when "data"
when "param"
when "include"
end
when :end_element
case event[1]
when "attribute", "element"
slinker.pop
elinker.pop
etype = event[1] == "attribute" ? :end_attribute : event[0]
evt = Event.new( etype, element_names.pop )
elinker[-1].call( evt )
when "zeroOrMore"
slinker.pop
elinker.pop
zps[zpe] = previous = branches.pop
when "oneOrMore"
e,s = branches.pop
previous[ e ] = s
when "choice"
slinker.pop
elinker.pop
previous = branches.pop
branches.pop
when "optional"
elinker << eoptional
elinker << nil
when "empty"
when "group"
slinker.pop
elinker.pop
previous = zps
elinker[-1].call( zpe )
end
when :end_document
previous[ Event.new( event[0] ) ] = State.new
when :text
if valevt
valevt.event_arg = event[1]
valevt = nil
end
end
end while event[0] != :end_document
end