scratch – Diff between revs 75 and 125

Subversion Repositories:
Rev:
Only display areas with differencesIgnore whitespace
Rev 75 Rev 125
1   1  
2 # Pattern is a zero-conflict wrapper extending RegExp features 2 # Pattern is a zero-conflict wrapper extending RegExp features
3 # in order to make YAML parsing regex more expressive. 3 # in order to make YAML parsing regex more expressive.
4 # 4 #
5 class Pattern 5 class Pattern
6   6  
7 # @property [RegExp] The RegExp instance 7 # @property [RegExp] The RegExp instance
8 regex: null 8 regex: null
9   9  
10 # @property [String] The raw regex string 10 # @property [String] The raw regex string
11 rawRegex: null 11 rawRegex: null
12   12  
13 # @property [String] The cleaned regex string (used to create the RegExp instance) 13 # @property [String] The cleaned regex string (used to create the RegExp instance)
14 cleanedRegex: null 14 cleanedRegex: null
15   15  
16 # @property [Object] The dictionary mapping names to capturing bracket numbers 16 # @property [Object] The dictionary mapping names to capturing bracket numbers
17 mapping: null 17 mapping: null
18   18  
19 # Constructor 19 # Constructor
20 # 20 #
21 # @param [String] rawRegex The raw regex string defining the pattern 21 # @param [String] rawRegex The raw regex string defining the pattern
22 # 22 #
23 constructor: (rawRegex, modifiers = '') -> 23 constructor: (rawRegex, modifiers = '') ->
24 cleanedRegex = '' 24 cleanedRegex = ''
25 len = rawRegex.length 25 len = rawRegex.length
26 mapping = null 26 mapping = null
27   27  
28 # Cleanup raw regex and compute mapping 28 # Cleanup raw regex and compute mapping
29 capturingBracketNumber = 0 29 capturingBracketNumber = 0
30 i = 0 30 i = 0
31 while i < len 31 while i < len
32 _char = rawRegex.charAt(i) 32 _char = rawRegex.charAt(i)
33 if _char is '\\' 33 if _char is '\\'
34 # Ignore next character 34 # Ignore next character
35 cleanedRegex += rawRegex[i..i+1] 35 cleanedRegex += rawRegex[i..i+1]
36 i++ 36 i++
37 else if _char is '(' 37 else if _char is '('
38 # Increase bracket number, only if it is capturing 38 # Increase bracket number, only if it is capturing
39 if i < len - 2 39 if i < len - 2
40 part = rawRegex[i..i+2] 40 part = rawRegex[i..i+2]
41 if part is '(?:' 41 if part is '(?:'
42 # Non-capturing bracket 42 # Non-capturing bracket
43 i += 2 43 i += 2
44 cleanedRegex += part 44 cleanedRegex += part
45 else if part is '(?<' 45 else if part is '(?<'
46 # Capturing bracket with possibly a name 46 # Capturing bracket with possibly a name
47 capturingBracketNumber++ 47 capturingBracketNumber++
48 i += 2 48 i += 2
49 name = '' 49 name = ''
50 while i + 1 < len 50 while i + 1 < len
51 subChar = rawRegex.charAt(i + 1) 51 subChar = rawRegex.charAt(i + 1)
52 if subChar is '>' 52 if subChar is '>'
53 cleanedRegex += '(' 53 cleanedRegex += '('
54 i++ 54 i++
55 if name.length > 0 55 if name.length > 0
56 # Associate a name with a capturing bracket number 56 # Associate a name with a capturing bracket number
57 mapping ?= {} 57 mapping ?= {}
58 mapping[name] = capturingBracketNumber 58 mapping[name] = capturingBracketNumber
59 break 59 break
60 else 60 else
61 name += subChar 61 name += subChar
62   62  
63 i++ 63 i++
64 else 64 else
65 cleanedRegex += _char 65 cleanedRegex += _char
66 capturingBracketNumber++ 66 capturingBracketNumber++
67 else 67 else
68 cleanedRegex += _char 68 cleanedRegex += _char
69 else 69 else
70 cleanedRegex += _char 70 cleanedRegex += _char
71   71  
72 i++ 72 i++
73   73  
74 @rawRegex = rawRegex 74 @rawRegex = rawRegex
75 @cleanedRegex = cleanedRegex 75 @cleanedRegex = cleanedRegex
76 @regex = new RegExp @cleanedRegex, 'g'+modifiers.replace('g', '') 76 @regex = new RegExp @cleanedRegex, 'g'+modifiers.replace('g', '')
77 @mapping = mapping 77 @mapping = mapping
78   78  
79   79  
80 # Executes the pattern's regex and returns the matching values 80 # Executes the pattern's regex and returns the matching values
81 # 81 #
82 # @param [String] str The string to use to execute the pattern 82 # @param [String] str The string to use to execute the pattern
83 # 83 #
84 # @return [Array] The matching values extracted from capturing brackets or null if nothing matched 84 # @return [Array] The matching values extracted from capturing brackets or null if nothing matched
85 # 85 #
86 exec: (str) -> 86 exec: (str) ->
87 @regex.lastIndex = 0 87 @regex.lastIndex = 0
88 matches = @regex.exec str 88 matches = @regex.exec str
89   89  
90 if not matches? 90 if not matches?
91 return null 91 return null
92   92  
93 if @mapping? 93 if @mapping?
94 for name, index of @mapping 94 for name, index of @mapping
95 matches[name] = matches[index] 95 matches[name] = matches[index]
96   96  
97 return matches 97 return matches
98   98  
99   99  
100 # Tests the pattern's regex 100 # Tests the pattern's regex
101 # 101 #
102 # @param [String] str The string to use to test the pattern 102 # @param [String] str The string to use to test the pattern
103 # 103 #
104 # @return [Boolean] true if the string matched 104 # @return [Boolean] true if the string matched
105 # 105 #
106 test: (str) -> 106 test: (str) ->
107 @regex.lastIndex = 0 107 @regex.lastIndex = 0
108 return @regex.test str 108 return @regex.test str
109   109  
110   110  
111 # Replaces occurences matching with the pattern's regex with replacement 111 # Replaces occurences matching with the pattern's regex with replacement
112 # 112 #
113 # @param [String] str The source string to perform replacements 113 # @param [String] str The source string to perform replacements
114 # @param [String] replacement The string to use in place of each replaced occurence. 114 # @param [String] replacement The string to use in place of each replaced occurence.
115 # 115 #
116 # @return [String] The replaced string 116 # @return [String] The replaced string
117 # 117 #
118 replace: (str, replacement) -> 118 replace: (str, replacement) ->
119 @regex.lastIndex = 0 119 @regex.lastIndex = 0
120 return str.replace @regex, replacement 120 return str.replace @regex, replacement
121   121  
122   122  
123 # Replaces occurences matching with the pattern's regex with replacement and 123 # Replaces occurences matching with the pattern's regex with replacement and
124 # get both the replaced string and the number of replaced occurences in the string. 124 # get both the replaced string and the number of replaced occurences in the string.
125 # 125 #
126 # @param [String] str The source string to perform replacements 126 # @param [String] str The source string to perform replacements
127 # @param [String] replacement The string to use in place of each replaced occurence. 127 # @param [String] replacement The string to use in place of each replaced occurence.
128 # @param [Integer] limit The maximum number of occurences to replace (0 means infinite number of occurences) 128 # @param [Integer] limit The maximum number of occurences to replace (0 means infinite number of occurences)
129 # 129 #
130 # @return [Array] A destructurable array containing the replaced string and the number of replaced occurences. For instance: ["my replaced string", 2] 130 # @return [Array] A destructurable array containing the replaced string and the number of replaced occurences. For instance: ["my replaced string", 2]
131 # 131 #
132 replaceAll: (str, replacement, limit = 0) -> 132 replaceAll: (str, replacement, limit = 0) ->
133 @regex.lastIndex = 0 133 @regex.lastIndex = 0
134 count = 0 134 count = 0
135 while @regex.test(str) and (limit is 0 or count < limit) 135 while @regex.test(str) and (limit is 0 or count < limit)
136 @regex.lastIndex = 0 136 @regex.lastIndex = 0
137 str = str.replace @regex, '' 137 str = str.replace @regex, replacement
138 count++ 138 count++
139 139
140 return [str, count] 140 return [str, count]
141   141  
142   142  
143 module.exports = Pattern 143 module.exports = Pattern
144   144  
145   145