tokn 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 84933fe2966d19908c447c84cbccb9179c4e351d
4
- data.tar.gz: d1a6fae299cdd6c9b57961bfde7c879e1a786a48
3
+ metadata.gz: 84244706589683dd8fa77c96355a4494d6585561
4
+ data.tar.gz: cf5dcd362908eaad20371f9f62193000fc986d8b
5
5
  SHA512:
6
- metadata.gz: 022689701816eb3fb37690579b275194cbafc53d31591b7fb87d93a6cacafc50318dd964d28697ed1181ceb288d700214191cc41d6362cf4221e110e7c885531
7
- data.tar.gz: 96ee32c79d3e12ba8b01cd27fdfb9ff0bfc6ff518972358dc2fbac04f4c8842fccd6f8722c994daba299327718915074f853cc3c9125c0e22dffe3ef19fd189d
6
+ metadata.gz: c2a6659f5c4819088ff95dda3a48b42b2a7deb7dcd46f01149b45121bff298778850e42597e63a3cd8ec5bcc94f9aba41c90b914c2b5d88f6cf13ad9d64dd4cf
7
+ data.tar.gz: 059e6c6601c8e35aa7f7e465fd408dc227a23e899458962592a12bdd4bcc9004bb802bf0ca4e580e8502c6a2ba2ebe4ea8e23705903198efd431e30833783cb6
@@ -16,4 +16,5 @@
16
16
  * Version 0.1.0
17
17
  * Cleaned up test directory
18
18
 
19
-
19
+ 2013-04-15
20
+ * No longer maintaining CHANGELOG.txt; see git commit comments instead.
@@ -20,7 +20,7 @@ module Tokn
20
20
  def self.from_script(script, persistPath = nil)
21
21
 
22
22
  if persistPath and File.exist?(persistPath)
23
- return extractDFA(readTextFile(persistPath))
23
+ return extractDFA(read_text_file(persistPath))
24
24
  end
25
25
 
26
26
  req('token_defn_parser')
@@ -29,7 +29,7 @@ module Tokn
29
29
  dfa = td.dfa
30
30
 
31
31
  if persistPath
32
- writeTextFile(persistPath, dfa.serialize())
32
+ write_text_file(persistPath, dfa.serialize())
33
33
  end
34
34
 
35
35
  dfa
@@ -39,14 +39,14 @@ module Tokn
39
39
  # the file at scriptPath.
40
40
  #
41
41
  def self.from_script_file(scriptPath, persistPath = nil)
42
- self.from_script(readTextFile(scriptPath), persistPath)
42
+ self.from_script(read_text_file(scriptPath), persistPath)
43
43
  end
44
44
 
45
45
  # Compile a Tokenizer DFA from a text file (that contains a
46
46
  # JSON string)
47
47
  #
48
48
  def self.from_file(path)
49
- from_json(readTextFile(path))
49
+ from_json(read_text_file(path))
50
50
  end
51
51
 
52
52
  # Compile a Tokenizer DFA from a JSON string
@@ -32,3 +32,18 @@ module ToknInternal
32
32
  EPSILON-1-edgeLabel
33
33
  end
34
34
  end
35
+
36
+ # Convert a .dot file (string) to a PDF file "__mygraph__nnn.pdf"
37
+ #
38
+ # It does this by making a system call to the 'dot' utility.
39
+ #
40
+ def dotToPDF(dotFile, name = "", test_dir = nil)
41
+ gr = dotFile
42
+
43
+ raise ArgumentError if !test_dir
44
+
45
+ dotPath = File.join(test_dir,".__mygraph__.dot")
46
+ write_text_file(dotPath,gr)
47
+ destName = File.join(test_dir,"__mygraph__"+name+".pdf")
48
+ system("dot -Tpdf "+dotPath+" -o "+destName)
49
+ end
@@ -1,13 +1,31 @@
1
1
  require 'set'
2
2
  require 'fileutils'
3
3
 
4
+ ###############################################################
5
+ #
4
6
  # Various utility and debug convenience functions.
5
7
  #
8
+ ###############################################################
6
9
 
7
- # Perform 'require_relative' on a set of files
10
+ # Exception class for objects in illegal states
8
11
  #
9
- # fileListStr : space-delimited file/path items, without .rb extensions
10
- # subdir : optional path to files relative to tools.rb
12
+ class IllegalStateException < Exception
13
+ end
14
+
15
+ # A string containing a single zero, with ASCII 8-bit encoding (i.e., plain old bytes)
16
+ ZERO_CHAR = "\0".force_encoding("ASCII-8BIT")
17
+
18
+ # Construct a string of zeros
19
+ # @param count number of zeros
20
+ #
21
+ def zero_bytes(count)
22
+ ZERO_CHAR * count
23
+ end
24
+
25
+ # Convenience method to perform 'require_relative' on a set of files
26
+ #
27
+ # @param fileListStr space-delimited file/path items, without .rb extensions
28
+ # @param subdir optional path to files relative to this file
11
29
  #
