def rule(re, tok=nil, next_state=nil, &callback)
if tok.nil? && callback.nil?
raise "please pass `rule` a token to yield or a callback"
end
callback ||= case next_state
when :pop!
proc do |stream|
puts " yielding #{tok.qualname}, #{stream[0].inspect}" if @debug
@output_stream.call(tok, stream[0])
puts " popping stack: 1" if @debug
@stack.pop or raise 'empty stack!'
end
when :push
proc do |stream|
puts " yielding #{tok.qualname}, #{stream[0].inspect}" if @debug
@output_stream.call(tok, stream[0])
puts " pushing :#{@stack.last.name}" if @debug
@stack.push(@stack.last)
end
when Symbol
proc do |stream|
puts " yielding #{tok.qualname}, #{stream[0].inspect}" if @debug
@output_stream.call(tok, stream[0])
state = @states[next_state] || self.class.get_state(next_state)
puts " pushing :#{state.name}" if @debug
@stack.push(state)
end
when nil
proc do |stream|
puts " yielding #{tok.qualname}, #{stream[0].inspect}" if @debug
@output_stream.call(tok, stream[0])
end
else
raise "invalid next state: #{next_state.inspect}"
end
rules << Rule.new(re, callback)
end