regextest 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +3 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +25 -0
  7. data/README.md +88 -0
  8. data/Rakefile +55 -0
  9. data/bin/console +14 -0
  10. data/bin/regextest +4 -0
  11. data/bin/setup +7 -0
  12. data/contrib/Onigmo/RE.txt +522 -0
  13. data/contrib/Onigmo/UnicodeProps.txt +728 -0
  14. data/contrib/Onigmo/testpy.py +1319 -0
  15. data/contrib/unicode/Blocks.txt +298 -0
  16. data/contrib/unicode/CaseFolding.txt +1414 -0
  17. data/contrib/unicode/DerivedAge.txt +1538 -0
  18. data/contrib/unicode/DerivedCoreProperties.txt +11029 -0
  19. data/contrib/unicode/PropList.txt +1525 -0
  20. data/contrib/unicode/PropertyAliases.txt +193 -0
  21. data/contrib/unicode/PropertyValueAliases.txt +1420 -0
  22. data/contrib/unicode/README.txt +25 -0
  23. data/contrib/unicode/Scripts.txt +2539 -0
  24. data/contrib/unicode/UnicodeData.txt +29215 -0
  25. data/lib/pre-case-folding.rb +101 -0
  26. data/lib/pre-posix-char-class.rb +150 -0
  27. data/lib/pre-unicode.rb +116 -0
  28. data/lib/regextest.rb +268 -0
  29. data/lib/regextest/back.rb +58 -0
  30. data/lib/regextest/back/element.rb +151 -0
  31. data/lib/regextest/back/main.rb +356 -0
  32. data/lib/regextest/back/result.rb +498 -0
  33. data/lib/regextest/back/test-case.rb +268 -0
  34. data/lib/regextest/back/work-thread.rb +119 -0
  35. data/lib/regextest/common.rb +63 -0
  36. data/lib/regextest/front.rb +60 -0
  37. data/lib/regextest/front/anchor.rb +45 -0
  38. data/lib/regextest/front/back-refer.rb +120 -0
  39. data/lib/regextest/front/bracket-parser.rb +400 -0
  40. data/lib/regextest/front/bracket-parser.y +117 -0
  41. data/lib/regextest/front/bracket-scanner.rb +124 -0
  42. data/lib/regextest/front/bracket.rb +64 -0
  43. data/lib/regextest/front/builtin-functions.rb +31 -0
  44. data/lib/regextest/front/case-folding.rb +18 -0
  45. data/lib/regextest/front/char-class.rb +243 -0
  46. data/lib/regextest/front/empty.rb +43 -0
  47. data/lib/regextest/front/letter.rb +327 -0
  48. data/lib/regextest/front/manage-parentheses.rb +74 -0
  49. data/lib/regextest/front/parenthesis.rb +153 -0
  50. data/lib/regextest/front/parser.rb +1366 -0
  51. data/lib/regextest/front/parser.y +271 -0
  52. data/lib/regextest/front/range.rb +60 -0
  53. data/lib/regextest/front/repeat.rb +90 -0
  54. data/lib/regextest/front/repeatable.rb +77 -0
  55. data/lib/regextest/front/scanner.rb +187 -0
  56. data/lib/regextest/front/selectable.rb +65 -0
  57. data/lib/regextest/front/sequence.rb +73 -0
  58. data/lib/regextest/front/unicode.rb +1272 -0
  59. data/lib/regextest/regex-option.rb +144 -0
  60. data/lib/regextest/regexp.rb +44 -0
  61. data/lib/regextest/version.rb +5 -0
  62. data/lib/tst-reg-test.rb +159 -0
  63. data/regextest.gemspec +26 -0
  64. metadata +162 -0