12
30
  def req(fileListStr,subdir = nil)
13
31
  fileListStr.split(' ').each do |x|
@@ -21,67 +39,114 @@ end
21
39
 
22
40
  # Shorthand for printf(...)
23
41
  #
24
- def pr(*args)
25
- printf(*args)
42
+ alias :pr :printf
43
+
44
+ # Convert an object to a human-readable string,
45
+ # or <nil>; should be considered a debug-only feature
46
+ #
47
+ def d(arg)
48
+ arg.nil? ? "<nil>" : arg.inspect
26
49
  end
27
50
 
51
+ # Convert an object to a human-readable string,
52
+ # by calling a type-appropriate function: da, dh, or just d.
53
+ # @param arg object
54
+ # @param indent optional indentation for pretty printing; if result
55
+ # spans multiple lines, each line should be indented by this amount
56
+ #
57
+ def d2(arg, indent = 0)
58
+ return da(arg, indent) if arg.is_a? Array
59
+ return dh(arg, indent) if arg.is_a? Hash
60
+ return df(arg) if arg.class == FalseClass || arg.class == TrueClass
61
+ return d(arg)
62
+ end
28
63
 
29
- # Convert an object to a human-readable string;
30
- # should be considered a debug-only feature
64
+ # Convert an object to a human-readable string, prefixed with its type
31
65
  #
32
- def d(arg)
33
- arg.nil? ? "<nil>" : arg.inspect
66
+ def dt(arg)
67
+ if arg.nil?
68
+ return "<nil>"
69
+ end
70
+ s = arg.class.to_s
71
+ s << ':'
72
+ s << arg.inspect
73
+ s
74
+ end
75
+
76
+ # Append a particular number of spaces to a string
77
+ def add_sp(s, indent = 0)
78
+ s << ' ' * indent
79
+ end
80
+
81
+ # Pretty-print an array,
82
+ # one element to a line
83
+ # @param indent indentation of each line, in spaces
84
+ def da(array, indent = 0)
85
+ return d(array) if !array
86
+ s = 'Array ['
87
+ indent += 2
88
+ array.each do |x|
89
+ s << "\n"
90
+ add_sp(s,indent)
91
+ s2 = d2(x, indent + 2)
92
+ s << s2
93
+ end
94
+ s << " ]"
95
+ s
96
+ end
97
+
98
+ # Pretty-print a hash,
99
+ # one element to a line
100
+ # @param indent indentation of each line, in spaces
101
+ def dh(hash, indent = 0)
102
+ return d(hash) if !hash
103
+ s = 'Hash {'
104
+ indent += 2
105
+ hash.each_pair do |key,val|
106
+ s2 = d(key)
107
+ s3 = d2(val, indent + 4)
108
+ s << "\n "
109
+ add_sp(s,indent)
110
+ s << s2.chomp << " => " << s3.chomp
111
+ end
112
+ s << " }"
113
+ s
114
+ end
115
+
116
+ # Generate debug description of a boolean value
117
+ # @param flag value to interpret as a boolean; prints 'T' iff not nil
118
+ # @param label optional label
119
+ def df(flag, label=nil)
120
+ s = ''
121
+ if label
122
+ s << label << ':'
123
+ end
124
+ s << (flag ? "T" : "F")
125
+ s << ' '
126
+ s
34
127
  end
35
128
 
36
129
  # Assert that a value is true. Should be considered a
37
130
  # very temporary, debug-only option; it is slow and
38
131
  # generates a warning that it is being called.
39
- #
40
- def myAssert(cond, *msg)
41
- oneTimeAlert("warning",0,"Checking assertion")
132
+ # @param cond condition
133
+ # @param msg generates additional message using printf(), if these arguments exist
134
+ def assert!(cond, *msg)
135
+ one_time_alert("warning",0,"Checking assertion")
42
136
  if not cond
43
137
  str = (msg.size == 0) ? "assertion error" : sprintf(*msg)
44
138
  raise Exception, str
45
139
  end
46
140
  end
47
141
 
48
-
49
- ## Set test directory. If nil, sets to home directory + "__test__"
50
- ##
51
- #def setTestDir(d = nil)
52
- # $testDir = d || File.join(Dir.home,"__test__")
53
- #end
54
-
55
- ## Get a path within the test directory;
56
- ## create test directory if it doesn't exist.
57
- ##
58
- ## relPath : if nil, returns the test directory; else
59
- ## returns the test directory joined to this one
60
- ##
61
- #def withinTestDir(relPath = nil)
62
- # if !$testDir
63
- # raise IllegalStateException, "No test directory has been defined"
64
- # end
65
- # if !File.directory?($testDir)
66
- # Dir::mkdir($testDir)
67
- # end
68
- # relPath ? File.join($testDir,relPath) : $testDir
69
- #end
70
-
71
- # Convert a .dot file (string) to a PDF file "__mygraph__nnn.pdf"
72
- # in the test directory.
73
- #
74
- # It does this by making a system call to the 'dot' utility.
142
+ # Abort with message about unimplemented code
75
143
  #
