<commit_before>//
//  Regex.swift
//  LLRegex
//
//  Created by <NAME> on 2017/5/31.
//  Copyright © 2017年 <NAME>. All rights reserved.
//

import Foundation

func extractNamedCaptureGroups(in pattern: String, expectedGroupsCount: Int) -> [String: Int] {
    struct RE {
        static let captureGroup: Regex = Regex("(\\\\*+)\\((?!\\?)")
        static let namedCaptureGroup: Regex = Regex("(\\\\*+)\\(\\?<(\\w+)>")
    }
    
    let captureGroups = RE.captureGroup.matches(in: pattern).filter { ($0.groups[1].matched ?? "").utf16.count % 2 == 0 }
    let namedCaptureGroups = RE.namedCaptureGroup.matches(in: pattern).filter { ($0.groups[1].matched ?? "").utf16.count % 2 == 0 }
    
    guard captureGroups.count + namedCaptureGroups.count == expectedGroupsCount - 1 else { return [:] }
    
    let allGroups = (captureGroups + namedCaptureGroups).sorted { $0.range.lowerBound < $1.range.lowerBound }
    
    var reval = [String: Int]()
    
    for (idx, match) in allGroups.enumerated() {
        guard match.regex == RE.namedCaptureGroup, let name = match.groups[2].matched else { continue }
        reval[name] = idx + 1
    }
    
    return reval
}


/// A type that is used to reprensent and apply regular expreesion to Unicode strings, which wrapps NSRegularExpression.
public struct Regex {
    
    /// Options of Regex.
    public typealias Options = NSRegularExpression.Options
    
    /// Wrapped NSRegularExpression.
    public var regularExpression: NSRegularExpression
    
    
    
    /**
     Creates a `Regex` with unchecked string literal and options. Runtime error is raised if the unchecked pattern is invalid.
     - parameter uncheckedPattern: The unchecked regulare expression pattern.
     - parameter options: The regular expression options that are applied to the expression during matching. Empty options by default.
     - returns: An instance with given pattern and options. Runtime error is raised if the unchecked pattern is invalid.
    */
    public init(_ uncheckedPattern: StaticString, options: Options = []) {
        do {
            try self.init(pattern: uncheckedPattern.description, options: options)
        } catch {
            fatalError("Pattern \(uncheckedPattern) is invalid.")
        }
    }
    
    /**
     Creates a `Regex` with pattern and options.
     - parameter pattern: The regulare expression pattern.
     - parameter options: The regular expression options that are applied to the expression during matching. Empty options by default.
     - returns: An instance with given pattern and options.
     - throws: An error if failed.
     */
    public init(pattern: String, options: Options = []) throws {
        let re = try NSRegularExpression(pattern: pattern, options: options)
        self.regularExpression = re
//        self.namedCaptureGroupInfo = extractNamedCaptureGroups(in: pattern, expectedGroupsCount: re.numberOfCaptureGroups)
        self.namedCaptureGroupInfo = [:]
    }
    
    /**
     Creates a `Regex` with an instance of NSRegularExpression.
     - parameters regularExpression: A compiled NSRegulareExpression.
     - returns: An instance wrapping given NSRegularExpression.
     */
    
    public init(regularExpression: NSRegularExpression) {
        self.regularExpression = regularExpression
        self.namedCaptureGroupInfo = [:]
    }
    
    
    /// The pattern value.
    public var pattern: String { return regularExpression.pattern }
    
    /**
     Set a new pattern value.
     - parameter pattern: A new pattern.
     - throws: An error if pattern is invalid.
     */
    public mutating func setPattern(_ pattern: String) throws {
        self = try Regex(pattern: pattern, options: self.options)
    }
    
    
    /// The options value.
    public var options: Options {
        get {
            return regularExpression.options
        }
        set {
            self = try! Regex(pattern: self.pattern, options: newValue)
        }
    }
    <commit_msg>Remove typealias Options = NSRegularExpression.Options<commit_after>//
//  Regex.swift
//  LLRegex
//
//  Created by <NAME> on 2017/5/31.
//  Copyright © 2017年 <NAME>. All rights reserved.
//

import Foundation

func extractNamedCaptureGroups(in pattern: String, expectedGroupsCount: Int) -> [String: Int] {
    struct RE {
        static let captureGroup: Regex = Regex("(\\\\*+)\\((?!\\?)")
        static let namedCaptureGroup: Regex = Regex("(\\\\*+)\\(\\?<(\\w+)>")
    }
    
    let captureGroups = RE.captureGroup.matches(in: pattern).filter { ($0.groups[1].matched ?? "").utf16.count % 2 == 0 }
    let namedCaptureGroups = RE.namedCaptureGroup.matches(in: pattern).filter { ($0.groups[1].matched ?? "").utf16.count % 2 == 0 }
    
    guard captureGroups.count + namedCaptureGroups.count == expectedGroupsCount - 1 else { return [:] }
    
    let allGroups = (captureGroups + namedCaptureGroups).sorted { $0.range.lowerBound < $1.range.lowerBound }
    
    var reval = [String: Int]()
    
    for (idx, match) in allGroups.enumerated() {
        guard match.regex == RE.namedCaptureGroup, let name = match.groups[2].matched else { continue }
        reval[name] = idx + 1
    }
    
    return reval
}


/// A type that is used to reprensent and apply regular expreesion to Unicode strings, which wrapps NSRegularExpression.
public struct Regex {
    