@@ -0,0 +1,43 @@
1
+ # encoding: utf-8
2
+
3
+ # Copyright (C) 2016 Mikio Ikoma
4
+
5
+ require 'regextest/common'
6
+
7
+ # Empty part
8
+ module Regextest::Front::Empty
9
+ class TEmpty
10
+ include Regextest::Common
11
+ @@id = 0 # a class variable for generating unique name of element
12
+
13
+ # Constructor
14
+ def initialize
15
+ TstLog("Empty: ")
16
+ @offset = -1
17
+ @length = 0
18
+ end
19
+
20
+ attr_reader :offset, :length
21
+
22
+ # set options
23
+ def set_options(options)
24
+ TstLog("Empty set_options: #{options[:reg_options].inspect}");
25
+ # do nothing
26
+ self
27
+ end
28
+
29
+ # generate json format
30
+ def json
31
+ @@id += 1
32
+ "{" +
33
+ "\"type\": \"LEX_EMPTY\", \"id\": \"E#{@@id}\", \"value\": \"\", " +
34
+ "\"offset\": #{@offset}, \"length\": #{@length}" +
35
+ "}"
36
+ end
37
+ end
38
+ end
39
+
40
+ # Test suite (execute when this file is specified in command line)
41
+ if __FILE__ == $0
42
+ end
43
+
@@ -0,0 +1,327 @@
1
+ # encoding: utf-8
2
+
3
+ # Copyright (C) 2016 Mikio Ikoma
4
+
5
+ require 'regextest/common'
6
+ require 'regextest/front/char-class' # character class element
7
+ require 'regextest/front/range' # range of character point
8
+ require 'regextest/regex-option'
9
+ require 'regextest/front/unicode'
10
+
11
+ # A letter
12
+ module Regextest::Front::Letter
13
+ class TLetter
14
+ include Regextest::Common
15
+ include Regextest::Front::CharClass
16
+ include Regextest::Front::Range
17
+ @@id = 0 # a class variable for generating unique name of element
18
+ @@unicode_ranges = {}
19
+
20
+ # Constructor
21
+ def initialize(type, val)
22
+ TstLog("TLetter: type:#{type}, value:#{val}")
23
+ @options = nil
24
+ @data_type = type
25
+ @value = val[0] || ""
26
+ @offset = val[1] || -1
27
+ @length = val[2] || 0
28
+ @obj = nil
29
+ end
30
+
31
+ attr_reader :offset, :length, :value
32
+
33
+ # generate character(s) corresponding type of the character
34
+ def set_attr(type, val)
35
+ case type
36
+ when :LEX_CHAR, :LEX_SPACE
37
+ @data_type = :LEX_CHAR
38
+ @obj = CharClass.new([ TRange.new(val)])
39
+ when :LEX_SIMPLE_ESCAPE
40
+ @data_type = :LEX_CHAR
41
+ @obj = CharClass.new([ TRange.new(val[1..1])])
42
+ when :LEX_CODE_LITERAL, :LEX_ESCAPED_LETTER, :LEX_UNICODE, :LEX_CONTROL_LETTER, :LEX_META_LETTER, :LEX_OCTET
43
+ @data_type = :LEX_CHAR
44
+ @obj = CharClass.new([ TRange.new(eval('"'+ val + '"'))]) # convert using ruby's eval
45
+ when :LEX_BRACKET
46
+ @obj = Regextest::Front::Bracket.new(val)
47
+ when :LEX_SIMPLIFIED_CLASS
48
+ @obj = generate_simplified_class(val)
49
+ when :LEX_POSIX_CHAR_CLASS
50
+ @obj = generate_char_class(val)
51
+ when :LEX_UNICODE_CLASS
52
+ @obj = generate_unicode_char(val)
53
+ when :LEX_ANY_LETTER
54
+ @obj = generate_any_char(val)
55
+ when :LEX_SPECIAL_LETTER
56
+ @obj = generate_special_char(val)
57
+ when :LEX_AND_AND
58
+ raise "Internal error: enexpected LEX_AND_AND"
59
+ @obj = CharClass.new([TRange.new(val)])
60
+ else
61
+ raise "Error: internal error, type:#{type} not implemented"
62
+ end
63
+ end
64
+
65
+ # generate whole set of letters (depends on option)
66
+ def generate_any_char(val)
67
+ if @options[:reg_options].is_unicode?
68
+ obj = CharClass.new(TstConstUnicodeCharSet)
69
+ else
70
+ obj = CharClass.new( [ TRange.new("\x20", "\x7e") ] )
71
+ end
72
+
73
+ if( @options[:reg_options].is_multiline? )
74
+ obj.add_ranges( [ TRange.new("\n") ] )
75
+ end
76
+ obj
77
+ end
78
+
79
+ # generate special character class
80
+ def generate_special_char(val)
81
+ @data_type = :LEX_CHAR
82
+ obj = nil
83
+ case val
84
+ when "\\R"
85
+ if @options[:reg_options].is_unicode?
86
+ # BUG: "\x0a\x0d" must be supported!
87
+ obj = CharClass.new(
88
+ [ TRange.new("\x0a", "\x0d"), TRange.new("\u{85}"),
89
+ TRange.new("\u{2028}", "\u{2029}") ]
90
+ )
91
+ else
92
+ # BUG: "\x0a\x0d" must be supported!
93
+ obj = CharClass.new(
94
+ [ TRange.new("\x0a", "\x0d") ]
95
+ )
96
+ end
97
+ when "\\X"
98
+ if @options[:reg_options].is_unicode?
99
+ # BUG: (?>\P{M}\p{M}*)
100
+ obj = CharClass.new("M")
101
+ obj.set_reverse(@options)
102
+ else
103
+ obj = CharClass.new(
104
+ [ TRange.new("\x20", "\x7e"), TRange.new("\n") ]
105
+ )
106
+ end
107
+ else
108
+ raise "Error: internal error, invalid special char: #{val}"
109
+ end
110
+ obj
111
+ end
112
+
113
+ # generate simplified character class
114
+ def generate_simplified_class(val)
115
+ obj = nil
116
+ case val
117
+ when "\\w"
118
+ if @options[:reg_options].is_unicode?
119
+ obj = CharClass.new("Letter|Mark|Number|Connector_Punctuation")
120
+ else
121
+ obj = CharClass.new(
122
+ [ TRange.new('a', 'z'), TRange.new('A', 'Z'),
123
+ TRange.new('0', '9'), TRange.new('_') ]
124
+ )
125
+ end
126
+ when "\\W"
127
+ obj = CharClass.new(
128
+ [ TRange.new("\x20", "\x2f"), TRange.new("\x3a", "\x40"),
129
+ TRange.new("\x5b", "\x5e"), TRange.new("\x60"),
130
+ TRange.new("\x7b", "\x7e") ]
131
+ )
132
+ when "\\d"
133
+ if @options[:reg_options].is_unicode?
134
+ #obj = CharClass.new([ TRange.new('0', '9'), TRange.new('0', '9')])
135
+ obj = CharClass.new("Decimal_Number")
136
+ else
137
+ obj = CharClass.new(
138
+ [ TRange.new('0', '9') ]
139
+ )
140
+ end
141
+ when "\\D"
142
+ obj = CharClass.new(
143
+ [ TRange.new("\x20", "\x2f"), TRange.new("\x3a", "\x7e") ]
144
+ )
145
+ when "\\h"
146
+ obj = CharClass.new(
147
+ [ TRange.new('0', '9') , TRange.new('a', 'f'), TRange.new('A', 'F')]
148
+ )
149
+ when "\\H"
150
+ obj = CharClass.new(
151
+ [ TRange.new("\x20", "\x2f"), TRange.new("\x3a", "\x40"),
152
+ TRange.new("\x47", "\x60"), TRange.new("\x67", "\x7e")]
153
+ )
154
+ when "\\s"
155
+ ascii_ranges = [ TRange.new(' '), TRange.new("\x9", "\xd") ]
156
+ if @options[:reg_options].is_unicode?
157
+ obj = CharClass.new("Line_Separator|Paragraph_Separator|Space_Separator")
158
+ obj.add_ranges(ascii_ranges + [ TRange.new("\u{85}") ])
159
+ else
160
+ obj = CharClass.new(ascii_ranges)
161
+ end
162
+ when "\\S"
163
+ obj = CharClass.new(
164
+ [ TRange.new("\x21", "\x7e") ]
165
+ )
166
+ when "\\n", "\\r", "\\t", "\\f", "\\a", "\\e", "\\v"
167
+ obj = CharClass.new(
168
+ [ TRange.new(eval("\""+ string + "\"")) ]
169
+ )
170
+ when "\\b", "\\z", "\\A", "\\B", "\\G", "\\Z"
171
+ warn "Ignored unsupported escape char #{val}."
172
+ when "\\c", "\\x", "\\C", "\\M"
173
+ raise "Error: Unsupported escape char #{string}"
174
+ else
175
+ raise "Error: Invalid simplifiled class #{val}"
176
+ end
177
+ obj
178
+ end
179
+
180
+ # generate Unicode class (ie. \p{...} | \P{...})
181
+ def generate_unicode_char(val)
182
+ # Dynamic loading of Unicode regarding modules (for better performance).
183
+ # commented out since this code not executed at ruby 2.0.0
184
+ # require 'regextest/front/unicode'
185
+
186
+ if(md = val.match(/(p|P)\{(\^?)(\w+)\}/))
187
+ class_name = md[3].downcase
188
+ reverse = (md[2] && md[2]=="^")?true:false
189
+
190
+ # if not found at cache
191
+ if !@@unicode_ranges[class_name]
192
+ #work = Regextest::Front::Unicode.property(class_name) ||
193
+ # raise("Invalid Unicode class #{class_name} in #{val}")
194
+ # construct char class
195
+ #work = work.map{|elem| TRange.new(elem[0], elem[1])}
196
+ @@unicode_ranges[class_name] = CharClass.new(class_name)
197
+ end
198
+ else
199
+ raise "Internal error, inconsistent Unicode class #{val}"
200
+ end
201
+
202
+ # ¥P{^...} is equivalent to \p{...}
203
+ if((md[1] == "p" && !reverse) || (md[1] == "P" && reverse))
204
+ @@unicode_ranges[class_name]
205
+ else # \P{} or \p{^}
206
+ @@unicode_ranges[class_name].set_reverse(@options)
207
+ end
208
+ end
209
+
210
+ def classname_to_ranges(arrays)
211
+ end
212
+
213
+ # generate POSIX character class (ie. [[:alpha:]], etc.)
214
+ def generate_char_class(val)
215
+ if(md = val.match(/^\[\:(\^)?(\w+)\:\]$/))
216
+ reverse = (md[1] && md[1]=="^")?true:false
217
+ class_name = md[2]
218
+ else
219
+ raise "internal error, invalid POSIX class name(#{val})"
220
+ end
221
+
222
+ obj = nil
223
+ if @options[:reg_options].is_unicode?
224
+ obj = CharClass.new(class_name)
225
+ else
226
+ case class_name
227
+ when 'alnum'
228
+ obj = CharClass.new(
229
+ [ TRange.new('a', 'z'), TRange.new('A', 'Z'),
230
+ TRange.new('0', '9') ]
231
+ )
232
+ when 'alpha'
233
+ obj = CharClass.new(
234
+ [ TRange.new('a', 'z'), TRange.new('A', 'Z') ]
235
+ )
236
+ when 'cntrl'
237
+ obj = CharClass.new(
238
+ [ TRange.new("\x00", "\x1f"), TRange.new("\x7f") ]
239
+ )
240
+ when 'lower'
241
+ obj = CharClass.new(
242
+ [ TRange.new('a', 'z') ]
243
+ )
244
+ when 'print'
245
+ obj = CharClass.new(
246
+ [ TRange.new("\x20", "\x7e") ]
247
+ )
248
+ when 'space'
249
+ obj = CharClass.new(
250
+ [ TRange.new(' '), TRange.new("\n"), TRange.new("\r"),
251
+ TRange.new("\t"), TRange.new("\f"), TRange.new("\v") ]
252
+ )
253
+ when 'digit'
254
+ obj = CharClass.new(
255
+ [ TRange.new('0', '9') ]
256
+ )
257
+ when 'upper'
258
+ obj = CharClass.new(
259
+ [ TRange.new('A', 'Z') ]
260
+ )
261
+ when 'blank'
262
+ obj = CharClass.new(
263
+ [ TRange.new(' '), TRange.new("\t") ]
264
+ )
265
+ when 'graph'
266
+ obj = CharClass.new(
267
+ [ TRange.new("\x21", "\x7e") ]
268
+ )
269
+ when 'punct'
270
+ obj = CharClass.new(
271
+ [ TRange.new("\x21", "\x23"), TRange.new("\x25", "\x2a"),
272
+ TRange.new("\x2c", "\x2f"), TRange.new("\x3a", "\x3b"),
273
+ TRange.new("\x3f", "\x40"), TRange.new("\x5b", "\x5d"),
274
+ TRange.new("\x5f"), TRange.new("\x7b"), TRange.new("\x7d") ]
275
+ )
276
+ when 'xdigit'
277
+ obj = CharClass.new(
278
+ [ TRange.new('a', 'f'), TRange.new('A', 'F'),
279
+ TRange.new('0', '9') ]
280
+ )
281
+ when 'word'
282
+ obj = CharClass.new(
283
+ [ TRange.new('a', 'z'), TRange.new('A', 'Z'),
284
+ TRange.new('0', '9'), TRange.new('_') ]
285
+ )
286
+ else
287
+ raise "Error: Invalid character class #{val}"
288
+ end
289
+ end
290
+
291
+ if reverse
292
+ obj.set_reverse(@options)
293
+ end
294
+
295
+ obj
296
+ end
297
+
298
+ # enumerate codepoints
299
+ def enumerate
300
+ @obj.enumerate
301
+ end
302
+
303
+ # set options
304
+ def set_options(options)
305
+ TstLog("Letter set_options: #{options[:reg_options].inspect}")
306
+ @options = options
307
+ set_attr(@data_type, @value)
308
+ @obj.set_options(options)
309
+ self
310
+ end
311
+
312
+ # transform to json format
313
+ def json
314
+ @@id += 1
315
+ "{" +
316
+ "\"type\": \"#{@data_type}\", \"id\": \"L#{@@id}\", \"value\": #{@obj.json}, " +
317
+ "\"offset\": #{@offset}, \"length\": #{@length}" +
318
+ "}"
319
+ end
320
+ end
321
+ end
322
+
323
+
324
+ # Test suite (execute when this file is specified in command line)
325
+ if __FILE__ == $0
326
+ end
327
+
@@ -0,0 +1,74 @@
1
+ # encoding: utf-8
2
+
3
+ # Copyright (C) 2016 Mikio Ikoma
4
+
5
+ # A class for managing parentheses
6
+ class Regextest::Front::ManageParentheses
7
+ def initialize()
8
+ @paren_hash = {}
9
+ @paren_array = []
10
+ end
11
+
12
+ # register a parenthesis
13
+ def add(paren)
14
+ # register capturable parentheses
15
+ if(paren.prefix.length == 0 || # capture without prefix or
16
+ (paren.prefix[-1] != ':' && # other than (?: or (?i: or (?imx), etc.
17
+ !paren.prefix.match(/^([imx]*(?:\-[imx]+)?)$/) &&
18
+ !paren.prefix.match(/^[\=\!\>]|\<[\=\!]/)
19
+ )
20
+ )
21
+ @paren_array.push paren
22
+ end
23
+
24
+ # if name (ie. (?<foo>... ), register the name
25
+ if(paren.name)
26
+ @paren_hash[paren.name] = paren
27
+ end
28
+ paren
29
+ end
30
+
31
+ # sort of parentheses (since number of parenthesis not analyze order but offset order)
32
+ def sort
33
+ # pp @paren_array.map{|paren| paren.offset}
34
+ @paren_array.sort{|x, y| x.offset <=> y.offset}.each_with_index do | paren, i |
35
+ # puts "$$_#{i+1} offset:#{paren.offset}"
36
+ refer_name = "$$_#{i+1}"
37
+ @paren_hash[refer_name] = paren # parenthesis number from 1
38
+ paren.set_refer_name(refer_name)
39
+ end
40
+ end
41
+
42
+ # search target parenthesis
43
+ def get_paren(get_id, offset = nil)
44
+ if !offset
45
+ if(Integer === get_id)
46
+ @paren_hash["$$_#{get_id}"]
47
+ else
48
+ @paren_hash[get_id]
49
+ end
50
+ else
51
+ # puts "offset = #{offset}, id = #{get_id}"
52
+ target_id = @paren_array.size + 1
53
+ @paren_array.each_with_index do | paren, i |
54
+ # puts paren.offset
55
+ if paren.offset > offset
56
+ target_id = i + 1 # paren is started from 1
57
+ break
58
+ end
59
+ end
60
+ relative_offset = get_id.to_i
61
+ if relative_offset < 0
62
+ target_id += get_id.to_i
63
+ else
64
+ target_id += get_id.to_i - 1
65
+ end
66
+ @paren_hash["$$_#{target_id}"]
67
+ end
68
+ end
69
+ end
70
+
71
+ # Test suite (execute when this file is specified in command line)
72
+ if __FILE__ == $0
73
+ end
74
+
@@ -0,0 +1,153 @@
1
+ #encoding: utf-8
2
+
3
+ # Copyright (C) 2016 Mikio Ikoma
4
+
5
+ require 'regextest/common'
6
+ require 'regextest/front/empty' # parser class for empty part ("", (|) etc.)
7
+
8
+ # Class for parsing parenthesis
9
+ module Regextest::Front::Parenthesis
10
+
11
+ class Paren
12
+ include Regextest::Common
13
+ include Regextest::Front::Empty
14
+ @@id = 0 # a class variable for generating unique name of element
15
+
16
+ # Constructor
17
+ def initialize(paren_start, element = nil, paren_end = nil)
18
+ @options = @@parse_options
19
+ @paren_type = paren_start[0]
20
+ @offset = paren_start[1]
21
+ if paren_end
22
+ @length = (paren_end[1] - paren_start[1]) + paren_end[2]
23
+ else
24
+ @length = paren_start[2]
25
+ end
26
+
27
+ # delete head '(', '?', and tail ")"
28
+ @prefix = @paren_type.sub(/^\(\??/, "")
29
+ if @prefix.index("(") != 0
30
+ @prefix.sub!(/\)$/, "")
31
+ end
32
+
33
+ @name = get_name(@prefix)
34
+ @condition = nil # set at generating json
35
+ @refer_name = nil
36
+ if element
37
+ TstLog("Parenthesis: name:#{@name}, offset:#{@offset}, element:#{element}")
38
+ @element = element
39
+ @type_name = "LEX_PAREN"
40
+ else
41
+ TstLog("Parenthesis: name:#{@name}, offset:#{@offset}, element: \"\"")
42
+ @element = TEmpty.new
43
+ @type_name = "LEX_OPTION_PAREN" # (?x-i) etc.
44
+ end
45
+ @generated_string = []
46
+ @nest = 0
47
+ end
48
+
49
+ attr_reader :prefix, :name, :refer_name, :offset, :length
50
+
51
+ # get name of parenthesis (if any)
52
+ def get_name(prefix)
53
+ if(md = prefix.match(/^[<'](\w+)[>']$/))
54
+ md[1]
55
+ else
56
+ nil
57
+ end
58
+ end
59
+
60
+ # get condition of parenthesis
61
+ def get_condition(prefix)
62
+ # puts "prefix: #{prefix}"
63
+ if(md = prefix.match(/^\((\d+)\)$/))
64
+ condition_name = @options[:parens].get_paren(md[1].to_i)
65
+ if !condition_name
66
+ raise "condition number #{prefix} is invalid"
67
+ end
68
+ elsif(md = prefix.match(/^\(<(\w+)>\)|\('(\w+)'\)$/))
69
+ match_string = md[1] || md[2]
70
+ condition_name = @options[:parens].get_paren(match_string)
71
+ if !condition_name
72
+ raise "condition name (#{match_string}) is not found"
73
+ end
74
+ else
75
+ condition_name = nil
76
+ end
77
+
78
+ # check number of elements
79
+ if(condition_name)
80
+ if(Regextest::Front::Selectable::Selectable === @element)
81
+ if(@element.candidates.size > 2)
82
+ raise "invalid condition. 1 or 2 selectable elements"
83
+ end
84
+ end
85
+ end
86
+
87
+ condition_name
88
+ end
89
+
90
+ # set unique name for back reference
91
+ def set_refer_name(name)
92
+ @refer_name = name
93
+ end
94
+
95
+ # get generated string
96
+ def get_value(relative_num = 0)
97
+ # print "gen: "; pp @generated_string
98
+ if(@generated_string.size > 0)
99
+ @generated_string[-1]
100
+ else
101
+ warn "Error: refer uninitialized parenthesis"
102
+ nil
103
+ end
104
+ end
105
+
106
+ # set options
107
+ def set_options(options)
108
+ reg_options = options[:reg_options]
109
+ TstLog("Parenthesis set_options before: #{reg_options.inspect}, prefix: #{@prefix}");
110
+ if md = @prefix.match(/^([imxdau]*(?:\-[imx]*)?)(:)?$/)
111
+ if md[2]
112
+ # deep copy if (?imx: ) pattern
113
+ cur_options = reg_options.dup
114
+ else
115
+ # replace option if (?imx) pattern
116
+ cur_options = reg_options
117
+ end
118
+ cur_options.modify(md[1])
119
+ TstLog("Parenthesis set_options after: #{cur_options.inspect}, new_regopt: #{md[1]}");
120
+ else
121
+ cur_options = reg_options
122
+ end
123
+
124
+ new_options = options.dup
125
+ new_options[:reg_options] = cur_options
126
+
127
+ @element.set_options(new_options)
128
+ self
129
+ end
130
+
131
+ # transform to json format
132
+ def json
133
+ @@id += 1
134
+ @condition = get_condition(@prefix)
135
+ condition_name = @condition.refer_name if @condition
136
+ "{\"type\": \"#{@type_name}\"," +
137
+ " \"name\": \"#{@name}\"," +
138
+ " \"offset\": \"#{@offset}\"," +
139
+ " \"length\": \"#{@length}\"," +
140
+ " \"prefix\": \"#{@prefix}\"," +
141
+ " \"refer_name\": \"#{@refer_name}\"," +
142
+ " \"condition_name\": \"#{condition_name}\"," +
143
+ " \"id\": \"p#{@@id}\", " +
144
+ " \"value\": #{@element.json}" +
145
+ "}"
146
+ end
147
+ end
148
+ end
149
+
150
+ # Test suite (execute when this file is specified in command line)
151
+ if __FILE__ == $0
152
+ end
153
+