76
- def dotToPDF(dotFile, name = "", test_dir = nil)
77
- gr = dotFile
78
-
79
- raise ArgumentError if !test_dir
80
-
81
- dotPath = File.join(test_dir,".__mygraph__.dot")
82
- writeTextFile(dotPath,gr)
83
- destName = File.join(test_dir,"__mygraph__"+name+".pdf")
84
- system("dot -Tpdf "+dotPath+" -o "+destName)
144
+ def unimp!(msg = nil)
145
+ msg2 = "Unimplemented code"
146
+ if msg
147
+ msg2 << ": " << msg
148
+ end
149
+ raise Exception, msg2
85
150
  end
86
151
 
87
152
  # Extensions to the Enumerable module
@@ -106,13 +171,12 @@ module Enumerable
106
171
  end
107
172
  end
108
173
 
109
-
110
174
  # Get a nice, concise description of the file and line
111
175
  # of some caller within the stack.
112
176
  #
113
- # nSkip : the number of items deep in the call stack to look
177
+ # @param nSkip the number of items deep in the call stack to look
114
178
  #
115
- def getCallerLocation(nSkip = 2)
179
+ def get_caller_location(nSkip = 2)
116
180
 
117
181
  filename = nil
118
182
  linenumber = nil
@@ -130,11 +194,11 @@ def getCallerLocation(nSkip = 2)
130
194
  if pth.size
131
195
  filename = pth[-1]
132
196
  end
133
- linenumber = fi[i+1,j-i-1].to_i
197
+ linenumber = fi[i+1,j-i-1]
134
198
  end
135
199
  end
136
200
  if filename && linenumber
137
- loc = filename + " ("+linenumber.to_s+")"
201
+ loc = filename + " ("+linenumber+")"
138
202
  else
139
203
  loc = "(UNKNOWN LOCATION)"
140
204
  end
@@ -149,12 +213,12 @@ $AlertStrings = Set.new
149
213
  # Print a message if it hasn't yet been printed,
150
214
  # which includes the caller's location
151
215
  #
152
- # > typeString : e.g., "warning", "unimplemented"
153
- # > nSkip : the number of levels deep that the caller is in the stack
154
- # > args : if present, calls sprintf(...) with these to append to the message
216
+ # @param typeString e.g., "warning", "unimplemented"
217
+ # @param nSkip the number of levels deep that the caller is in the stack
218
+ # @param args if present, calls sprintf(...) with these to append to the message
155
219
  #
156
- def oneTimeAlert(typeString, nSkip, *args)
157
- loc = getCallerLocation(nSkip + 2)
220
+ def one_time_alert(typeString, nSkip, *args)
221
+ loc = get_caller_location(nSkip + 2)
158
222
  s = "*** "+typeString+" " + loc
159
223
  if args && args.size
160
224
  s2 = sprintf(args[0], *args[1..-1])
@@ -169,33 +233,160 @@ def oneTimeAlert(typeString, nSkip, *args)
169
233
  end
170
234
 
171
235
  # Print a 'warning' alert, one time only
172
- #
236
+ # @param args if present, calls printf() with these
173
237
  def warn(*args)
174
- oneTimeAlert("warning",0, *args)
238
+ one_time_alert("warning",0, *args)
239
+ end
240
+
241
+ # Convenience method for setting 'db' true within methods,
242
+ # and to print a one-time warning if so.
243
+ # @param val value to set db to; it is convenient to disable
244
+ # debug printing quickly by adding a zero, e.g., 'warndb 0'
245
+ #
246
+ def warndb(val = true)
247
+ if !val || val == 0
248
+ return false
249
+ end
250
+ one_time_alert("warning",1,"Debug printing enabled")
251
+ true
175
252
  end
176
253
 
177
254
  # Print an 'unimplemented' alert, one time only
178
- #
255
+ # @param args if present, calls printf() with these
179
256
  def unimp(*args)
180
- oneTimeAlert("unimplemented", 0, *args)
257
+ one_time_alert("unimplemented", 0, *args)
181
258
  end
182
259
 
183
260
  # Write a string to a text file
184
261
  #
185
- def writeTextFile(path, contents)
262
+ def write_text_file(path, contents)
186
263
  File.open(path, "wb") {|f| f.write(contents) }
187
264
  end
188
265
 
189
266
  # Read a file's contents, return as a string
190
267
  #
191
- def readTextFile(path)
268
+ def read_text_file(path)
192
269
  contents = nil
193
270
  File.open(path,"rb") {|f| contents = f.read }