    /// Options of Regex.
    public struct Options: OptionSet {
    
        public let rawValue: UInt
        
        public init(rawValue: UInt) {
            self.rawValue = rawValue
        }
        
        public init(_ options: NSRegularExpression.Options) {
            self.init(rawValue: options.rawValue)
        }
        
        public static let caseInsensitive = Options.init(.caseInsensitive)
        public static let allowCommentsAndWhitespace = Options.init(.allowCommentsAndWhitespace)
        public static let ignoreMetacharacters = Options.init(.ignoreMetacharacters)
        public static let dotMatchesLineSeparators = Options.init(.dotMatchesLineSeparators)
        public static let anchorsMatchLines = Options.init(.anchorsMatchLines)
        public static let useUnixLineSeparators = Options.init(.useUnixLineSeparators)
        public static let useUnicodeWordBoundaries = Options.init(.useUnicodeWordBoundaries)
        
        public func toNSRegularExpresstionOptions() -> NSRegularExpression.Options {
            return NSRegularExpression.Options.init(rawValue: self.rawValue)
        }
    }
    
    /// Wrapped NSRegularExpression.
    public var regularExpression: NSRegularExpression {
        didSet {
            _options = Options(regularExpression.options)
        }
    }
    
    /**
     Creates a `Regex` with unchecked string literal and options. Runtime error is raised if the unchecked pattern is invalid.
     - parameter uncheckedPattern: The unchecked regulare expression pattern.
     - parameter options: The regular expression options that are applied to the expression during matching. Empty options by default.
     - returns: An instance with given pattern and options. Runtime error is raised if the unchecked pattern is invalid.
    */
    public init(_ uncheckedPattern: StaticString, options: Options = []) {
        do {
            try self.init(pattern: uncheckedPattern.description, options: options)
        } catch {
            fatalError("Pattern \(uncheckedPattern) is invalid.")
        }
    }
    
    /**
     Creates a `Regex` with pattern and options.
     - parameter pattern: The regulare expression pattern.
     - parameter options: The regular expression options that are applied to the expression during matching. Empty options by default.
     - returns: An instance with given pattern and options.
     - throws: An error if failed.
     */
    public init(pattern: String, options: Options = []) throws {
        let re = try NSRegularExpression(pattern: pattern, options: options.toNSRegularExpresstionOptions())
        self.regularExpression = re
        self._options = options
//        self.namedCaptureGroupInfo = extractNamedCaptureGroups(in: pattern, expectedGroupsCount: re.numberOfCaptureGroups)
        self.namedCaptureGroupInfo = [:]
    }
    
    /**
     Creates a `Regex` with an instance of NSRegularExpression.
     - parameters regularExpression: A compiled NSRegulareExpression.
     - returns: An instance wrapping given NSRegularExpression.
     */
    
    public init(regularExpression: NSRegularExpression) {
        self.regularExpression = regularExpression
        self._options = Options(regularExpression.options)
        self.namedCaptureGroupInfo = [:]
    }
    
    
    /// The pattern value.
    public var pattern: String { return regularExpression.pattern }
    
    /**
     Set a new pattern value.
     - parameter pattern: A new pattern.
     - throws: An error if pattern is invalid.
     */
    public mutating func setPattern(_ pattern: String) throws {
        self = try Regex(pattern: pattern, options: self.options)
    }
    
    private var _options: Options
    
    /// The options value.
    public var options: Options {
        get {
            return _options
        }
        set {
            self = try! Regex(pattern: self.pattern, options: newValue)
        }
    }
    
{'fraction_non_alphanumeric': 0.09485825158995365, 'fraction_numerical': 0.0060364341920879595, 'mean_word_length': 2.6017080745341614, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 12, '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': '1957008', 'n_tokens_mistral': 2500, 'n_tokens_neox': 2410, 'n_words': 763}