yap-shell-parser 0.5.0 → 0.6.0
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.
- checksums.yaml +4 -4
- data/lib/yap/shell/parser/lexer.rb +95 -22
- data/lib/yap/shell/parser/version.rb +1 -1
- data/lib/yap/shell/parser.rb +20 -7
- data/yap-shell-parser.gemspec +2 -0
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4cbb2bd60f57e8a7ec75043614f19ca42b6a5b87
|
4
|
+
data.tar.gz: 91050d9396ad122987af76764bca6810ac99546c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a9d8a4feabef744b97369765d8dda04f92964f92ec7f8f47c159dca53d76dbeee25c4d7635911c99eb709fa9d44739e0d7994ec34cff78ee5492b4db616254ca
|
7
|
+
data.tar.gz: 1037679abed76641c88652aa503064093f9a77ed7420c9fd31c7b62c27df8b0fdbfe1254a7bb295b45197939863a62ef8c3f057c63fe93a62c0cf6223c8d495d
|
@@ -103,6 +103,7 @@ module Yap::Shell
|
|
103
103
|
end
|
104
104
|
|
105
105
|
def tokenize(str)
|
106
|
+
debug_log "##{__callee__} string: #{str.inspect}"
|
106
107
|
@chunk = str
|
107
108
|
@tokens = []
|
108
109
|
@lineno = 0
|
@@ -119,6 +120,7 @@ module Yap::Shell
|
|
119
120
|
line_continuation_token
|
120
121
|
|
121
122
|
while process_next_chunk.call
|
123
|
+
debug_log "##{__callee__} looking for next token in: #{@chunk.inspect}"
|
122
124
|
result =
|
123
125
|
comment_token ||
|
124
126
|
block_token ||
|
@@ -156,7 +158,9 @@ module Yap::Shell
|
|
156
158
|
private
|
157
159
|
|
158
160
|
def token(tag, value, attrs:{})
|
159
|
-
|
161
|
+
token = [tag, Token.new(tag, value, lineno:@lineno, attrs:attrs)]
|
162
|
+
debug_log "#{__callee__} found token: #{token.inspect}"
|
163
|
+
@tokens.push token
|
160
164
|
end
|
161
165
|
|
162
166
|
def block_token
|
@@ -172,6 +176,8 @@ module Yap::Shell
|
|
172
176
|
@looking_for_args = false
|
173
177
|
token :BlockEnd, md[1]
|
174
178
|
md[0].length
|
179
|
+
else
|
180
|
+
did_not_match
|
175
181
|
end
|
176
182
|
end
|
177
183
|
|
@@ -179,11 +185,16 @@ module Yap::Shell
|
|
179
185
|
if md=@chunk.match(COMMENT)
|
180
186
|
token :Comment, md[0]
|
181
187
|
md[0].length
|
188
|
+
else
|
189
|
+
did_not_match
|
182
190
|
end
|
183
191
|
end
|
184
192
|
|
185
193
|
def numerical_range_token
|
186
|
-
|
194
|
+
if @looking_for_args
|
195
|
+
skipping
|
196
|
+
return
|
197
|
+
end
|
187
198
|
|
188
199
|
if md=@chunk.match(NUMERIC_RANGE_W_CALL)
|
189
200
|
start, stop = md[2].to_i, md[3].to_i
|
@@ -227,31 +238,47 @@ module Yap::Shell
|
|
227
238
|
token :Range, (start..stop)
|
228
239
|
md[0].length
|
229
240
|
|
241
|
+
else
|
242
|
+
did_not_match
|
230
243
|
end
|
231
|
-
|
232
244
|
end
|
233
245
|
|
234
246
|
def command_token
|
235
|
-
if
|
247
|
+
if @looking_for_args
|
248
|
+
skipping
|
249
|
+
return
|
250
|
+
elsif md=@chunk.match(COMMAND)
|
236
251
|
@looking_for_args = true
|
237
252
|
token :Command, md[1]
|
238
253
|
md[0].length
|
254
|
+
else
|
255
|
+
did_not_match
|
239
256
|
end
|
240
257
|
end
|
241
258
|
|
242
259
|
def literal_command_token
|
243
|
-
if
|
260
|
+
if @looking_for_args
|
261
|
+
skipping
|
262
|
+
return
|
263
|
+
elsif md=@chunk.match(LITERAL_COMMAND)
|
244
264
|
@looking_for_args = true
|
245
265
|
token :LiteralCommand, md[1]
|
246
266
|
md[0].length
|
267
|
+
else
|
268
|
+
did_not_match
|
247
269
|
end
|
248
270
|
end
|
249
271
|
|
250
272
|
def numeric_expr_token
|
251
|
-
if
|
273
|
+
if @looking_for_args
|
274
|
+
skipping
|
275
|
+
return
|
276
|
+
elsif md=@chunk.match(NUMERIC_EXPR)
|
252
277
|
@looking_for_args = true
|
253
278
|
token :NumericExpr, md[1]
|
254
279
|
md[0].length
|
280
|
+
else
|
281
|
+
did_not_match
|
255
282
|
end
|
256
283
|
end
|
257
284
|
|
@@ -281,6 +308,8 @@ module Yap::Shell
|
|
281
308
|
|
282
309
|
token :Heredoc, contents
|
283
310
|
consumed_length
|
311
|
+
else
|
312
|
+
did_not_match
|
284
313
|
end
|
285
314
|
end
|
286
315
|
|
@@ -296,6 +325,8 @@ module Yap::Shell
|
|
296
325
|
result = process_internal_eval substr, consumed: consumed
|
297
326
|
token :InternalEval, result.str
|
298
327
|
return result.consumed_length
|
328
|
+
else
|
329
|
+
did_not_match
|
299
330
|
end
|
300
331
|
end
|
301
332
|
|
@@ -308,6 +339,8 @@ module Yap::Shell
|
|
308
339
|
elsif md=@chunk.match(REDIRECTION2)
|
309
340
|
token :Redirection, md[2], attrs: { target: md[3] }
|
310
341
|
md[0].length
|
342
|
+
else
|
343
|
+
did_not_match
|
311
344
|
end
|
312
345
|
end
|
313
346
|
|
@@ -315,14 +348,19 @@ module Yap::Shell
|
|
315
348
|
if md=@chunk.match(SUBGROUP)
|
316
349
|
token md[0], md[0]
|
317
350
|
return md[0].length
|
351
|
+
else
|
352
|
+
did_not_match
|
318
353
|
end
|
319
354
|
end
|
320
355
|
|
321
356
|
# Matches and consumes non-meaningful whitespace.
|
322
357
|
def whitespace_token
|
323
|
-
|
324
|
-
|
325
|
-
|
358
|
+
if md=WHITESPACE.match(@chunk)
|
359
|
+
input = md.to_a[0]
|
360
|
+
input.length
|
361
|
+
else
|
362
|
+
did_not_match
|
363
|
+
end
|
326
364
|
end
|
327
365
|
|
328
366
|
def argument_token
|
@@ -361,13 +399,18 @@ module Yap::Shell
|
|
361
399
|
token :Argument, str, attrs: attrs
|
362
400
|
characters_read
|
363
401
|
else
|
364
|
-
|
402
|
+
did_not_match
|
365
403
|
end
|
404
|
+
else
|
405
|
+
skipping
|
366
406
|
end
|
367
407
|
end
|
368
408
|
|
369
409
|
def assignment_token
|
370
|
-
if
|
410
|
+
if @looking_for_args
|
411
|
+
skipping
|
412
|
+
return
|
413
|
+
elsif md=@chunk.match(LH_ASSIGNMENT)
|
371
414
|
token :LValue, md[2]
|
372
415
|
consumed_length = md[1].length
|
373
416
|
i = consumed_length
|
@@ -382,6 +425,8 @@ module Yap::Shell
|
|
382
425
|
consumed_length += md[0].length
|
383
426
|
end
|
384
427
|
consumed_length
|
428
|
+
else
|
429
|
+
did_not_match
|
385
430
|
end
|
386
431
|
end
|
387
432
|
|
@@ -391,6 +436,8 @@ module Yap::Shell
|
|
391
436
|
LineContinuationFound,
|
392
437
|
"Expected more input, line continutation found"
|
393
438
|
)
|
439
|
+
else
|
440
|
+
did_not_match
|
394
441
|
end
|
395
442
|
end
|
396
443
|
|
@@ -411,6 +458,8 @@ module Yap::Shell
|
|
411
458
|
@looking_for_args = false
|
412
459
|
token :Pipe, md[0]
|
413
460
|
md[0].length
|
461
|
+
else
|
462
|
+
did_not_match
|
414
463
|
end
|
415
464
|
end
|
416
465
|
|
@@ -423,7 +472,9 @@ module Yap::Shell
|
|
423
472
|
else
|
424
473
|
token :Command, result.str
|
425
474
|
end
|
426
|
-
|
475
|
+
result.consumed_length
|
476
|
+
else
|
477
|
+
did_not_match
|
427
478
|
end
|
428
479
|
end
|
429
480
|
|
@@ -446,7 +497,9 @@ module Yap::Shell
|
|
446
497
|
token :EndCommandSubstitution, delimiter
|
447
498
|
end
|
448
499
|
|
449
|
-
|
500
|
+
consumed_length_so_far + append_result.consumed_length
|
501
|
+
else
|
502
|
+
did_not_match
|
450
503
|
end
|
451
504
|
end
|
452
505
|
|
@@ -512,37 +565,57 @@ module Yap::Shell
|
|
512
565
|
i = delimiter.length # start string matching after our delimiter
|
513
566
|
result_str = ''
|
514
567
|
|
568
|
+
if indent == 0
|
569
|
+
debug_log "##{__callee__} input_str=#{input_str.inspect} delimiter=#{delimiter.inspect} start_position=#{i}"
|
570
|
+
indent += 1
|
571
|
+
else
|
572
|
+
debug_log "#{' ' * indent}##{__callee__} input_str=#{input_str.inspect} delimiter=#{delimiter.inspect} start_position=#{i}"
|
573
|
+
indent += 1
|
574
|
+
end
|
575
|
+
indent_str = ' ' * indent
|
576
|
+
|
515
577
|
loop do
|
516
578
|
chunk = input_str[i..-1]
|
517
579
|
|
518
|
-
puts "#{' '*indent}I: #{i}" if ENV["DEBUG"]
|
519
|
-
|
520
580
|
if i >= input_str.length
|
521
|
-
|
581
|
+
debug_log "#{indent_str}found unterminated string, raising error"
|
522
582
|
raise NonterminatedString, "Expected to find #{delimiter} in:\n #{input_str}"
|
523
|
-
return OpenStruct.new(str:result_str, consumed_length: input_str.length)
|
524
583
|
end
|
525
584
|
|
526
585
|
if chunk.start_with?(nested_delimiter) # we found a nested escaped string
|
527
|
-
|
586
|
+
debug_log "#{indent_str}nested string found in #{chunk.inspect}"
|
528
587
|
result = process_string(chunk[0..-1], nested_delimiter, indent+2)
|
529
588
|
result_str << [delimiter, result.str, delimiter].join
|
530
|
-
|
531
|
-
|
589
|
+
debug_log "#{indent_str}nested string found was #{result.inspect}"
|
532
590
|
i += result.consumed_length
|
533
591
|
|
534
592
|
elsif chunk.start_with?(delimiter) # we found the end of our current nested escaped string
|
535
|
-
|
593
|
+
debug_log "#{indent_str}found the end of the string making string: #{result_str.inspect}"
|
536
594
|
return OpenStruct.new(str:result_str, consumed_length: i+delimiter.length)
|
537
595
|
|
538
596
|
else
|
539
597
|
char = input_str[i]
|
540
598
|
result_str << char
|
541
|
-
|
599
|
+
debug_log "#{indent_str}consuming character #{char} at position #{i}"
|
542
600
|
i += 1
|
543
601
|
end
|
544
602
|
end
|
545
603
|
end
|
546
604
|
|
605
|
+
def debug_log(message)
|
606
|
+
Treefell['lexer'].puts message
|
607
|
+
end
|
608
|
+
|
609
|
+
def did_not_match
|
610
|
+
calling_method = caller[0][/`.*'/][1..-2]
|
611
|
+
debug_log "##{calling_method} didn't match: #{@chunk.inspect}"
|
612
|
+
nil
|
613
|
+
end
|
614
|
+
|
615
|
+
def skipping
|
616
|
+
calling_method = caller[0][/`.*'/][1..-2]
|
617
|
+
debug_log "##{calling_method} is being skipped"
|
618
|
+
nil
|
619
|
+
end
|
547
620
|
end
|
548
621
|
end
|
data/lib/yap/shell/parser.rb
CHANGED
@@ -5,20 +5,33 @@ module Yap
|
|
5
5
|
module Parser
|
6
6
|
class ParseError < ::StandardError ; end
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
class << self
|
9
|
+
def parse(input)
|
10
|
+
debug_log "#parse entry with: #{input.inspect}"
|
11
|
+
Yap::Shell::ParserImpl.new.parse(input).tap do |results|
|
12
|
+
debug_log "#parse exit returning: #{results.inspect}"
|
13
|
+
end
|
14
|
+
rescue Racc::ParseError => ex
|
15
|
+
raise ParseError, "Message: #{ex.message}\nInput: #{input}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def each_command_substitution_for(input, &blk)
|
19
|
+
Yap::Shell::Parser::Lexer.new.each_command_substitution_for(input, &blk)
|
20
|
+
end
|
13
21
|
|
14
|
-
|
15
|
-
|
22
|
+
private
|
23
|
+
|
24
|
+
def debug_log(message)
|
25
|
+
Treefell['parser'].puts message
|
26
|
+
end
|
16
27
|
end
|
28
|
+
|
17
29
|
end
|
18
30
|
end
|
19
31
|
end
|
20
32
|
|
21
33
|
$LOAD_PATH.unshift File.dirname(__FILE__) + "/../../"
|
34
|
+
require 'treefell'
|
22
35
|
require 'yap/shell/parser/lexer'
|
23
36
|
require 'yap/shell/parser/nodes'
|
24
37
|
require 'yap/shell/parser_impl'
|
data/yap-shell-parser.gemspec
CHANGED
@@ -19,6 +19,8 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
20
|
spec.require_paths = ["lib"]
|
21
21
|
|
22
|
+
spec.add_dependency "treefell", "~> 0.2.3"
|
23
|
+
|
22
24
|
spec.add_development_dependency "bundler", "~> 1.7"
|
23
25
|
spec.add_development_dependency "rake", "~> 10.0"
|
24
26
|
spec.add_development_dependency "rspec", "~> 3.2"
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yap-shell-parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Zach Dennis
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-05-
|
11
|
+
date: 2016-05-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: treefell
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.2.3
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.2.3
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|