<commit_before>//
//  Parser.swift
//  SwiftCLI
//
//  Created by <NAME> on 6/28/16.
//  Copyright (c) 2016 jakeheis. All rights reserved.
//

// MARK: - Parser

public class Parser {
    
    public enum RouteBehavior {
        case search
        case searchWithFallback(Command)
        case automatically(Command)
        
        var fallback: Command? {
            switch self {
            case .search: return nil
            case .searchWithFallback(let cmd): return cmd
            case .automatically(let cmd): return cmd
            }
        }
    }
    
    private enum State {
        case routing(CommandGroupPath)
        case routed(CommandPath, ParameterIterator)
        
        var command: CommandPath? {
            if case let .routed(path, _) = self {
                return path
            }
            return nil
        }
    }
    
    public var parseOptionsAfterCollectedParameter = false
    public var routeBehavior: RouteBehavior = .search
    
    public init() {}
    
    public func parse(cli: CLI, arguments: ArgumentList) throws -> CommandPath {
        let optionRegistry = OptionRegistry(routable: cli)
        
        var state: State = .routing(CommandGroupPath(top: cli))
        
        while arguments.hasNext() {
            if shouldParseOption(state: state, arguments: arguments, optionRegistry: optionRegistry) {
                try optionRegistry.parseOneOption(args: arguments, command: state.command)
                continue
            }
            
            switch state {
            case .routing(let groupPath):
                state = try route(groupPath: groupPath, arguments: arguments, optionRegistry: optionRegistry)
            case .routed(let commandPath, let params):
                if let namedParam = params.next() {
                    let result = namedParam.param.update(to: arguments.pop())
                    if case let .failure(error) = result {
                        throw ParameterError(command: commandPath, kind: .invalidValue(namedParam, error))
                    }
                } else {
                    throw ParameterError(command: commandPath, kind: .wrongNumber(params.minCount, params.maxCount))
                }
            }
        }
        
        if case let .routing(group) = state, let fallback = routeBehavior.fallback, cli.helpFlag?.value != true {
            var command = group.appending(fallback)
            command.ignoreName = true
            state = .routed(command, ParameterIterator(command: command))
        }
        <commit_msg>Don't take help flag into account when falling back<commit_after>//
//  Parser.swift
//  SwiftCLI
//
//  Created by <NAME> on 6/28/16.
//  Copyright (c) 2016 jakeheis. All rights reserved.
//

// MARK: - Parser

public class Parser {
    
    public enum RouteBehavior {
        case search
        case searchWithFallback(Command)
        case automatically(Command)
        
        var fallback: Command? {
            switch self {
            case .search: return nil
            case .searchWithFallback(let cmd): return cmd
            case .automatically(let cmd): return cmd
            }
        }
    }
    
    private enum State {
        case routing(CommandGroupPath)
        case routed(CommandPath, ParameterIterator)
        
        var command: CommandPath? {
            if case let .routed(path, _) = self {
                return path
            }
            return nil
        }
    }
    
    public var parseOptionsAfterCollectedParameter = false
    public var routeBehavior: RouteBehavior = .search
    
    public init() {}
    
    public func parse(cli: CLI, arguments: ArgumentList) throws -> CommandPath {
        let optionRegistry = OptionRegistry(routable: cli)
        
        var state: State = .routing(CommandGroupPath(top: cli))
        
        while arguments.hasNext() {
            if shouldParseOption(state: state, arguments: arguments, optionRegistry: optionRegistry) {
                try optionRegistry.parseOneOption(args: arguments, command: state.command)
                continue
            }
            
            switch state {
            case .routing(let groupPath):
                state = try route(groupPath: groupPath, arguments: arguments, optionRegistry: optionRegistry)
            case .routed(let commandPath, let params):
                if let namedParam = params.next() {
                    let result = namedParam.param.update(to: arguments.pop())
                    if case let .failure(error) = result {
                        throw ParameterError(command: commandPath, kind: .invalidValue(namedParam, error))
                    }
                } else {
                    throw ParameterError(command: commandPath, kind: .wrongNumber(params.minCount, params.maxCount))
                }
            }
        }
        
        if case let .routing(group) = state, let fallback = routeBehavior.fallback {
            var command = group.appending(fallback)
            command.ignoreName = true
            state = .routed(command, ParameterIterator(command: command))
        }
        
{'fraction_non_alphanumeric': 0.08146995916780089, 'fraction_numerical': 0.00349990278047832, 'mean_word_length': 1.7073684210526316, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7222000', 'n_tokens_mistral': 1313, 'n_tokens_neox': 1255, 'n_words': 354}