class Cucumber::CucumberExpressions::CucumberExpression

def assert_no_optionals(node, &raise_error)

def assert_no_optionals(node, &raise_error)
  nodes = node.nodes.select { |ast_node| NodeType::OPTIONAL == ast_node.type }
  raise_error.call(nodes[0]) if nodes.length > 0
end

def assert_no_parameters(node, &raise_error)

def assert_no_parameters(node, &raise_error)
  nodes = node.nodes.select { |ast_node| NodeType::PARAMETER == ast_node.type }
  raise_error.call(nodes[0]) if nodes.length > 0
end

def assert_not_empty(node, &raise_error)

def assert_not_empty(node, &raise_error)
  text_nodes = node.nodes.select { |ast_node| NodeType::TEXT == ast_node.type }
  raise_error.call(node) if text_nodes.length == 0
end

def escape_regex(expression)

def escape_regex(expression)
  expression.gsub(ESCAPE_PATTERN, '\\\\\1')
end

def initialize(expression, parameter_type_registry)

def initialize(expression, parameter_type_registry)
  @expression = expression
  @parameter_type_registry = parameter_type_registry
  @parameter_types = []
  parser = CucumberExpressionParser.new
  ast = parser.parse(expression)
  pattern = rewrite_to_regex(ast)
  @tree_regexp = TreeRegexp.new(pattern)
end

def match(text)

def match(text)
  Argument.build(@tree_regexp, text, @parameter_types)
end

def regexp

def regexp
  @tree_regexp.regexp
end

def rewrite_alternation(node)

def rewrite_alternation(node)
  # Make sure the alternative parts aren't empty and don't contain parameter types
  node.nodes.each { |alternative|
    raise AlternativeMayNotBeEmpty.new(alternative, @expression) if alternative.nodes.length == 0
    assert_not_empty(alternative) { |ast_node| raise AlternativeMayNotExclusivelyContainOptionals.new(ast_node, @expression) }
  }
  regex = node.nodes.map { |n| rewrite_to_regex(n) }.join('|')
  "(?:#{regex})"
end

def rewrite_alternative(node)

def rewrite_alternative(node)
  node.nodes.map { |last_node| rewrite_to_regex(last_node) }.join('')
end

def rewrite_expression(node)

def rewrite_expression(node)
  regex = node.nodes.map { |n| rewrite_to_regex(n) }.join('')
  "^#{regex}$"
end

def rewrite_optional(node)

def rewrite_optional(node)
  assert_no_parameters(node) { |ast_node| raise ParameterIsNotAllowedInOptional.new(ast_node, @expression) }
  assert_no_optionals(node) { |ast_node| raise OptionalIsNotAllowedInOptional.new(ast_node, @expression) }
  assert_not_empty(node) { |ast_node| raise OptionalMayNotBeEmpty.new(ast_node, @expression) }
  regex = node.nodes.map { |n| rewrite_to_regex(n) }.join('')
  "(?:#{regex})?"
end

def rewrite_parameter(node)

def rewrite_parameter(node)
  name = node.text
  parameter_type = @parameter_type_registry.lookup_by_type_name(name)
  raise UndefinedParameterTypeError.new(node, @expression, name) if parameter_type.nil?
  @parameter_types.push(parameter_type)
  regexps = parameter_type.regexps
  return "(#{regexps[0]})" if regexps.length == 1
  "((?:#{regexps.join(')|(?:')}))"
end

def rewrite_to_regex(node)

def rewrite_to_regex(node)
  case node.type
  when NodeType::TEXT
    return escape_regex(node.text)
  when NodeType::OPTIONAL
    return rewrite_optional(node)
  when NodeType::ALTERNATION
    return rewrite_alternation(node)
  when NodeType::ALTERNATIVE
    return rewrite_alternative(node)
  when NodeType::PARAMETER
    return rewrite_parameter(node)
  when NodeType::EXPRESSION
    return rewrite_expression(node)
  else
    # Can't happen as long as the switch case is exhaustive
    raise "#{node.type}"
  end
end

def source

def source
  @expression
end

def to_s

def to_s
  source.inspect
end