mucgly 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.rdoc +8 -0
  3. data/LICENSE +1 -1
  4. data/README.rdoc +160 -130
  5. data/bin/mucgly +4 -217
  6. data/doc/Mucgly.html +24 -82
  7. data/doc/_index.html +5 -153
  8. data/doc/class_list.html +7 -2
  9. data/doc/css/style.css +2 -1
  10. data/doc/file.CHANGELOG.html +16 -8
  11. data/doc/file.README.html +210 -187
  12. data/doc/file_list.html +6 -1
  13. data/doc/frames.html +5 -7
  14. data/doc/index.html +210 -187
  15. data/doc/js/app.js +7 -2
  16. data/doc/js/full_list.js +9 -6
  17. data/doc/method_list.html +7 -686
  18. data/doc/top-level-namespace.html +5 -5
  19. data/ext/mucgly/extconf.rb +11 -0
  20. data/ext/mucgly/mucgly.c +2095 -0
  21. data/lib/version.rb +6 -0
  22. data/test/golden/test_basic.txt +18 -0
  23. data/test/golden/test_specials_cli.txt +11 -0
  24. data/test/golden/test_specials_cmd.txt +36 -0
  25. data/test/result/test_basic.txt +18 -0
  26. data/test/result/test_specials_cli.txt +11 -0
  27. data/test/result/test_specials_cmd.txt +36 -0
  28. data/test/result/test_specials_cmd2.txt +1 -0
  29. data/test/test_basic.rx.txt +10 -6
  30. data/test/test_mucgly.rb +4 -6
  31. data/test/test_specials_cli.rx.txt +4 -4
  32. data/test/test_specials_cmd.rx.txt +5 -5
  33. metadata +45 -63
  34. data/Rakefile +0 -29
  35. data/doc/EasyFile/InOut.html +0 -2097
  36. data/doc/EasyFile/Read.html +0 -1334
  37. data/doc/EasyFile/ReadStack.html +0 -461
  38. data/doc/EasyFile/Stacked.html +0 -411
  39. data/doc/EasyFile/String.html +0 -570
  40. data/doc/EasyFile/Write.html +0 -1084
  41. data/doc/EasyFile/WriteStack.html +0 -305
  42. data/doc/EasyFile.html +0 -155
  43. data/doc/Mucgly/Env.html +0 -1675
  44. data/doc/Mucgly/MucglyFile/ParseState.html +0 -1662
  45. data/doc/Mucgly/MucglyFile/Token.html +0 -529
  46. data/doc/Mucgly/MucglyFile.html +0 -545
  47. data/doc/Mucgly/Separators.html +0 -521
  48. data/lib/easyfile.rb +0 -720
  49. data/lib/mucgly.rb +0 -627
  50. data/test/test_multi.rx.txt +0 -4
