mucgly 0.0.1
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.
- data/CHANGELOG.rdoc +3 -0
- data/LICENSE +20 -0
- data/README.rdoc +292 -0
- data/Rakefile +29 -0
- data/bin/mucgly +220 -0
- data/doc/EasyFile/InOut.html +2097 -0
- data/doc/EasyFile/Read.html +1334 -0
- data/doc/EasyFile/ReadStack.html +461 -0
- data/doc/EasyFile/Stacked.html +411 -0
- data/doc/EasyFile/String.html +570 -0
- data/doc/EasyFile/Write.html +1084 -0
- data/doc/EasyFile/WriteStack.html +305 -0
- data/doc/EasyFile.html +155 -0
- data/doc/Mucgly/Env.html +1675 -0
- data/doc/Mucgly/MucglyFile/ParseState.html +1662 -0
- data/doc/Mucgly/MucglyFile/Token.html +529 -0
- data/doc/Mucgly/MucglyFile.html +545 -0
- data/doc/Mucgly/Separators.html +521 -0
- data/doc/Mucgly.html +244 -0
- data/doc/_index.html +261 -0
- data/doc/class_list.html +53 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +57 -0
- data/doc/css/style.css +338 -0
- data/doc/file.CHANGELOG.html +79 -0
- data/doc/file.README.html +390 -0
- data/doc/file_list.html +58 -0
- data/doc/frames.html +28 -0
- data/doc/index.html +390 -0
- data/doc/js/app.js +214 -0
- data/doc/js/full_list.js +178 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +742 -0
- data/doc/top-level-namespace.html +112 -0
- data/lib/easyfile.rb +720 -0
- data/lib/mucgly.rb +627 -0
- data/test/test_basic.rx.txt +19 -0
- data/test/test_include.rb +6 -0
- data/test/test_include.txt +3 -0
- data/test/test_mucgly.rb +32 -0
- data/test/test_multi.rx.txt +4 -0
- data/test/test_specials_cli.rx.txt +11 -0
- data/test/test_specials_cmd.rx.txt +53 -0
- metadata +98 -0
data/lib/mucgly.rb
ADDED
@@ -0,0 +1,627 @@
|
|
1
|
+
module Mucgly
|
2
|
+
|
3
|
+
|
4
|
+
def Mucgly::error( str )
|
5
|
+
if Opt['warn_only'].given
|
6
|
+
puts "*** Mucgly Error: #{str}"
|
7
|
+
else
|
8
|
+
raise RuntimeError, "*** Mucgly Error: #{str}"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def Mucgly::debug( str )
|
13
|
+
puts "\nMucglyDebug: #{str}" if Opt['debug'].given
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
# Execution environment for MucglyFile.
|
18
|
+
class Env
|
19
|
+
|
20
|
+
@@fileStartHook = nil
|
21
|
+
@@fileEndHook = nil
|
22
|
+
|
23
|
+
attr_accessor :_separators
|
24
|
+
attr_accessor :_inIO
|
25
|
+
attr_accessor :_outIO
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
@_outIO = STDOUT
|
29
|
+
end
|
30
|
+
|
31
|
+
def Env.fileStartHook=( val )
|
32
|
+
@@fileStartHook = val
|
33
|
+
end
|
34
|
+
|
35
|
+
def Env.fileEndHook=( val )
|
36
|
+
@@fileEndHook = val
|
37
|
+
end
|
38
|
+
|
39
|
+
def Env.fileStartHook
|
40
|
+
@@fileStartHook
|
41
|
+
end
|
42
|
+
|
43
|
+
def Env.fileEndHook
|
44
|
+
@@fileEndHook
|
45
|
+
end
|
46
|
+
|
47
|
+
def fileStartHook
|
48
|
+
@@fileStartHook
|
49
|
+
end
|
50
|
+
|
51
|
+
def fileEndHook
|
52
|
+
@@fileEndHook
|
53
|
+
end
|
54
|
+
|
55
|
+
def write( str )
|
56
|
+
@_outIO.write str
|
57
|
+
end
|
58
|
+
|
59
|
+
def puts( str )
|
60
|
+
@_outIO.puts str
|
61
|
+
end
|
62
|
+
|
63
|
+
def source( file )
|
64
|
+
instance_eval( File.read( file ), file )
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
# ------------------------------------------------------------
|
69
|
+
# Interface methods:
|
70
|
+
|
71
|
+
|
72
|
+
def _processFilePair( filePair )
|
73
|
+
_openInput( filePair[ 0 ] )
|
74
|
+
_openOutput( filePair[ 1 ] )
|
75
|
+
Mucgly::MucglyFile.new( self )
|
76
|
+
end
|
77
|
+
|
78
|
+
def _processFilePairs( filePairs )
|
79
|
+
filePairs.each do |pair|
|
80
|
+
_processFilePair( pair )
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def _openInput( filename )
|
85
|
+
@_inIO = EasyFile::ReadStack.new( filename )
|
86
|
+
end
|
87
|
+
|
88
|
+
def _openOutput( filename )
|
89
|
+
@_outIO = EasyFile::WriteStack.new( filename )
|
90
|
+
end
|
91
|
+
|
92
|
+
def _openString( filename )
|
93
|
+
@_outIO = EasyFile::String.open( filename )
|
94
|
+
end
|
95
|
+
|
96
|
+
def _pushInput( name )
|
97
|
+
@_inIO.push( name )
|
98
|
+
end
|
99
|
+
|
100
|
+
def _pushOutput( name )
|
101
|
+
@_outIO.push( name )
|
102
|
+
end
|
103
|
+
|
104
|
+
def _closeInput
|
105
|
+
@_inIO.close
|
106
|
+
end
|
107
|
+
|
108
|
+
def _closeOutput
|
109
|
+
@_outIO.close
|
110
|
+
end
|
111
|
+
|
112
|
+
def _ofilename
|
113
|
+
@_outIO.filename
|
114
|
+
end
|
115
|
+
|
116
|
+
def _olinenumber
|
117
|
+
@_outIO.line
|
118
|
+
end
|
119
|
+
|
120
|
+
def _ifilename
|
121
|
+
@_inIO.filename
|
122
|
+
end
|
123
|
+
|
124
|
+
def _ilinenumber
|
125
|
+
@_inIO.line
|
126
|
+
end
|
127
|
+
|
128
|
+
def _eval( cmd )
|
129
|
+
instance_eval cmd
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
# MucglyFile includes processing and status for a file that is treated
|
136
|
+
# as Mucgly file. Separators are copied from the upper level
|
137
|
+
# context i.e. lower level settings does NOT affect higher level
|
138
|
+
# settings. Status of parsing is kept within the class.
|
139
|
+
class MucglyFile
|
140
|
+
|
141
|
+
attr_accessor :env, :parseState
|
142
|
+
|
143
|
+
def initialize( env )
|
144
|
+
|
145
|
+
@env = env
|
146
|
+
|
147
|
+
# Process fileStartHook callback:
|
148
|
+
@env._eval( @env.fileStartHook ) if @env.fileStartHook
|
149
|
+
|
150
|
+
# Copy upper level separators.
|
151
|
+
@env._separators = @env._separators.copy
|
152
|
+
|
153
|
+
# Process the Mucgly file.
|
154
|
+
parse
|
155
|
+
end
|
156
|
+
|
157
|
+
|
158
|
+
# Input is a stream of characters or control values.
|
159
|
+
#
|
160
|
+
# Supported types: char, hookEnd, hookBeg, escape, eof, and
|
161
|
+
# empty
|
162
|
+
class Token
|
163
|
+
|
164
|
+
attr_accessor :type, :value
|
165
|
+
|
166
|
+
def initialize( type, value = nil )
|
167
|
+
@type = type
|
168
|
+
@value = value
|
169
|
+
end
|
170
|
+
|
171
|
+
def isPunct
|
172
|
+
!isChar
|
173
|
+
end
|
174
|
+
|
175
|
+
def isChar
|
176
|
+
@type == :char
|
177
|
+
end
|
178
|
+
|
179
|
+
def to_s
|
180
|
+
"#{@type.to_s}:#{value}"
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
|
185
|
+
|
186
|
+
# Parse state regarding buffered tokens.
|
187
|
+
class ParseState
|
188
|
+
|
189
|
+
def initialize( host )
|
190
|
+
@host = host
|
191
|
+
@stack = [[]]
|
192
|
+
@level = 0
|
193
|
+
@active = false
|
194
|
+
end
|
195
|
+
|
196
|
+
# Add token.
|
197
|
+
def shift( token )
|
198
|
+
if @stack[-1][-1] && @stack[-1][-1].type == token.type
|
199
|
+
@stack[-1][-1].value += token.value
|
200
|
+
else
|
201
|
+
@stack[-1].push token
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
# Push new parse context.
|
206
|
+
def push
|
207
|
+
unless inside?
|
208
|
+
flush
|
209
|
+
end
|
210
|
+
inc
|
211
|
+
@stack.push []
|
212
|
+
end
|
213
|
+
|
214
|
+
# Pop top parse context.
|
215
|
+
def pop
|
216
|
+
if @active
|
217
|
+
# Execute.
|
218
|
+
eval( @stack[-1] )
|
219
|
+
@stack.pop
|
220
|
+
else
|
221
|
+
# Output literal.
|
222
|
+
output( @stack[-1] )
|
223
|
+
@stack.pop
|
224
|
+
end
|
225
|
+
|
226
|
+
dec
|
227
|
+
end
|
228
|
+
|
229
|
+
# Output shifted tokens.
|
230
|
+
def flush
|
231
|
+
output( @stack[-1] )
|
232
|
+
@stack[-1] = []
|
233
|
+
end
|
234
|
+
|
235
|
+
# Output list of tokens.
|
236
|
+
def output( list )
|
237
|
+
list.each do |t|
|
238
|
+
@host.env.write t.value
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
# Inside macro def.
|
243
|
+
def inside?
|
244
|
+
@level > 0
|
245
|
+
end
|
246
|
+
|
247
|
+
# Inc macro level.
|
248
|
+
def inc
|
249
|
+
@active = true
|
250
|
+
@level += 1
|
251
|
+
end
|
252
|
+
|
253
|
+
# Dec macro level.
|
254
|
+
def dec
|
255
|
+
@level -= 1
|
256
|
+
@active = false
|
257
|
+
end
|
258
|
+
|
259
|
+
# Evaluate shifted tokens.
|
260
|
+
def eval( list )
|
261
|
+
idx = 0
|
262
|
+
|
263
|
+
# Skip hookbeg.
|
264
|
+
idx += 1
|
265
|
+
|
266
|
+
# Check if macro is internal command.
|
267
|
+
if list[idx].value[0] == "."
|
268
|
+
|
269
|
+
# Variable reference.
|
270
|
+
|
271
|
+
varname = list[idx].value[1..-1]
|
272
|
+
|
273
|
+
# Skip hookend.
|
274
|
+
idx += 2
|
275
|
+
|
276
|
+
raise RuntimeError, "Garbage after hookend." if list[ idx ]
|
277
|
+
|
278
|
+
@host.env._eval( "write @#{varname}" )
|
279
|
+
|
280
|
+
elsif list[idx].value[0] == ":"
|
281
|
+
|
282
|
+
# Command.
|
283
|
+
|
284
|
+
cmd, rest = list[idx].value[1..-1].scan( /([a-z]+) (.*)/ )[0]
|
285
|
+
|
286
|
+
# Skip hookend.
|
287
|
+
idx += 2
|
288
|
+
|
289
|
+
raise RuntimeError, "Garbage after hookend." if list[ idx ]
|
290
|
+
|
291
|
+
case cmd
|
292
|
+
|
293
|
+
when 'include'
|
294
|
+
@host.env._pushInput( rest )
|
295
|
+
@host.env._inIO.automode = false
|
296
|
+
@host.parse
|
297
|
+
|
298
|
+
when 'output'
|
299
|
+
@host.env._pushOutput( rest )
|
300
|
+
|
301
|
+
when 'close'
|
302
|
+
@host.env._closeOutput
|
303
|
+
|
304
|
+
when 'comment'
|
305
|
+
# ' mode coloring fix comment.
|
306
|
+
true
|
307
|
+
|
308
|
+
when 'source'
|
309
|
+
@host.env.source( rest )
|
310
|
+
|
311
|
+
when 'hook'
|
312
|
+
if rest.split.length == 2
|
313
|
+
@host.env._separators.hookBegChars = rest.split[0]
|
314
|
+
@host.env._separators.hookEndChars = rest.split[1]
|
315
|
+
else
|
316
|
+
@host.env._separators.hookBegChars = rest
|
317
|
+
@host.env._separators.hookEndChars = rest
|
318
|
+
end
|
319
|
+
|
320
|
+
when 'hookbeg'
|
321
|
+
@host.env._separators.hookBegChars = rest
|
322
|
+
|
323
|
+
when 'hookend'
|
324
|
+
@host.env._separators.hookEndChars = rest
|
325
|
+
|
326
|
+
when 'escape'
|
327
|
+
@host.env._separators.escapeChar = rest
|
328
|
+
|
329
|
+
when 'exit'
|
330
|
+
exit
|
331
|
+
|
332
|
+
else
|
333
|
+
Mucgly::error "unkown internal command: \"#{cmd}\""
|
334
|
+
|
335
|
+
end
|
336
|
+
|
337
|
+
elsif list[idx].value[0] == "#"
|
338
|
+
|
339
|
+
# Remove macro cancel char from macro and output
|
340
|
+
# the macro again.
|
341
|
+
|
342
|
+
@host.env.write( list[idx-1].value )
|
343
|
+
@host.env.write( list[idx].value[1..-1] )
|
344
|
+
@host.env.write( list[idx+1].value )
|
345
|
+
|
346
|
+
# Skip hookend.
|
347
|
+
idx += 2
|
348
|
+
|
349
|
+
raise RuntimeError, "Garbage after hookend." if list[ idx ]
|
350
|
+
|
351
|
+
else
|
352
|
+
|
353
|
+
# Ruby code to evaluate.
|
354
|
+
|
355
|
+
code = list[idx].value
|
356
|
+
|
357
|
+
# Skip hookend.
|
358
|
+
idx += 2
|
359
|
+
|
360
|
+
raise RuntimeError, "Garbage after hookend." if list[ idx ]
|
361
|
+
|
362
|
+
@host.env._eval code
|
363
|
+
|
364
|
+
end
|
365
|
+
|
366
|
+
end
|
367
|
+
|
368
|
+
|
369
|
+
# Return char either from character buffer (String) or file stream.
|
370
|
+
def getChars( cnt = 1 )
|
371
|
+
c = @host.env._inIO.read( cnt )
|
372
|
+
Mucgly::debug( "Read char: \"#{c}\"" )
|
373
|
+
c
|
374
|
+
end
|
375
|
+
|
376
|
+
# Put character back.
|
377
|
+
def putBack( c )
|
378
|
+
@host.env._inIO.putback( c )
|
379
|
+
Mucgly::debug( "Putback char: \"#{c}\"" )
|
380
|
+
end
|
381
|
+
|
382
|
+
# Find a given string from input (true/false).
|
383
|
+
def findInInput( this )
|
384
|
+
|
385
|
+
str = getChars( this.length )
|
386
|
+
|
387
|
+
if str == this
|
388
|
+
# Found requested string from input.
|
389
|
+
true
|
390
|
+
else
|
391
|
+
# Mismatch to requested string, put back to input.
|
392
|
+
putBack( str )
|
393
|
+
false
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
|
398
|
+
# Create a token based on the current characters. The
|
399
|
+
# token returned is effected by parsing context and
|
400
|
+
# separator settings.
|
401
|
+
def getTokenRaw
|
402
|
+
|
403
|
+
escapeChar = @host.env._separators.escapeChar
|
404
|
+
hookEndChars = @host.env._separators.hookEndChars
|
405
|
+
hookBegChars = @host.env._separators.hookBegChars
|
406
|
+
|
407
|
+
|
408
|
+
c = getChars
|
409
|
+
|
410
|
+
if c == nil
|
411
|
+
|
412
|
+
Token.new( :eof )
|
413
|
+
|
414
|
+
else
|
415
|
+
|
416
|
+
# Handle escape characters before hooks.
|
417
|
+
if c == escapeChar
|
418
|
+
|
419
|
+
c = getChars
|
420
|
+
|
421
|
+
if c == "\n"
|
422
|
+
# Escaped newline.
|
423
|
+
return Token.new( :empty, "" )
|
424
|
+
|
425
|
+
elsif c == escapeChar
|
426
|
+
# Escaped escape.
|
427
|
+
return Token.new( :char, escapeChar )
|
428
|
+
|
429
|
+
elsif inside?
|
430
|
+
|
431
|
+
# Escape inside first level macro.
|
432
|
+
|
433
|
+
if ( c == " " || c == "\n" ) and
|
434
|
+
( escapeChar ==
|
435
|
+
hookEndChars )
|
436
|
+
|
437
|
+
# Hookend when same as escape is
|
438
|
+
# "hookend+space".
|
439
|
+
return Token.new( :hookEnd, escapeChar + c )
|
440
|
+
|
441
|
+
elsif c == hookEndChars[0]
|
442
|
+
|
443
|
+
# Escaped hookend.
|
444
|
+
return Token.new( :char, c )
|
445
|
+
|
446
|
+
else
|
447
|
+
|
448
|
+
# Ineffective escape.
|
449
|
+
return Token.new( :char,
|
450
|
+
escapeChar + c )
|
451
|
+
end
|
452
|
+
|
453
|
+
else
|
454
|
+
|
455
|
+
# Escape outside macro.
|
456
|
+
|
457
|
+
if escapeChar == hookEndChars
|
458
|
+
|
459
|
+
putBack( c )
|
460
|
+
return Token.new( :hookBeg,
|
461
|
+
hookBegChars )
|
462
|
+
|
463
|
+
elsif c == hookEndChars[0]
|
464
|
+
|
465
|
+
return Token.new( :char, c )
|
466
|
+
|
467
|
+
elsif ( c == " " || c == "\n" )
|
468
|
+
|
469
|
+
# Remove escaped space and newlines.
|
470
|
+
return Token.new( :empty )
|
471
|
+
|
472
|
+
elsif c == hookBegChars[0]
|
473
|
+
|
474
|
+
return Token.new( :char, c )
|
475
|
+
|
476
|
+
else
|
477
|
+
|
478
|
+
# Ineffective escape.
|
479
|
+
return Token.new( :char,
|
480
|
+
escapeChar + c )
|
481
|
+
|
482
|
+
end
|
483
|
+
|
484
|
+
end
|
485
|
+
|
486
|
+
else
|
487
|
+
|
488
|
+
# No escape, putback and search for hooks.
|
489
|
+
putBack c
|
490
|
+
|
491
|
+
end
|
492
|
+
|
493
|
+
|
494
|
+
# Look for hooks or return a character.
|
495
|
+
if inside?
|
496
|
+
|
497
|
+
# Inside macro.
|
498
|
+
|
499
|
+
if findInInput( hookEndChars )
|
500
|
+
return Token.new( :hookEnd, hookEndChars )
|
501
|
+
end
|
502
|
+
|
503
|
+
else
|
504
|
+
|
505
|
+
# Outside macro.
|
506
|
+
|
507
|
+
if findInInput( hookBegChars )
|
508
|
+
return Token.new( :hookBeg, hookBegChars )
|
509
|
+
end
|
510
|
+
|
511
|
+
end
|
512
|
+
|
513
|
+
|
514
|
+
# No escapes, no hooks, so return a char.
|
515
|
+
c = getChars
|
516
|
+
|
517
|
+
if c == nil
|
518
|
+
return Token.new( :eof )
|
519
|
+
else
|
520
|
+
return Token.new( :char, c )
|
521
|
+
end
|
522
|
+
|
523
|
+
end
|
524
|
+
end
|
525
|
+
|
526
|
+
|
527
|
+
def getToken
|
528
|
+
t = getTokenRaw
|
529
|
+
Mucgly::debug( "Got token: #{t.type}:\"#{t.value}\"" )
|
530
|
+
t
|
531
|
+
end
|
532
|
+
|
533
|
+
end
|
534
|
+
|
535
|
+
|
536
|
+
# Process a Mucgly file.
|
537
|
+
def parse
|
538
|
+
|
539
|
+
parseState = ParseState.new( self )
|
540
|
+
|
541
|
+
while true
|
542
|
+
|
543
|
+
t = parseState.getToken
|
544
|
+
|
545
|
+
if t.type == :eof
|
546
|
+
|
547
|
+
parseState.flush
|
548
|
+
|
549
|
+
# Process fileEndHook callback:
|
550
|
+
@env._eval( @env.fileEndHook ) if @env.fileEndHook
|
551
|
+
|
552
|
+
# End of stream.
|
553
|
+
# @fp.close
|
554
|
+
|
555
|
+
@env._inIO.close
|
556
|
+
|
557
|
+
return
|
558
|
+
|
559
|
+
elsif t.type == :hookBeg
|
560
|
+
|
561
|
+
parseState.push
|
562
|
+
parseState.shift( t )
|
563
|
+
|
564
|
+
elsif t.type == :hookEnd
|
565
|
+
|
566
|
+
parseState.shift( t )
|
567
|
+
parseState.pop
|
568
|
+
|
569
|
+
else
|
570
|
+
|
571
|
+
parseState.shift( t )
|
572
|
+
|
573
|
+
end
|
574
|
+
|
575
|
+
|
576
|
+
end
|
577
|
+
|
578
|
+
end
|
579
|
+
|
580
|
+
end
|
581
|
+
|
582
|
+
|
583
|
+
|
584
|
+
# Separators are collection of special characters used by Mucgly.
|
585
|
+
#
|
586
|
+
# These are:
|
587
|
+
# [escape] Escape char is used to convert special chars into their
|
588
|
+
# literal form or to remove the following char. Special
|
589
|
+
# characters are: escape char, hookbeg, hookend. Escape
|
590
|
+
# can remove the following newline, and space in special
|
591
|
+
# circumtances.
|
592
|
+
# [hookbeg] Hookbeg char (or string) starts macros. If user wants
|
593
|
+
# a literal hookbeg, then <escape> should be put before
|
594
|
+
# it.
|
595
|
+
# [hookend] Hookend char (or string) terminates macros. Hookend
|
596
|
+
# can also be escaped. If hookend end is same character
|
597
|
+
# as escape, then hookend followed by a space is
|
598
|
+
# considered as hookend.
|
599
|
+
class Separators
|
600
|
+
|
601
|
+
# Set of control characters for hook and escape indentification.
|
602
|
+
attr_reader :escapeChar
|
603
|
+
attr_accessor :hookBegChars, :hookEndChars
|
604
|
+
|
605
|
+
def initialize
|
606
|
+
@escapeChar = "\\"
|
607
|
+
@hookBegChars = "-<"
|
608
|
+
@hookEndChars = ">-"
|
609
|
+
end
|
610
|
+
|
611
|
+
def escapeChar=( value )
|
612
|
+
if value.length != 1
|
613
|
+
Mucgly::error( "Escape must be 1 char long, got \"#{value}\"" )
|
614
|
+
end
|
615
|
+
@escapeChar = value
|
616
|
+
end
|
617
|
+
|
618
|
+
def copy
|
619
|
+
c = Separators.new
|
620
|
+
c.escapeChar = @escapeChar
|
621
|
+
c.hookBegChars = @hookBegChars
|
622
|
+
c.hookEndChars = @hookEndChars
|
623
|
+
return c
|
624
|
+
end
|
625
|
+
end
|
626
|
+
|
627
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Line 1 from file "-<write _ifilename>-".
|
2
|
+
-<:hook \\>-\
|
3
|
+
Test escapes (backslash, empty): "\\" "\ \ " \
|
4
|
+
... and the rest of the line.
|
5
|
+
Next the test file "test_include.txt" is included.
|
6
|
+
\:comment :include test_include.txt\ \
|
7
|
+
\:include test_include.txt\ \
|
8
|
+
This is again in file "\write _ifilename\ ".
|
9
|
+
Next line should be three times "bar" in a row.
|
10
|
+
\@foo="bar";\ \.foo\ \write @foo\ \.foo\
|
11
|
+
A line of text.
|
12
|
+
\puts "Just some text from Mucgly."\ \
|
13
|
+
Source "test_include.rb" and instantiate the class defined in there.
|
14
|
+
\:source test_include.rb\ \@obj = MyClass.new\ \
|
15
|
+
Print out a sum using the previously instantiated class.
|
16
|
+
\puts "Sum of 1+2 is: #{@obj.sum(1,2)}..."\ \
|
17
|
+
The last line in "\write _ifilename\ "
|
18
|
+
The name of this file is: "\write _ifilename\ ".
|
19
|
+
We are outputting to file \write _ofilename\ and \write _olinenumber.to_s\
|
data/test/test_mucgly.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
|
4
|
+
# Test execution routine.
|
5
|
+
def runTest( cmdopts, test, sep = "" )
|
6
|
+
Dir.chdir( 'test' )
|
7
|
+
FileUtils.mkdir_p "result"
|
8
|
+
rf = "result/#{test}#{sep}.txt"
|
9
|
+
gf = "golden/#{test}#{sep}.txt"
|
10
|
+
|
11
|
+
system( "export RUBYLIB=#{ENV['RUBYLIB']}:../lib; ../bin/mucgly #{cmdopts} -i #{test}.rx.txt -o #{rf}" )
|
12
|
+
|
13
|
+
if false
|
14
|
+
# Populate golden files after inspection.
|
15
|
+
system( "cp #{rf} #{gf}" )
|
16
|
+
end
|
17
|
+
|
18
|
+
assert( system( "diff #{rf} #{gf}" ), "FAILED: diff #{rf} #{gf}" )
|
19
|
+
|
20
|
+
Dir.chdir( '..' )
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
class MucglyTest < Test::Unit::TestCase
|
25
|
+
|
26
|
+
def test_basic() runTest( "", "test_basic" ); end
|
27
|
+
def test_specials_cli1() runTest( "-s @ -e /", "test_specials_cli", "_1" ); end
|
28
|
+
def test_specials_cli2() runTest( "-sb @ -se @ -e /", "test_specials_cli", "_2" ); end
|
29
|
+
def test_specials_cmd() runTest( "", "test_specials_cmd" ); end
|
30
|
+
def test_multi() runTest( "-m", "test_multi" ); end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
Line @write (_ilinenumber+1).to_s@ from file "@write _ifilename@".
|
2
|
+
Test escapes (backslash, empty): "//" "@ @" /
|
3
|
+
... and the rest of the line.
|
4
|
+
Next the test file "test_include.txt" is included.
|
5
|
+
@:include test_include.txt@/
|
6
|
+
This is again in file "@write _ifilename@ ".
|
7
|
+
Next line should be three times "bar" in a row.
|
8
|
+
@/@foo="bar"@@.foo@@.foo@@puts /@foo@/
|
9
|
+
A line of text.
|
10
|
+
@puts "Just some text from Mucgly."@/
|
11
|
+
The last line in "@write _ifilename@"
|