ebnf 0.2.2 → 0.2.3
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 +8 -8
- data/VERSION +1 -1
- data/lib/ebnf/ll1/lexer.rb +1 -4
- data/lib/ebnf/ll1/parser.rb +73 -41
- data/lib/ebnf/ll1/scanner.rb +10 -10
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NDg4MzMwZTA0Yzg3MzY5Y2UyZDMwMWI2ZWRiODNjZWZjZmU5NGRlZQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NzA2ODg3ZTI1NzIwNjVjNmE1YWJjMDYzNTEyNjI1NGIzZWI5OTg1ZQ==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
N2FjYTRhNzI5NDFkZWI3OTNiOWFkNTNmYWY5NjUwMjA4YTM0ZmNiZTQ5NDYy
|
10
|
+
MjFjODYxODc1MzRjMTZjNGM0N2U4NDk2NTM2ZjM0MmY0ZGI3ZDE3OTg3OWFi
|
11
|
+
NjQwYTdjNzcxYTc3ZWJmYzcyMzlmOWJiZDlmZjc3YTJiOWVkODA=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ODVmZDZlMjVkMjY0ZDkwYWFiZGY4OGE3ZTRhNDQzZWRiZDlkZTQzODQ4ZWMw
|
14
|
+
MTZkZGMzNWYzZTMxNDc0MDc3YWFkNmU2NjExNWM2ZTkzOTJlZWE0MDQ1Yzdm
|
15
|
+
N2RmOTU5NGFhZTVlZDEwYzhlMjJjMDNhYmIwNDkyOTc3ZGVkNDQ=
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.3
|
data/lib/ebnf/ll1/lexer.rb
CHANGED
@@ -135,10 +135,7 @@ module EBNF::LL1
|
|
135
135
|
raise Error, "Terminal patterns not defined" unless @terminals && @terminals.length > 0
|
136
136
|
|
137
137
|
@lineno = 1
|
138
|
-
@scanner = Scanner.new(input)
|
139
|
-
string.force_encoding(Encoding::UTF_8) if string.respond_to?(:force_encoding)
|
140
|
-
string
|
141
|
-
end
|
138
|
+
@scanner = Scanner.new(input)
|
142
139
|
end
|
143
140
|
|
144
141
|
##
|
data/lib/ebnf/ll1/parser.rb
CHANGED
@@ -193,6 +193,8 @@ module EBNF::LL1
|
|
193
193
|
# Show progress of parser productions
|
194
194
|
# @option options [Boolean] :debug
|
195
195
|
# Detailed debug output
|
196
|
+
# @option options [Boolean] :reset_on_start
|
197
|
+
# Reset the parser state if the start token set with `prod` is found in a production. This reduces the production stack depth growth, which is appropriate for some grammars.
|
196
198
|
# @yield [context, *data]
|
197
199
|
# Yields for to return data to parser
|
198
200
|
# @yieldparam [:statement, :trace] context
|
@@ -227,6 +229,15 @@ module EBNF::LL1
|
|
227
229
|
todo_stack.last[:terms] = []
|
228
230
|
cur_prod = todo_stack.last[:prod]
|
229
231
|
|
232
|
+
# If cur_prod is the starting production, we can reset the stack
|
233
|
+
# to the beginning to avoid excessive growth in the production
|
234
|
+
# stack
|
235
|
+
if options[:reset_on_start] && cur_prod == prod
|
236
|
+
todo_stack = [{:prod => prod, :terms => []}]
|
237
|
+
@productions = []
|
238
|
+
@prod_data = [{}]
|
239
|
+
end
|
240
|
+
|
230
241
|
# Get this first valid token appropriate for the stacked productions,
|
231
242
|
# skipping invalid tokens until either a valid token is found (from @first),
|
232
243
|
# or a token appearing in @follow appears.
|
@@ -239,11 +250,11 @@ module EBNF::LL1
|
|
239
250
|
"prod #{cur_prod.inspect}, " +
|
240
251
|
"depth #{depth}"
|
241
252
|
end
|
242
|
-
|
253
|
+
|
243
254
|
# Got an opened production
|
244
255
|
onStart(cur_prod)
|
245
256
|
break if token.nil?
|
246
|
-
|
257
|
+
|
247
258
|
if prod_branch = @branch[cur_prod]
|
248
259
|
@recovering = false
|
249
260
|
sequence = prod_branch[token.representation]
|
@@ -304,7 +315,6 @@ module EBNF::LL1
|
|
304
315
|
(@recovering && @follow.fetch(terms.last, []).none? {|t| (token || :_eps) == t}))
|
305
316
|
debug("parse(pop)", :level => 2) {"todo #{todo_stack.last.inspect}, depth #{depth}"}
|
306
317
|
if terms.empty?
|
307
|
-
prod = todo_stack.last[:prod]
|
308
318
|
todo_stack.pop
|
309
319
|
onFinish
|
310
320
|
else
|
@@ -483,21 +493,6 @@ module EBNF::LL1
|
|
483
493
|
token
|
484
494
|
end
|
485
495
|
|
486
|
-
##
|
487
|
-
# @param [String] node Relevant location associated with message
|
488
|
-
# @param [String] message Error string
|
489
|
-
# @param [Hash] options
|
490
|
-
# @option options [URI, #to_s] :production
|
491
|
-
# @option options [Token] :token
|
492
|
-
def error(node, message, options = {})
|
493
|
-
message += ", found #{options[:token].representation.inspect}" if options[:token]
|
494
|
-
message += " at line #{@lineno}" if @lineno
|
495
|
-
message += ", production = #{options[:production].inspect}" if options[:production]
|
496
|
-
@error_log << message unless @recovering
|
497
|
-
@recovering = true
|
498
|
-
debug(node, message, options.merge(:level => 0))
|
499
|
-
end
|
500
|
-
|
501
496
|
##
|
502
497
|
# Return the next token, entering error recovery if the token is invalid
|
503
498
|
#
|
@@ -521,6 +516,21 @@ module EBNF::LL1
|
|
521
516
|
token
|
522
517
|
end
|
523
518
|
|
519
|
+
##
|
520
|
+
# @param [String] node Relevant location associated with message
|
521
|
+
# @param [String] message Error string
|
522
|
+
# @param [Hash] options
|
523
|
+
# @option options [URI, #to_s] :production
|
524
|
+
# @option options [Token] :token
|
525
|
+
def error(node, message, options = {})
|
526
|
+
message += ", found #{options[:token].representation.inspect}" if options[:token]
|
527
|
+
message += " at line #{@lineno}" if @lineno
|
528
|
+
message += ", production = #{options[:production].inspect}" if options[:production]
|
529
|
+
@error_log << message unless @recovering
|
530
|
+
@recovering = true
|
531
|
+
debug(node, message, options.merge(:level => 0))
|
532
|
+
end
|
533
|
+
|
524
534
|
##
|
525
535
|
# Progress output when parsing
|
526
536
|
# param [String] node Relevant location associated with message
|
@@ -535,35 +545,57 @@ module EBNF::LL1
|
|
535
545
|
message = args.join(",")
|
536
546
|
depth = options[:depth] || self.depth
|
537
547
|
message += yield.to_s if block_given?
|
538
|
-
|
539
|
-
return debug(node, message, {:level => 0}.merge(options))
|
540
|
-
else
|
541
|
-
$stderr.puts("[#{@lineno}]#{' ' * depth}#{node}: #{message}")
|
542
|
-
end
|
548
|
+
debug(node, message, options.merge(:level => 1))
|
543
549
|
end
|
544
550
|
|
545
551
|
##
|
546
|
-
# Progress output when debugging
|
547
|
-
#
|
548
|
-
#
|
549
|
-
#
|
550
|
-
#
|
551
|
-
#
|
552
|
+
# Progress output when debugging.
|
553
|
+
# Captures output to `@options[:debug]` if it is an array.
|
554
|
+
# Otherwise, if `@options[:debug]` is set, or
|
555
|
+
# `@options[:progress]` is set and `:level` <= 1, or
|
556
|
+
# `@options[:validate]` is set and `:level` == 0 output
|
557
|
+
# to standard error.
|
558
|
+
#
|
559
|
+
# @overload debug(node, message)
|
560
|
+
# @param [String] node Relevant location associated with message
|
561
|
+
# @param [String] message ("")
|
562
|
+
# @param [Hash] options
|
563
|
+
# @option options [Integer] :depth
|
564
|
+
# Recursion depth for indenting output
|
565
|
+
# @option options [Integer] :level
|
566
|
+
# Debug level, `0` for errors, `1` for progress, anything else
|
567
|
+
# for debug output.
|
568
|
+
#
|
569
|
+
# @overload debug(message)
|
570
|
+
# @param [String] node Relevant location associated with message
|
571
|
+
# @param [Hash] options
|
572
|
+
# @option options [Integer] :depth
|
573
|
+
# Recursion depth for indenting output
|
574
|
+
# @option options [Integer] :level
|
575
|
+
# Debug level, `0` for errors, `1` for progress, anything else
|
576
|
+
# for debug output.
|
552
577
|
# @yieldreturn [String] added to message
|
553
|
-
def debug(
|
554
|
-
|
555
|
-
debug_level = options.fetch(:level,
|
556
|
-
return unless debug_level <= DEBUG_LEVEL
|
578
|
+
def debug(*args)
|
579
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
580
|
+
debug_level = options.fetch(:level, 2)
|
581
|
+
return unless @options[:debug] && debug_level <= DEBUG_LEVEL ||
|
582
|
+
@options[:progress] && debug_level <= 1 ||
|
583
|
+
@options[:validate] && debug_level == 0
|
557
584
|
depth = options[:depth] || self.depth
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
when :yield
|
585
|
+
d_str = depth > 20 ? ' ' * 20 + '+' : ' ' * depth
|
586
|
+
args << yield if block_given?
|
587
|
+
message = "#{args.join(': ')}"
|
588
|
+
str = "[#{@lineno}](#{debug_level})#{d_str}#{message}"
|
589
|
+
@options[:debug] << str if @options[:debug].is_a?(Array)
|
590
|
+
case
|
591
|
+
when @options[:yield]
|
566
592
|
@parse_callback.call(:trace, node, message, options)
|
593
|
+
when @options[:debug] == true
|
594
|
+
$stderr.puts str
|
595
|
+
when @options[:progress] && debug_level <= 1
|
596
|
+
$stderr.puts str
|
597
|
+
when @options[:validate] && debug_level == 0
|
598
|
+
$stderr.puts str
|
567
599
|
end
|
568
600
|
end
|
569
601
|
|
data/lib/ebnf/ll1/scanner.rb
CHANGED
@@ -24,12 +24,8 @@ module EBNF::LL1
|
|
24
24
|
# @param [Hash{Symbol => Object}] options
|
25
25
|
# @option options[Integer] :high_water (HIGH_WATER)
|
26
26
|
# @option options[Integer] :low_water (LOW_WATER)
|
27
|
-
# @yield [string]
|
28
|
-
# @yieldparam [String] string data read from input file
|
29
|
-
# @yieldreturn [String] replacement read data, useful for decoding escapes.
|
30
27
|
# @return [Scanner]
|
31
|
-
def initialize(input, options = {}
|
32
|
-
@block = block
|
28
|
+
def initialize(input, options = {})
|
33
29
|
@options = options.merge(:high_water => HIGH_WATER, :low_water => LOW_WATER)
|
34
30
|
|
35
31
|
if input.respond_to?(:read)
|
@@ -48,7 +44,7 @@ module EBNF::LL1
|
|
48
44
|
# @return [String]
|
49
45
|
def rest
|
50
46
|
feed_me
|
51
|
-
super
|
47
|
+
encode_utf8 super
|
52
48
|
end
|
53
49
|
|
54
50
|
##
|
@@ -82,7 +78,7 @@ module EBNF::LL1
|
|
82
78
|
# @return [String]
|
83
79
|
def scan(pattern)
|
84
80
|
feed_me
|
85
|
-
super
|
81
|
+
encode_utf8 super
|
86
82
|
end
|
87
83
|
|
88
84
|
private
|
@@ -91,11 +87,15 @@ module EBNF::LL1
|
|
91
87
|
if rest_size < @options[:low_water] && @input && !@input.eof?
|
92
88
|
# Read up to high-water mark ensuring we're at an end of line
|
93
89
|
diff = @options[:high_water] - rest_size
|
94
|
-
string = @input.read(diff)
|
95
|
-
string << @input.gets unless @input.eof?
|
96
|
-
string = @block.call(string) if @block
|
90
|
+
string = encode_utf8(@input.read(diff))
|
91
|
+
string << encode_utf8(@input.gets) unless @input.eof?
|
97
92
|
self << string if string
|
98
93
|
end
|
99
94
|
end
|
95
|
+
|
96
|
+
# Perform UTF-8 encoding of input
|
97
|
+
def encode_utf8(string)
|
98
|
+
string.respond_to?(:force_encoding) ? string.force_encoding(Encoding::UTF_8) : string
|
99
|
+
end
|
100
100
|
end
|
101
101
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ebnf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gregg Kellogg
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-03-
|
11
|
+
date: 2013-03-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sxp
|