194
271
  contents
195
272
  end
196
273
 
274
+ # Method that takes a code block as an argument to
275
+ # achieve the same functionality as Java/C++'s
276
+ # do {
277
+ # ...
278
+ # ... possibly with 'break' to jump to the end ...
279
+ # } while (false);
280
+ #
281
+ def block
282
+ yield
283
+ end
284
+
285
+ # Construct hex representation of value
286
+ # @param value integer value
287
+ # @param num_digits number of hex digits
288
+ #
289
+ def to_hex(value, num_digits=4)
290
+ s = sprintf("%x", value)
291
+ s.rjust(num_digits,'0')
292
+ end
293
+
294
+ # Hex dump a string or byte array
295
+ # @param byte_array_or_string
296
+ # @param title
297
+ # @param offset offset to first value within array
298
+ # @param length number of values to dump
299
+ # @param bytes_per_row
300
+ # @param with_text if true, displays ASCII values to right of hex dump
301
+ #
302
+ def hex_dump(byte_array_or_string, title=nil, offset=0, length= -1, bytes_per_row=16, with_text=true)
303
+ ss = hex_dump_to_string(byte_array_or_string, title, offset, length, bytes_per_row, with_text)
304
+ puts ss
305
+ end
306
+
307
+ # Hex dump a string or byte array to a string; see hex_dump for parameter descriptions
308
+ #
309
+ def hex_dump_to_string(byte_array_or_string, title=nil, offset=0, length= -1, bytes_per_row=16, with_text=true)
310
+
311
+ byte_array = byte_array_or_string
312
+ if byte_array.is_a? String
313
+ byte_array = byte_array.bytes.to_a
314
+ end
315
+
316
+ ss = ''
317
+
318
+ if title
319
+ ss << title << ":\n"
320
+ end
321
+
322
+ if length < 0
323
+ length = byte_array.size - offset
324
+ end
325
+
326
+ length = [length, byte_array.size - offset].min
327
+
328
+ max_addr = offset + length - 1
329
+ num_digits = 4
330
+ while (1 << (4 * num_digits)) <= max_addr
331
+ num_digits += 1
332
+ end
333
+
334
+ while true
335
+ ss << to_hex(offset, num_digits)
336
+ ss << ': '
337
+
338
+ chunk = [length, bytes_per_row].min
339
+ bytes_per_row.times do |i|
340
+ if i % 4 == 0
341
+ ss << ' '
342
+ end
343
+
344
+ if i < chunk
345
+ v = byte_array[offset + i]
346
+ ss << ((v != 0) ? to_hex(v,2) : '..')
347
+ ss << ' '
348
+ else
349
+ ss << ' '
350
+ end
351
+ end
352
+
353
+ if with_text
354
+ ss << ' |'
355
+ bytes_per_row.times do |i|
356
+ if i < chunk
357
+ v = byte_array[offset + i]
358
+ ss << ((v >= 32 && v < 127) ? v : '_')
359
+ end
360
+ end
361
+ ss << '|'
362
+ end
363
+ ss << "\n"
364
+
365
+ length -= chunk
366
+ offset += chunk
367
+ break if length <= 0
368
+ end
369
+ ss
370
+ end
371
+
372
+ $prevTime = nil
373
+
374
+ # Calculate time elapsed, in seconds, from last call to this function;
375
+ # if it's never been called, returns zero
376
+ #
377
+ def elapsed
378
+ curr = Time.now.to_f
379
+ elap = 0
380
+ if $prevTime
381
+ elap = curr - $prevTime
382
+ end
383
+ $prevTime = curr
384
+ elap
385
+ end
386
+
197
387
  # Delete a file or directory, if it exists.
198
388
  # Caution! If directory, deletes all files and subdirectories.
389
+ #
199
390
  def remove_file_or_dir(pth)
200
391
  if File.directory?(pth)
201
392
  FileUtils.remove_dir(pth)
@@ -204,22 +395,96 @@ def remove_file_or_dir(pth)
204
395
  end
205
396
  end
206
397
 
207
- # Method that takes a code block as an argument to
208
- # achieve the same functionality as Java/C++'s
209
- # do {
210
- # ...
211
- # ... possibly with 'break' to jump to the end ...
212
- # } while (false);
398
+ require 'stringio'
399
+
400
+ $IODest = nil
401
+ $OldStdOut = nil
402
+
403
+ # Redirect standard output to an internal string
213
404
  #
214
- def block
215
- yield
405
+ def capture_begin
406
+ raise IllegalStateException if $IODest
407
+ $IODest = StringIO.new
408
+ $OldStdOut, $stdout = $stdout, $IODest
216
409
  end
217
410
 
218
- # Exception class for objects in illegal states
411
+ # Restore standard output; return captured text
412
+ # @return text that was redirected
219
413
  #
