<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def process(self, context, lines):
 		"""Chop up individual lines into static and dynamic parts. 		 		Applies light optimizations, such as empty chunk removal, and calls out to other methods to process different 		chunk types. 		 		The processor protocol here requires the method to accept values by yielding resulting lines while accepting 		sent chunks. Deferral of multiple chunks is possible by yielding None. The processor will be sent None to 		be given a chance to yield a final line and perform any clean-up. 		"""

		
		handler = None
		
		for line in lines:
			for chunk in chunk_(line):
				if 'strip' in context.flag:
					chunk.line = chunk.stripped
				
				if not chunk.line: continue  # Eliminate empty chunks, i.e. trailing text segments, ${}, etc.
				
				if not handler or handler[0] != chunk.kind:
					if handler:
						try:
							result = next(handler[1])
						except StopIteration:
							result = None
						
						if result: yield result
					
					handler = getattr(self, 'process_' + chunk.kind, self.process_generic)(chunk.kind, context)
					handler = (chunk.kind, handler)
					
					try:
						next(handler[1])  # We fast-forward to the first yield.
					except StopIteration:
						return
				
				result = handler[1].send(chunk)  # Send the handler the next contiguous chunk.
				if result: yield result
				
				if __debug__:  # In development mode we skip the contiguous chunk compaction optimization.
					handler = (None, handler[1])
		
		# Clean up the final iteration.
		if handler:
			try:
				result = next(handler[1])
			except StopIteration:
				return
			
			if result: yield result