def parse_expr(io, stop_char = nil, stack_depth = 0, multiple_expressions = false)
      # A standard stack is an expression that does not evaluate to a string
      expressions = []
      stack = []
      buf = ''
      
      loop do
        char = io.read_one_char
        
        # Ignore carriage returns
        next if char == "\r"
        
        if stop_char && char.nil?
          raise Error, "IO ran out when parsing a subexpression (expected to end on #{stop_char.inspect})"
        elsif char == stop_char # Bail out of a subexpr or bail out on nil
          # TODO: default stop_char is nil, and this is also what gets returned from a depleted
          # IO on IO#read(). We should do that in Bychar.
          # Handle any remaining subexpressions
          return wrap_up(expressions, stack, buf, stack_depth, multiple_expressions)
        elsif char == " " || char == "\n" # Space
          if buf.length > 0
            stack << buf
            buf = ''
          end
          if TERMINATORS.include?(char) && stack.any? # Introduce a stack separator! This is a new line
            
            # First get rid of the remaining buffer data
            consume_remaining_buffer(stack, buf)
            
            # Since we now finished an expression and it is on the stack,
            # we can run this expression through the filter
            filtered_expr = compact_subexpr(stack, stack_depth + 1)
            
            # Only preserve the parsed expression if it's not nil
            expressions << filtered_expr unless filtered_expr.nil?
            
            # Reset the stack for the next expression
            stack = []
            
            # Note that we will return multiple expressions instead of one
            multiple_expressions = true
          end
        elsif char == '[' # Opens a new string expression
          consume_remaining_buffer(stack, buf)
          stack << [:b] + parse_expr(io, ']', stack_depth + 1)
        elsif char == '{' # Opens a new literal expression  
          consume_remaining_buffer(stack, buf)
          stack << [:c] + parse_expr(io, '}', stack_depth + 1)
        elsif QUOTES.include?(char) # String
          consume_remaining_buffer(stack, buf)
          stack << parse_str(io, char)
        else
          buf << char
        end
      end
      
      raise Error, "Should never happen"
    end
def parse_expr(io, stop_char = nil, stack_depth = 0, multiple_expressions = false)
      # A standard stack is an expression that does not evaluate to a string
      expressions = []
      stack = []
      buf = ''
      
      loop do
        char = io.read_one_char
        
        # Ignore carriage returns
        next if char == "\r"
        
        if stop_char && char.nil?
          raise Error, "IO ran out when parsing a subexpression (expected to end on #{stop_char.inspect})"
        elsif char == stop_char # Bail out of a subexpr or bail out on nil
          # TODO: default stop_char is nil, and this is also what gets returned from a depleted
          # IO on IO#read(). We should do that in Bychar.
          # Handle any remaining subexpressions
          return wrap_up(expressions, stack, buf, stack_depth, multiple_expressions)
        elsif char == " " || char == "\n" # Space
          if buf.length > 0
            stack << buf
            buf = ''
          end
          if TERMINATORS.include?(char) && stack.any? # Introduce a stack separator! This is a new line
            
            # First get rid of the remaining buffer data
            consume_remaining_buffer(stack, buf)
            
            # Since we now finished an expression and it is on the stack,
            # we can run this expression through the filter
            filtered_expr = compact_subexpr(stack, stack_depth + 1)
            
            # Only preserve the parsed expression if it's not nil
            expressions << filtered_expr unless filtered_expr.nil?
            
            # Reset the stack for the next expression
            stack = []
            
            # Note that we will return multiple expressions instead of one
            multiple_expressions = true
          end
        elsif char == '[' # Opens a new string expression
          consume_remaining_buffer(stack, buf)
          stack << [:b] + parse_expr(io, ']', stack_depth + 1)
        elsif char == '{' # Opens a new literal expression  
          consume_remaining_buffer(stack, buf)
          stack << [:c] + parse_expr(io, '}', stack_depth + 1)
        elsif QUOTES.include?(char) # String
          consume_remaining_buffer(stack, buf)
          stack << parse_str(io, char)
        else
          buf << char
        end
      end
      
      raise Error, "Should never happen"
    end
Parse from a passed IO object either until an unescaped stop_char is reached
 or until the IO is exhausted. The last argument is the class used to
 compose the subexpression being parsed. The subparser is reentrant and not
 destructive for the object containing it.