220
- class IllegalStateException < Exception
414
+ def capture_end
415
+ raise IllegalStateException if !$IODest
416
+ $stdout = $OldStdOut
417
+ ret = $IODest.string
418
+ $IODest = nil
419
+ ret
420
+ end
421
+
422
+ # Compare a string with disk file; abort if different. Disk filename is derived
423
+ # from caller function name; e.g., test_xxx produces filename _output_xxx
424
+ #
425
+ # @param str if not nil, string to compare; if nil, calls capture_end to get string
426
+ #
427
+ def match_expected_output(str = nil)
428
+
429
+ if !str
430
+ str = capture_end
431
+ end
432
+
433
+ cl_method = caller[0][/`.*'/][1..-2]
434
+ if (cl_method.start_with?("test_"))
435
+ cl_method = cl_method[5..-1]
436
+ end
437
+ path = "_output_" + cl_method + ".txt"
438
+
439
+ if !File.file?(path)
440
+ printf("no such file #{path} exists, writing it...\n")
441
+ write_text_file(path,str)
442
+ else
443
+ exp_cont = read_text_file(path)
444
+ if str != exp_cont
445
+ d1 = str
446
+ d2 = exp_cont
447
+
448
+ # Find location where they differ
449
+ lines1 = d1.split("\n")
450
+ lines2 = d2.split("\n")
451
+ j = [lines1.size, lines2.size].max
452
+
453
+ s = "???"
454
+ found_diff = false
455
+ hist = []
456
+
457
+ found_count = 0
458
+ j.times do |i|
459
+ found_diff ||= (i >= lines1.size || i >= lines2.size || lines1[i] != lines2[i])
460
+ s = sprintf("%3d:",i)
461
+ if !found_diff
462
+ hist << "#{s} #{lines1[i]}\n #{lines2[i]}\n"
463
+ else
464
+ if found_count < 3
465
+ if i < lines1.size
466
+ s << " #{lines1[i]}\n"
467
+ else
468
+ s << " ---END---\n"
469
+ end
470
+ if i < lines2.size
471
+ s << " #{lines2[i]}\n"
472
+ else
473
+ s << " ---END---\n"
474
+ end
475
+ hist << s
476
+ end
477
+ found_count += 1
478
+ end
479
+ while hist.size > 6
480
+ hist.shift
481
+ end
482
+ end
483
+ dash = "-" * 95 + "\n"
484
+ raise IllegalStateException,"output did not match expected:\n#{dash}#{hist.join('')}#{dash}"
485
+ end
486
+ end
221
487
  end
222
-
223
488
 
224
489
  # Convenience method to detect if a script is being run
225
490
  # e.g. as a 'main' method (for debug purposes only).
@@ -328,14 +593,6 @@ if defined? Test::Unit
328
593
  method_setup
329
594
  end
330
595
 
331
- def out_dir
332
- "_output_"
333
- end
334
-
335
- def out_path(f)
336
- File.join(out_dir,f)
337
- end
338
-
339
596
  def teardown
340
597
  if _suite_active?
341
598
  if !defined? @@suiteSetup
@@ -360,3 +617,136 @@ if defined? Test::Unit
360
617
  end
361
618
  end
362
619
 
620
+ # Construct a string from an array of bytes
621
+ # @param byte_array array of bytes, or string (in which case it
622
+ # returns it unchanged)
623
+ #
624
+ def bytes_to_str(byte_array)
625
+ return byte_array if byte_array.is_a? String
626
+
627
+ byte_array.pack('C*')
628
+ end
629
+
630
+ # Construct an array of bytes from a string
631
+ # @param str string, or array of bytes (in which case it
632
+ # returns it unchanged)
633
+ #
634
+ def str_to_bytes(str)
635
+ return str if str.is_a? Array
636
+ str.bytes
637
+ end
638
+
639
+ # Get directory entries, excluding '.' and '..'
640
+ #
641
+ def dir_entries(path)
642
+ ents = Dir.entries(path)
643
+ ents.reject!{|entry| entry == '.' || entry == '..'}
644
+ end
645
+
646
+ def int_to_bytes(x)
647
+ [(x >> 24) & 0xff, (x >> 16) & 0xff, (x >> 8) & 0xff, x & 0xff]
648
+ end
649
+
650
+ def short_to_bytes(x)
651
+ [(x >> 8) & 0xff, x & 0xff]
652
+ end
653
+
654
+ # Decode a short from an array of bytes (big-endian).
655
+ # @param ba array of bytes
656
+ # @param offset offset of first (most significant) byte
657
+ #
658
+ def short_from_bytes(ba, offset=0)
659
+ (ba[offset] << 8) | ba[offset + 1]
660
+ end
661
+
662
+ # Decode an int from an array of bytes (big-endian).
663
+ # @param ba array of bytes
664
+ # @param offset offset of first (most significant) byte
665
+ #
666
+ def int_from_bytes(ba, offset=0)
667
+ (((((ba[offset] << 8) | ba[offset + 1]) << 8) | \
668
+ ba[offset + 2]) << 8) | ba[offset + 3]
669
+ end
670
+
671
+ # Transform string to 8-bit ASCII (i.e., just treat each byte as-is)
672
+ #
673
+ def to_ascii8(str)
674
+ str.force_encoding("ASCII-8BIT")
675
+ end
676
+
677
+ # Verify that a string is encoded as ASCII-8BIT
678
+ def simple_str(s)
679
+ if s.encoding.name != 'ASCII-8BIT' && s.encoding.name != 'UTF-8'
680
+ pr("string [%s]\n encoding is %s,\n expected ASCII-8BIT\n",s,s.encoding.name)
681
+ assert!(false)
682
+ end
683
+ end
684
+
685
+ # Truncate or pad string so it has a particular size
686
+ #
687
+ # @param s input string
688
+ # @param size
689
+ # @param pad padding character to use if string needs to grow
690
+ # @return modified string
691
+ #
692
+ def str_sized(s, size, pad="\0")
693
+ s[0...size].ljust(size,pad)
694
+ end
695
+
696
+ # Determine if running on the Windows operating system.
697
+ # Note: there is some debate about the best way to do this.
698
+ #
699
+ def windows?
700
+ if !defined? $__windows__
701
+ $__windows__ = (RUBY_PLATFORM =~ /mswin/)
702
+ end
703
+ $__windows__
704
+ end
705
+
706
+ # Mark all constants ending with '_' as private constants
707
+ #
708
+ # @param entity the class to examine
709
+ # @param add_non_suffix_versions if true, for each constant ABC_ found, also
710
+ # defines a constant ABC with the same value that is also private
711
+ #
712
+ def privatize(entity, add_non_suffix_versions = false)
713
+
714
+ db = false
715
+
716
+ # First command defines constants ABC = n for each constant ABC_ = n;
717
+ # Second declares both versions to be private
718
+
719
+ cmd1 = nil
720
+ cmd2 = nil
721
+
722
+ entity.constants.each do |c|
723
+ nm = c.to_s
724
+
725
+ if nm.end_with?('_')
726
+ nm_small = nm[0..-2]
727
+
728
+ if !cmd2
729
+ if add_non_suffix_versions
730
+ cmd1 = ''
731
+ end
732
+ cmd2 = 'private_constant '
733
+ else
734
+ cmd2 << ','
735
+ end
736
+
737
+
738
+ !cmd1 || cmd1 << entity.to_s << '::' << nm_small << '=' << entity.const_get(c).to_s << "\n"
739
+ !cmd1 || cmd2 << ':' << nm_small << ','
740
+ cmd2 << ':' << nm
741
+ end
742
+ end
743
+
744
+ if cmd2
745
+ if cmd1
746
+ !db || pr("about to eval:\n%s\n",cmd1)
747
+ eval(cmd1)
748
+ end
749
+ !db || pr("about to eval:\n%s\n",cmd2)
750
+ eval(cmd2)
751
+ end
752
+ end
@@ -0,0 +1 @@
1
+ {"version":1.0,"tokens":["WS","DBL","INT","LBL","ID","ASSIGN","EQUIV","IF","DO","BROP","BRCL"],"states":[[false,[[[125,126],1],[[123,124],2],[[100,101],3],[[105,106],4],[[61,62],5],[[65,91,95,96,97,100,101,105,106,123],6],[[39,40],7],[[48,58],8],[[45,46],9],[[46,47],10],[[9,11,12,13,32,33,92,93],11],[[47,48],12]]],[false,[[[-12,-11],14]]],[false,[[[-11,-10],14]]],[false,[[[48,58,65,91,95,96,97,111,112,123],6],[[-6,-5],14],[[111,112],22]]],[false,[[[48,58,65,91,95,96,97,102,103,123],6],[[-6,-5],14],[[102,103],21]]],[false,[[[-7,-6],14],[[61,62],20]]],[false,[[[48,58,65,91,95,96,97,123],6],[[-6,-5],14]]],[false,[[[0,10,11,39,40,92,93,1114112],7],[[39,40],17],[[92,93],18]]],[false,[[[48,58],8],[[46,47],10],[[-4,-3],14]]],[false,[[[48,58],8],[[46,47],10]]],[false,[[[48,58],16]]],[false,[[[9,11,12,13,32,33,92,93],11],[[-2,-1],14]]],[false,[[[47,48],13]]],[false,[[[0,10,11,1114112],13],[[-2,-1],14],[[10,11],15]]],[true,[]],[false,[[[-2,-1],14]]],[false,[[[-3,-2],14],[[48,58],16]]],[false,[[[-5,-4],14]]],[false,[[[0,10,11,39,40,92,93,1114112],7],[[92,93],18],[[39,40],19]]],[false,[[[0,10,11,39,40,92,93,1114112],7],[[-5,-4],14],[[39,40],17],[[92,93],18]]],[false,[[[-8,-7],14]]],[false,[[[48,58,65,91,95,96,97,123],6],[[-9,-8],14]]],[false,[[[48,58,65,91,95,96,97,123],6],[[-10,-9],14]]]]}
@@ -0,0 +1,26 @@
1
+ (line 1, col 1) : speed
2
+ (line 1, col 6) : =
3
+ (line 1, col 7) : 42
4
+ (line 1, col 9) : gravity
5
+ (line 1, col 16) : =
6
+ (line 1, col 17) : -9.80
7
+ ...couldn't find sequence...
8
+ (line 1, col 22) : {
9
+ (line 1, col 23) : color
10
+ (line 1, col 29) : =
11
+ (line 1, col 30) : green
12
+ (line 1, col 35) : }
13
+ (line 1, col 36) : title
14
+ (line 1, col 41) : =
15
+ (line 1, col 42) : 'This is a string with \' an escaped delimiter'
16
+ (line 1, col 89) : if
17
+ (line 1, col 91) : gravity
18
+ (line 1, col 98) : ==
19
+ (line 1, col 100) : 12
20
+ ...read BROP DO ID sequence...
21
+ (line 1, col 102) : {
22
+ (line 1, col 103) : do
23
+ (line 1, col 105) : something
24
+ (line 1, col 114) : }
25
+ (line 1, col 115) : do
26
+ (line 1, col 117) : something_else
@@ -3,11 +3,8 @@ require 'test/unit'
3
3
  require_relative '../lib/tokn/tools.rb'
4
4
  req('range_partition dfa dfa_builder tokenizer token_defn_parser')
5
5
 
6
- # Get access to Tokn namespace
6
+ #SINGLETEST = "test_100_add"
7
7
 
8
- #setTestDir()
9
-
10
- #SINGLETEST = "test_ps_output_multi"
11
8
  if defined? SINGLETEST
12
9
  if main?(__FILE__)
13
10
  ARGV.concat("-n #{SINGLETEST}".split)
@@ -18,29 +15,27 @@ class TestTokn < MyTestSuite
18
15
 
19
16
  include Tokn, ToknInternal
20
17
 
21
- # def data_file(f)
22
- # File.join("data",f)
23
- # # File.dirname(__FILE__)+"/data/"+f
24
- # end
25
-
26
18
  def suite_setup
27
-
19
+
28
20
  # Make current directory = the one containing this script
29
21
  main?(__FILE__)
30
22
 
31
- if !File.directory?(out_dir)
32
- Dir.mkdir(out_dir)
23
+ @@out_dir = File.absolute_path(File.join(Dir.pwd,"_misc_"))
24
+
25
+ if !File.directory?(@@out_dir)
26
+ Dir.mkdir(@@out_dir)
33
27
  end
34
28
 
35
- @@sampleText = readTextFile("sampletext.txt")
36
- @@sampleTokens = readTextFile("sampletokens.txt")
29
+ @@sampleText = read_text_file("sampletext.txt")
30
+ @@sampleTokens = read_text_file("sampletokens.txt")
37
31
  end
38
32
 
39
- # def withinTestDir(f)
40
- # File.join(@@testDir,"__source__")
41
-
33
+ def out_path(f)
34
+ File.join(@@out_dir,f)
35
+ end
36
+
42
37
  def suite_teardown
43
- remove_file_or_dir(out_dir)
38
+ # remove_file_or_dir(@@out_dir)
44
39
  end
45
40
 
46
41
  def method_setup
@@ -332,7 +327,7 @@ class TestTokn < MyTestSuite
332
327
  addset(40,50)
333
328
  @par.prepare
334
329
 
335
- @par.generatePDF(out_dir)
330
+ @par.generatePDF(@@out_dir)
336
331
 
337
332
  prep
338
333
  add 25,33
@@ -367,13 +362,13 @@ END
367
362
  s = x.startState
368
363
  x.endState.finalState = true
369
364
 
370
- s.generatePDF(out_dir,"nfa")
365
+ s.generatePDF(@@out_dir,"nfa")
371
366
 
372
367
  r = s.reverseNFA()
373
- r.generatePDF(out_dir,"reversed")
368
+ r.generatePDF(@@out_dir,"reversed")
374
369
 
375
370
  dfa = DFABuilder.nfa_to_dfa(s)
376
- dfa.generatePDF(out_dir,"buildDFA")
371
+ dfa.generatePDF(@@out_dir,"buildDFA")
377
372
  end
378
373
 
379
374
  def test_180_cvt_NFA_to_DFA
@@ -382,14 +377,14 @@ END
382
377
  s = x.startState
383
378
  x.endState.finalState = true
384
379
 
385
- s.generatePDF(out_dir,"nfa")
380
+ s.generatePDF(@@out_dir,"nfa")
386
381
 
387
382
  dfa = DFABuilder.nfa_to_dfa(s)
388
- dfa.generatePDF(out_dir,"dfa")
383
+ dfa.generatePDF(@@out_dir,"dfa")
389
384
 
390
385
  oldToNewMap, maxId2 = dfa.duplicateNFA(42)
391
386
  dfa2 = oldToNewMap[dfa]
392
- dfa2.generatePDF(out_dir,"dfa_duplicated")
387
+ dfa2.generatePDF(@@out_dir,"dfa_duplicated")
393
388
  end
394
389
 
395
390
  def test_190_TokenDefParser
@@ -399,7 +394,7 @@ END
399
394
  td = TokenDefParser.new(s)
400
395
 
401
396
  tokDFA = td.dfa
402
- tokDFA.startState.generatePDF(out_dir,"TokenDFA")
397
+ tokDFA.startState.generatePDF(@@out_dir,"TokenDFA")
403
398
 
404
399
  end
405
400
 
@@ -525,10 +520,11 @@ END
525
520
 
526
521
  def test_270_filter_ws
527
522
 
523
+ capture_begin
524
+
528
525
  dfa = DFA.from_script_file("sampletokens.txt")
529
- t = Tokenizer.new(dfa, readTextFile("sampletext.txt"), "WS")
526
+ t = Tokenizer.new(dfa, read_text_file("sampletext.txt"), "WS")
530
527
 
531
- s = ''
532
528
  while t.hasNext do
533
529
 
534
530
  tk = t.peek
@@ -536,48 +532,19 @@ END
536
532
  if t.nameOf(tk) == 'BROP'
537
533
  lst = t.readSequenceIf('BROP DO ID BRCL')
538
534
  if lst
539
- s << " ...read BROP DO ID sequence...\n"
540
- lst.each{ |x| s << " #{d(x)}\n"}
535
+ puts " ...read BROP DO ID sequence..."
536
+ lst.each{ |x| puts " #{d(x)}"}
541
537
  next
542
538
  else
543
- s << " ...couldn't find sequence...\n"
539
+ puts " ...couldn't find sequence..."
544
540
  end
545
541
  end
546
542
 
547
543
  tk = t.read
548
- s << d(tk) << "\n"
549
-
544
+ puts d(tk)
550
545
  end
551
- exp =<<"EXP"
552
- (line 1, col 1) : speed
553
- (line 1, col 6) : =
554
- (line 1, col 7) : 42
555
- (line 1, col 9) : gravity
556
- (line 1, col 16) : =
557
- (line 1, col 17) : -9.80
558
- ...couldn't find sequence...
559
- (line 1, col 22) : {
560
- (line 1, col 23) : color
561
- (line 1, col 29) : =
562
- (line 1, col 30) : green
563
- (line 1, col 35) : }
564
- (line 1, col 36) : title
565
- (line 1, col 41) : =
566
- (line 1, col 42) : 'This is a string with \\' an escaped delimiter'
567
- (line 1, col 89) : if
568
- (line 1, col 91) : gravity
569
- (line 1, col 98) : ==
570
- (line 1, col 100) : 12
571
- ...read BROP DO ID sequence...
572
- (line 1, col 102) : {
573
- (line 1, col 103) : do
574
- (line 1, col 105) : something
575
- (line 1, col 114) : }
576
- (line 1, col 115) : do
577
- (line 1, col 117) : something_else
578
- EXP
579
-
580
- assert(s.strip == exp.strip)
546
+
547
+ match_expected_output
581
548
  end
582
549
 
583
550
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tokn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Sember
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-04-09 00:00:00.000000000 Z
11
+ date: 2013-04-15 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: "Given a script containing token descriptions (each a regular expression),
14
14
  \ntokn compiles an automaton which it can then use to efficiently convert a \ntext
@@ -40,6 +40,15 @@ files:
40
40
  - test/_OLD_/data/sampletokens_dfa.txt
41
41
  - test/_OLD_/test.rb
42
42
  - test/_OLD_/testcmds
43
+ - test/_misc_/__mygraph__TokenDFA.pdf
44
+ - test/_misc_/__mygraph__buildDFA.pdf
45
+ - test/_misc_/__mygraph__dfa.pdf
46
+ - test/_misc_/__mygraph__dfa_duplicated.pdf
47
+ - test/_misc_/__mygraph__nfa.pdf
48
+ - test/_misc_/__mygraph__partition.pdf
49
+ - test/_misc_/__mygraph__reversed.pdf
50
+ - test/_misc_/sampletokens_dfa.txt
51
+ - test/_output_270_filter_ws.txt
43
52
  - test/sampletext.txt
44
53
  - test/sampletokens.txt
45
54
  - test/test_tokn.rb