data/lib/easyfile.rb DELETED
@@ -1,720 +0,0 @@
1
- # EasyFile module provides simplified file access management. The user
2
- # can refer all files by name, also the standard streams (STDIN,
3
- # STDOUT, STDERR). File names are unique since they are stored as
4
- # absolute path names. Also short names (relative/original) can be
5
- # used.
6
- #
7
- # The files are divided to Read and Write files. This simplifies the file
8
- # handling. Both files maintain the current line number.
9
- #
10
- # Read files has put-back feature. Arbitrary number of chars can be put
11
- # back to stream. This is helpful for parsers that has to perform
12
- # look-ahead.
13
- #
14
- # Write file have redirection support. Write file can be split into two
15
- # physical files if output requires copying to two or more files. Two
16
- # (or more ) Write files can also be joined, i.e. all writes are
17
- # directed to the joined file. Stream output can be suppressed.
18
- #
19
- # Examples:
20
- # f = EasyFile::Read.open( 'myfile' )
21
- # c = f.getc
22
- # if c == "#"
23
- # puts "Error in #{f.absname} on line #{f.line+1}: can't have '#' as first char..."
24
- # end
25
- #
26
- # f = EasyFile::Write.open( 'myfile' )
27
- # f.branch( 'myfile2' )
28
- # f.puts "foo\nbar\ndii"
29
- # puts "Number of lines output to 'myfile' and 'myfile2': #{f.line}..."
30
- #
31
-
32
- module EasyFile
33
-
34
-
35
- # Base class for Read and Write files.
36
- class InOut
37
-
38
- require 'stringio'
39
-
40
- # Map symbolic file direction to mode character.
41
- FILEMODEMAP = {
42
- :read => 'r',
43
- :write => 'w',
44
- }
45
-
46
- # Get absolute path for name.
47
- #
48
- # @param name [String] Relative file name.
49
- # @return [String] Absolute path name for the file.
50
- def InOut.abspath( name, mode )
51
- if InOut.standard?( name )
52
- name
53
- elsif mode == :string
54
- name
55
- else
56
- File.absolute_path( name )
57
- end
58
- end
59
-
60
- # Is name for standard IO?
61
- #
62
- # @param name [String] Relative file name.
63
- def InOut.standard?( name )
64
- case name
65
- when "<STDIN>"; true
66
- when "<STDOUT>"; true
67
- when "<STDERR>"; true
68
- else false
69
- end
70
- end
71
-
72
-
73
- # Create EasyFile object and, open file with given name and
74
- # mode.
75
- #
76
- # @param name [String] Relative path name for file.
77
- # @param mode [Symbol] Access direction (:read/:write).
78
- # @return [Read,Write] EasyFile handle.
79
- def InOut.open( name, mode = :read )
80
- file = InOut.create( name, mode )
81
- file.open
82
- file
83
- end
84
-
85
-
86
- # Create EasyFile object, no open. Open is performed
87
- # separately.
88
- #
89
- # @param name [String] Relative path name for file.
90
- # @param mode [Symbol] Access direction (:read/:write).
91
- # @return [Read,Write] EasyFile handle to non-opened file (use
92
- # "open").
93
- def InOut.create( name, mode = :read )
94
-
95
- absname = InOut.abspath( name, mode )
96
-
97
- # Check if file exists already.
98
- file = InOut.getByAbsname( absname )
99
-
100
- if file
101
-
102
- file
103
-
104
- else
105
-
106
- if mode == :read
107
- # file = Read.new( name, absname )
108
- file = Read.new( name, absname )
109
- elsif mode == :write
110
- file = Write.new( name, absname )
111
- elsif mode == :string
112
- file = String.new( name, absname )
113
- else
114
- raise RuntimeError, "Unknown file mode \"#{mode.to_s}\"..."
115
- end
116
-
117
- InOut.add( file )
118
-
119
- end
120
-
121
- file
122
-
123
- end
124
-
125
-
126
- # Add InOut to filelist.
127
- #
128
- # @param io [InOut] Item to list.
129
- # @return [InOut] Added item.
130
- def InOut.add( io )
131
- @@file_io[ io.absname ] = io
132
- end
133
-
134
-
135
- # Delete InOut from filelist.
136
- #
137
- # @param io [InOut] Item to list.
138
- # @return [InOut] Added item.
139
- def InOut.delete( io )
140
- @@file_io.delete( io.absname )
141
- end
142
-
143
-
144
- # Get InOut from filelist by InOut handle.
145
- #
146
- # @param io [InOut] Item handle.
147
- # @return [InOut] Added item.
148
- def InOut.get( io )
149
- @@file_io.getByAbsname( io.absname )
150
- end
151
-
152
-
153
- # Get InOut from filelist by absname.
154
- #
155
- # @param absname [InOut] Item absname.
156
- # @return [InOut] Added item.
157
- def InOut.getByAbsname( absname )
158
- @@file_io[ absname ]
159
- end
160
-
161
-
162
- # Get EasyFile list.
163
- #
164
- # @return [Array<InOut>] List of all files.
165
- def InOut.getList
166
- @@file_io.values
167
- end
168
-
169
-
170
-
171
- # Relative path name for file.
172
- attr_reader :filename
173
-
174
- # Absolute path name for file.
175
- attr_reader :absname
176
- alias :id :absname
177
-
178
- # File mode.
179
- attr_reader :mode
180
-
181
- # IO stream handle.
182
- attr_accessor :io
183
-
184
- # Parent EasyFile (push/pop).
185
- attr_accessor :parent
186
-
187
- # List of peer files (braches).
188
- attr_accessor :peers
189
-
190
- # Current line number (0,1,2...)
191
- attr_accessor :line
192
-
193
-
194
- # Create InOut object.
195
- #
196
- # @param mode [Symbol] File operation mode (:read, :write, :string).
197
- # @param filename [String] Relative path file name.
198
- # @param absname [String] Absolute path file name (generated
199
- # if not given).
200
- # @param io [IO] IO handle.
201
- def initialize( mode, filename, absname = nil, io = nil )
202
-
203
- @mode = mode
204
-
205
- unless absname
206
- absname = InOut.abspath( filename, mode )
207
- end
208
-
209
- # Set Primary IO.
210
- @io = io
211
-
212
- @filename = filename
213
- @absname = absname
214
-
215
- @peers = []
216
-
217
- @line = 0
218
- end
219
-
220
-
221
- # Open the stream.
222
- def open
223
-
224
- # Ensure single open.
225
- return if self.io
226
-
227
- if mode == :string
228
- handle = StringIO.new
229
- else
230
- handle = File.open( @absname, FILEMODEMAP[ mode ] )
231
- end
232
-
233
- self.io = handle
234
-
235
- self
236
- end
237
-
238
-
239
- # Close primary stream and peer streams.
240
- def close
241
-
242
- begin
243
- unless InOut.standard?( @filename )
244
- @io.close if @io
245
- InOut.delete( self )
246
- end
247
- rescue IOError
248
- end
249
-
250
- @peers.each do |i|
251
- i.close
252
- end
253
- end
254
-
255
-
256
- private
257
-
258
- # Update line number status according to encountered newline
259
- # chars.
260
- #
261
- # @param blk [String] Transfer chars.
262
- # @param offset [Integer] Line number value Change step.
263
- def updateLineNumber( blk, offset = 1 )
264
- return nil unless blk
265
- cnt = 0
266
- blk.each_char do |c|
267
- cnt += offset if c == "\n"
268
- end
269
- @line += cnt
270
- blk
271
- end
272
-
273
- end
274
-
275
-
276
-
277
- # Read file.
278
- #
279
- # Features:
280
- # * Line counting.
281
- # * Put-back char support.
282
- class Read < InOut
283
-
284
-
285
- # Create EasyFile::Read object and, open file with given name.
286
- #
287
- # @param name [String] Relative path name for file.
288
- # @return [Read] EasyFile handle.
289
- def Read.open( name )
290
- InOut.open( name, :read )
291
- end
292
-
293
-
294
- # Create Read object.
295
- #
296
- # @param filename [String] Relative path file name.
297
- # @param absname [String] Absolute path file name (generated
298
- # if not given).
299
- # @param io [IO] IO handle.
300
- def initialize( filename, absname = nil, io = nil )
301
- super( :read, filename, absname, io )
302
-
303
- @charbuffer = ""
304
- end
305
-
306
-
307
- # Get line.
308
- def gets
309
- begin
310
- readline
311
- rescue EOFError
312
- nil
313
- end
314
- end
315
-
316
-
317
- # Get line without newline.
318
- def getschomp
319
- line = gets
320
- if line
321
- line.chomp
322
- else
323
- line
324
- end
325
- end
326
-
327
-
328
- # Get char (from IO or put-back buffer).
329
- def getc
330
- begin
331
- getchar
332
- rescue EOFError
333
- nil
334
- end
335
- end
336
-
337
-
338
- # Get char (from IO or put-back buffer).
339
- def getchar
340
- updateLineNumber( getn( 1 ) )
341
- end
342
-
343
-
344
- # Put-back char(s) (to put-back buffer).
345
- def putback( c )
346
- @charbuffer = c + @charbuffer
347
- updateLineNumber( c, -1 )
348
- end
349
-
350
-
351
- # Read from IO.
352
- def read( length = 1024 )
353
- begin
354
- readchars( length )
355
- rescue EOFError
356
- nil
357
- end
358
- end
359
-
360
-
361
- # Read from IO with exception.
362
- def readchars( length = 1024 )
363
- updateLineNumber( getn( length ) )
364
- end
365
-
366
-
367
- def eof?
368
- @charbuffer.empty? && @io.eof?
369
- end
370
-
371
- alias eof eof?
372
-
373
-
374
- # Return Array of lines.
375
- def readlines( chomp = false )
376
- lines = []
377
- if chomp
378
- loop do
379
- line = getschomp
380
- break unless line
381
- lines.push line
382
- end
383
- else
384
- loop do
385
- line = gets
386
- break unless line
387
- lines.push line
388
- end
389
- end
390
- lines
391
- end
392
-
393
- # Iterate over lines.
394
- #
395
- # @yield Each line.
396
- def each_line( &blk )
397
- while ( line = gets )
398
- yield line
399
- end
400
- end
401
-
402
-
403
- # Iterate over lines with newline removed.
404
- #
405
- # @yield Each line.
406
- def each_chomp( &blk )
407
- while ( line = getschomp )
408
- yield line
409
- end
410
- end
411
-
412
-
413
- # Readline from file.
414
- def readline
415
- updateLineNumber( getline )
416
- end
417
-
418
-
419
-
420
- private
421
-
422
- # Get n characters from stream.
423
- def getn( n = 1 )
424
-
425
- while n > @charbuffer.length
426
- # Fill char buffer first.
427
- break if @io.eof?
428
- @charbuffer += @io.readline
429
- end
430
-
431
- ret = @charbuffer[ 0..(n-1) ]
432
-
433
- raise EOFError if ret == ""
434
-
435
- @charbuffer = @charbuffer[ n..-1 ]
436
-
437
- unless @charbuffer
438
- @charbuffer = ""
439
- end
440
-
441
- ret
442
- end
443
-
444
-
445
- # Get chars until newline.
446
- def getline
447
-
448
- if @charbuffer.empty?
449
- @io.readline
450
- else
451
- ret = ""
452
- nl = nil
453
-
454
- # Check if newline in @charbuffer.
455
- if ( nl = @charbuffer.index( "\n" ) )
456
- ret = @charbuffer[ 0..nl ]
457
- @charbuffer = @charbuffer[ nl+1..-1 ]
458
- ret
459
- else
460
- if @io.eof?
461
- ret = @charbuffer
462
- else
463
- ret = @charbuffer + @io.readline
464
- end
465
- @charbuffer = ""
466
- ret
467
- end
468
- end
469
- end
470
-
471
- end
472
-
473
-
474
-
475
- # Write file.
476
- #
477
- # Features:
478
- # * Line counting.
479
- # * Branching and joining.
480
- # * Stream output suppression.
481
- class Write < InOut
482
-
483
-
484
- # Create EasyFile::Write object and, open file with given name.
485
- #
486
- # @param name [String] Relative path name for file.
487
- # @return [Write] EasyFile handle.
488
- def Write.open( name )
489
- InOut.open( name, :write )
490
- end
491
-
492
-
493
- # Output is enabled.
494
- attr_accessor :enabled
495
-
496
- # Flush after each write.
497
- attr_accessor :flush
498
-
499
-
500
- # Create Write object.
501
- #
502
- # @param filename [String] Relative path file name.
503
- # @param absname [String] Absolute path file name (generated
504
- # if not given).
505
- # @param io [IO] IO handle.
506
- def initialize( filename, absname = nil, io = nil )
507
- super( :write, filename, absname, io )
508
- @enabled = true
509
- @flush = false
510
- end
511
-
512
-
513
- # Write to all IOs.
514
- def write( str )
515
- if @enabled
516
- updateLineNumber( str )
517
- if @io
518
- @io.write( str )
519
- @io.flush if @flush
520
- else
521
- # No output with nil stream.
522
- end
523
-
524
- @peers.each do |p|
525
- p.write( str )
526
- end
527
- end
528
- end
529
-
530
-
531
- # Write with automatic newline.
532
- def puts( str )
533
- nl = str[-1] == "\n" ? '' : "\n"
534
- write( str + nl )
535
- end
536
-
537
-
538
- # Attach a file to existing Write stream i.e. writes to Write
539
- # will be directed to attached file as well.
540
- #
541
- # @param fileid [String,Write] Filename or Write to add branching.
542
- # @return [Write] Added peer.
543
- def branch( fileid )
544
-
545
- if fileid.class == String
546
-
547
-
548
- # Get new IO.
549
- fileio = Write.open( fileid )
550
-
551
- else
552
-
553
- fileio = fileid
554
-
555
- end
556
-
557
- # Add if not already included.
558
- @peers.push fileio unless @peers.index( fileio )
559
-
560
- fileio
561
- end
562
-
563
-
564
- # Join the given filestream to this stream. After joining the
565
- # joined stream is output to same file as this stream.
566
- #
567
- # @param fileid [String,Write] Filename or Write to join.
568
- # @return [Write] Joined peer.
569
- def join( fileid )
570
-
571
- if fileid.class == String
572
- fileio = Write.create( fileid, nil )
573
- else
574
- fileio = fileid
575
- fileio.close
576
- end
577
-
578
- fileio.io = @io
579
- fileio
580
- end
581
-
582
-
583
- # Suppress stream output.
584
- #
585
- # @param disable [Boolean] Disable or enable suppression.
586
- def suppress( disable = true )
587
- @enabled = !disable
588
- end
589
-
590
- end
591
-
592
-
593
- # String buffer file.
594
- #
595
- # Features:
596
- # * Putback.
597
- class String < InOut
598
-
599
- def method_missing( name, *args, &block )
600
- @io.send( name, *args, &block )
601
- end
602
-
603
-
604
- # Create EasyFile::String object and, open file with given name.
605
- #
606
- # @param name [String] Name for file.
607
- # @return [String] EasyFile handle.
608
- def String.open( name )
609
- InOut.open( name, :string )
610
- end
611
-
612
- # Create String object.
613
- #
614
- # @param filename [String] Name.
615
- # @param absname [String] Absolute path file name (generated
616
- # if not given).
617
- # @param io [IO] IO handle.
618
- def initialize( filename, absname = nil, io = nil )
619
- super( :string, filename, absname, io )
620
- end
621
-
622
-
623
- # Put-back char(s) (to put-back buffer).
624
- # @param c [String] Chars to put back to buffer.
625
- def putback( c )
626
- @io.string = c + @io.string[ @io.pos..-1 ]
627
- end
628
-
629
-
630
- end
631
-
632
-
633
- class InOut
634
-
635
- # Declare standards IOs.
636
- @@file_io = {
637
- "<STDIN>" => Read.new( '<STDIN>', nil, STDIN ),
638
- "<STDOUT>" => Write.new( '<STDOUT>', nil, STDOUT ),
639
- "<STDERR>" => Write.new( '<STDERR>', nil, STDERR ),
640
- # filename (absname) => InOut object
641
- }
642
-
643
- end
644
-
645
-
646
- # Stack of files.
647
- module Stacked
648
- attr_accessor :stack
649
-
650
- instance_methods.each { |m| undef_method m unless m =~ /(^__|^send$|^object_id$)/ }
651
-
652
- def setup( first = nil )
653
- if first
654
- @stack = [ first ]
655
- else
656
- @stack = []
657
- end
658
- end
659
-
660
- def pop
661
- if @stack.length > 1
662
- @stack[-1].close
663
- @stack.pop
664
- end
665
- end
666
-
667
- def method_missing( name, *args, &block )
668
- if [ :getc, :gets, :gets! ].index( name )
669
- if @stack[-1].eof? && @automode
670
- pop
671
- end
672
- end
673
- @stack[-1].send( name, *args, &block )
674
- end
675
-
676
- alias close pop
677
- end
678
-
679
-
680
- # Stack of Read files.
681
- class ReadStack
682
- include Stacked
683
-
684
- # Automatically revert to lower file at EOF.
685
- attr_accessor :automode
686
-
687
- def initialize( name )
688
- io = InOut.open( name, :read )
689
- setup( io )
690
- @automode = true
691
- end
692
-
693
- def push( name )
694
- io = InOut.open( name, :read )
695
- @stack.push io
696
- end
697
-
698
- def eof?
699
- @stack.length == 1 && @stack[-1].eof?
700
- end
701
- end
702
-
703
-
704
- # Stack of Write files.
705
- class WriteStack
706
- include Stacked
707
-
708
- def initialize( name )
709
- io = InOut.open( name, :write )
710
- setup( io )
711
- end
712
-
713
- def push( name )
714
- io = InOut.open( name, :write )
715
- @stack.push io
716
- end
717
-
718
- end
719
-
720
- end