ebnf 1.1.3 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/bin/ebnf +3 -3
- data/lib/ebnf.rb +2 -2
- data/lib/ebnf/ll1.rb +7 -3
- data/lib/ebnf/ll1/lexer.rb +17 -10
- data/lib/ebnf/ll1/parser.rb +19 -12
- data/lib/ebnf/ll1/scanner.rb +3 -3
- data/lib/ebnf/rule.rb +1 -0
- metadata +18 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aae4c0b2a8f6d03654bc5436b36c90e577669c41ea4df25d881be3aef86e5ace
|
4
|
+
data.tar.gz: 7f1b7fe448ae87f3755e6da4fc0faf47dbb3d3b573a3e4a8be9b3066f0fac6fa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6d0f441731842af8ac38f98352b96a47cf6810bfe81ce620f8ef57af87ce6d65c679d88903c35dbce99617b24bdea8fbb70a23d4873d941ae151275a11561627
|
7
|
+
data.tar.gz: f19f527e041a8f1c48da918497660466c5df71a02077e2183472b157a8611cbf87903fe2b6858e889c119211a7fedb279ad4889d811bec5d6132dd9287d74314
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.2.0
|
data/bin/ebnf
CHANGED
@@ -75,19 +75,19 @@ end
|
|
75
75
|
|
76
76
|
input = File.open(ARGV[0]) if ARGV[0]
|
77
77
|
|
78
|
-
ebnf = EBNF.parse(input || STDIN, options)
|
78
|
+
ebnf = EBNF.parse(input || STDIN, **options)
|
79
79
|
ebnf.make_bnf if options[:bnf] || options[:ll1]
|
80
80
|
if options[:ll1]
|
81
81
|
ebnf.first_follow(*options[:ll1])
|
82
82
|
ebnf.build_tables
|
83
|
-
|
83
|
+
end
|
84
84
|
|
85
85
|
res = case options[:output_format]
|
86
86
|
when :ebnf then ebnf.to_s
|
87
87
|
when :html then ebnf.to_html
|
88
88
|
when :sxp then ebnf.to_sxp
|
89
89
|
when :ttl then ebnf.to_ttl(options[:prefix], options[:namespace])
|
90
|
-
when :rb then ebnf.to_ruby(out,
|
90
|
+
when :rb then ebnf.to_ruby(out, grammarFile: ARGV[0], **options)
|
91
91
|
else ebnf.ast.inspect
|
92
92
|
end
|
93
93
|
|
data/lib/ebnf.rb
CHANGED
@@ -17,7 +17,7 @@ module EBNF
|
|
17
17
|
# @param [Hash{Symbol => Object}] options
|
18
18
|
# @return [EBNF::Base]
|
19
19
|
# @raise [Exception] on invalid input
|
20
|
-
def self.parse(input, options
|
21
|
-
query = ::EBNF::Base.new(input, options)
|
20
|
+
def self.parse(input, **options)
|
21
|
+
query = ::EBNF::Base.new(input, **options)
|
22
22
|
end
|
23
23
|
end
|
data/lib/ebnf/ll1.rb
CHANGED
@@ -168,6 +168,10 @@ module EBNF
|
|
168
168
|
progress("first_follow") {"(#{ittr}) firsts #{firsts}, follows #{follows}"}
|
169
169
|
ittr += 1
|
170
170
|
end while (firsts + follows) > 0
|
171
|
+
|
172
|
+
debug("Fi.2-post: non-terminals without first") do
|
173
|
+
ast.reject(&:terminal?).reject(&:first).map(&:sym)
|
174
|
+
end if ast.reject(&:terminal?).any? {|r| r.first.nil?}
|
171
175
|
end
|
172
176
|
end
|
173
177
|
|
@@ -287,16 +291,16 @@ module EBNF
|
|
287
291
|
|
288
292
|
if rule.expr.first == :matches
|
289
293
|
debug("prod") {"Rule is regexp: #{rule}"}
|
290
|
-
|
291
|
-
error("No record of what token #{lhs} can start with") unless rule.first
|
292
294
|
return
|
293
295
|
end
|
294
296
|
|
297
|
+
error("No record of what token #{lhs.inspect} can start with") unless rule.first
|
298
|
+
|
295
299
|
if rule.alt?
|
296
300
|
# A First/Follow conflict appears when _eps is in the first
|
297
301
|
# of one rule and there is a token in the first and
|
298
302
|
# follow of the same rule
|
299
|
-
if rule.first.include?(:_eps) && !(overlap = ((rule.first & (rule.follow || [])) - [:eps])).empty?
|
303
|
+
if Array(rule.first).include?(:_eps) && !(overlap = ((Array(rule.first) & (rule.follow || [])) - [:eps])).empty?
|
300
304
|
error("First/Follow Conflict: #{overlap.first.inspect} is both first and follow of #{rule.sym}")
|
301
305
|
end
|
302
306
|
|
data/lib/ebnf/ll1/lexer.rb
CHANGED
@@ -98,8 +98,8 @@ module EBNF::LL1
|
|
98
98
|
# @yieldparam [Lexer] lexer
|
99
99
|
# @return [Lexer]
|
100
100
|
# @raise [Lexer::Error] on invalid input
|
101
|
-
def self.tokenize(input, terminals, options
|
102
|
-
lexer = self.new(input, terminals, options)
|
101
|
+
def self.tokenize(input, terminals, **options, &block)
|
102
|
+
lexer = self.new(input, terminals, **options)
|
103
103
|
block_given? ? block.call(lexer) : lexer
|
104
104
|
end
|
105
105
|
|
@@ -115,17 +115,24 @@ module EBNF::LL1
|
|
115
115
|
# Whitespace between tokens, including comments
|
116
116
|
# @option options[Integer] :high_water passed to scanner
|
117
117
|
# @option options[Integer] :low_water passed to scanner
|
118
|
-
def initialize(input = nil, terminals = nil, options
|
118
|
+
def initialize(input = nil, terminals = nil, **options)
|
119
119
|
@options = options.dup
|
120
120
|
@whitespace = @options[:whitespace]
|
121
121
|
@terminals = terminals.map do |term|
|
122
|
-
term.is_a?(Array)
|
122
|
+
if term.is_a?(Array) && term.length ==3
|
123
|
+
# Last element is options
|
124
|
+
Terminal.new(term[0], term[1], **term[2])
|
125
|
+
elsif term.is_a?(Array)
|
126
|
+
Terminal.new(*term)
|
127
|
+
else
|
128
|
+
term
|
129
|
+
end
|
123
130
|
end
|
124
131
|
|
125
132
|
raise Error, "Terminal patterns not defined" unless @terminals && @terminals.length > 0
|
126
133
|
|
127
134
|
@lineno = 1
|
128
|
-
@scanner = Scanner.new(input, options)
|
135
|
+
@scanner = Scanner.new(input, **options)
|
129
136
|
end
|
130
137
|
|
131
138
|
##
|
@@ -300,7 +307,7 @@ module EBNF::LL1
|
|
300
307
|
# Cause strings and codepoints to be unescaped.
|
301
308
|
# @option options [Regexp] :partial_regexp
|
302
309
|
# A regular expression matching the beginning of this terminal; useful for terminals that match things longer than the scanner low water mark.
|
303
|
-
def initialize(type, regexp, options
|
310
|
+
def initialize(type, regexp, **options)
|
304
311
|
@type, @regexp, @options = type, regexp, options
|
305
312
|
@partial_regexp = options[:partial_regexp]
|
306
313
|
@map = options.fetch(:map, {})
|
@@ -353,8 +360,8 @@ module EBNF::LL1
|
|
353
360
|
# Scanner instance with access to matched groups
|
354
361
|
# @param [Hash{Symbol => Object}] options
|
355
362
|
# @return [Token]
|
356
|
-
def token(type, value, options
|
357
|
-
Token.new(type, value,
|
363
|
+
def token(type, value, **options)
|
364
|
+
Token.new(type, value, lineno: lineno, **options)
|
358
365
|
end
|
359
366
|
|
360
367
|
##
|
@@ -398,7 +405,7 @@ module EBNF::LL1
|
|
398
405
|
# @param [String] value
|
399
406
|
# @param [Hash{Symbol => Object}] options
|
400
407
|
# @option options [Integer] :lineno (nil)
|
401
|
-
def initialize(type, value, options
|
408
|
+
def initialize(type, value, **options)
|
402
409
|
@type = type.to_s.to_sym if type
|
403
410
|
@value = value.to_s
|
404
411
|
@options = options.dup
|
@@ -514,7 +521,7 @@ module EBNF::LL1
|
|
514
521
|
# @option options [String] :input (nil)
|
515
522
|
# @option options [String] :token (nil)
|
516
523
|
# @option options [Integer] :lineno (nil)
|
517
|
-
def initialize(message, options
|
524
|
+
def initialize(message, **options)
|
518
525
|
@input = options[:input]
|
519
526
|
@token = options[:token]
|
520
527
|
@lineno = options[:lineno]
|
data/lib/ebnf/ll1/parser.rb
CHANGED
@@ -51,10 +51,10 @@ module EBNF::LL1
|
|
51
51
|
# @yieldparam [Proc] block
|
52
52
|
# Block passed to initialization for yielding to calling parser.
|
53
53
|
# Should conform to the yield specs for #initialize
|
54
|
-
def terminal(term, regexp, options
|
54
|
+
def terminal(term, regexp, **options, &block)
|
55
55
|
@patterns ||= []
|
56
56
|
# Passed in order to define evaulation sequence
|
57
|
-
@patterns << EBNF::LL1::Lexer::Terminal.new(term, regexp, options)
|
57
|
+
@patterns << EBNF::LL1::Lexer::Terminal.new(term, regexp, **options)
|
58
58
|
@terminal_handlers ||= {}
|
59
59
|
@terminal_handlers[term] = block if block_given?
|
60
60
|
end
|
@@ -122,7 +122,14 @@ module EBNF::LL1
|
|
122
122
|
|
123
123
|
def method_missing(method, *args, &block)
|
124
124
|
if @delegate ||= nil
|
125
|
-
|
125
|
+
# special handling when last arg is **options
|
126
|
+
params = @delegate.method(method).parameters
|
127
|
+
if params.any? {|t, _| t == :keyrest} && args.last.is_a?(Hash)
|
128
|
+
opts = args.pop
|
129
|
+
@delegate.send(method, *args, **opts, &block)
|
130
|
+
else
|
131
|
+
@delegate.send(method, *args, &block)
|
132
|
+
end
|
126
133
|
else
|
127
134
|
super
|
128
135
|
end
|
@@ -219,7 +226,7 @@ module EBNF::LL1
|
|
219
226
|
# or errors raised during processing callbacks. Internal
|
220
227
|
# errors are raised using {Error}.
|
221
228
|
# @see http://cs.adelaide.edu.au/~charles/lt/Lectures/07-ErrorRecovery.pdf
|
222
|
-
def parse(input = nil, start = nil, options
|
229
|
+
def parse(input = nil, start = nil, **options, &block)
|
223
230
|
@options = options.dup
|
224
231
|
@options[:debug] ||= case
|
225
232
|
when @options[:progress] then 2
|
@@ -229,7 +236,7 @@ module EBNF::LL1
|
|
229
236
|
@first = options[:first] ||= {}
|
230
237
|
@follow = options[:follow] ||= {}
|
231
238
|
@cleanup = options[:cleanup] ||= {}
|
232
|
-
@lexer = input.is_a?(Lexer) ? input : Lexer.new(input, self.class.patterns,
|
239
|
+
@lexer = input.is_a?(Lexer) ? input : Lexer.new(input, self.class.patterns, **@options)
|
233
240
|
@productions = []
|
234
241
|
@parse_callback = block
|
235
242
|
@recovering = false
|
@@ -467,7 +474,7 @@ module EBNF::LL1
|
|
467
474
|
# @option options [URI, #to_s] :production
|
468
475
|
# @option options [Token] :token
|
469
476
|
# @see {#debug}
|
470
|
-
def error(node, message, options
|
477
|
+
def error(node, message, **options)
|
471
478
|
lineno = @lineno || (options[:token].lineno if options[:token].respond_to?(:lineno))
|
472
479
|
m = "ERROR "
|
473
480
|
m += "[line: #{lineno}] " if lineno
|
@@ -476,7 +483,7 @@ module EBNF::LL1
|
|
476
483
|
m += ", production = #{options[:production].inspect}" if options[:production]
|
477
484
|
@error_log << m unless @recovering
|
478
485
|
@recovering = true
|
479
|
-
debug(node, m,
|
486
|
+
debug(node, m, level: 0, **options)
|
480
487
|
if options[:raise] || @options[:validate]
|
481
488
|
raise Error.new(m, lineno: lineno, token: options[:token], production: options[:production])
|
482
489
|
end
|
@@ -491,20 +498,20 @@ module EBNF::LL1
|
|
491
498
|
# @option options [URI, #to_s] :production
|
492
499
|
# @option options [Token] :token
|
493
500
|
# @see {#debug}
|
494
|
-
def warn(node, message, options
|
501
|
+
def warn(node, message, **options)
|
495
502
|
m = "WARNING "
|
496
503
|
m += "[line: #{@lineno}] " if @lineno
|
497
504
|
m += message
|
498
505
|
m += " (found #{options[:token].inspect})" if options[:token]
|
499
506
|
m += ", production = #{options[:production].inspect}" if options[:production]
|
500
507
|
@error_log << m unless @recovering
|
501
|
-
debug(node, m,
|
508
|
+
debug(node, m, level: 1, **options)
|
502
509
|
end
|
503
510
|
|
504
511
|
##
|
505
512
|
# Progress output when parsing. Passed as level `2` debug messages.
|
506
513
|
#
|
507
|
-
# @overload progress(node, message, options)
|
514
|
+
# @overload progress(node, message, **options)
|
508
515
|
# @param [String] node Relevant location associated with message
|
509
516
|
# @param [String] message ("")
|
510
517
|
# @param [Hash] options
|
@@ -526,7 +533,7 @@ module EBNF::LL1
|
|
526
533
|
# if `@options[:debug]` is an Integer, the call is aborted if the
|
527
534
|
# `:level` option is less than than `:level`.
|
528
535
|
#
|
529
|
-
# @overload debug(node, message, options)
|
536
|
+
# @overload debug(node, message, **options)
|
530
537
|
# @param [Array<String>] args Relevant location associated with message
|
531
538
|
# @param [Hash] options
|
532
539
|
# @option options [Integer] :depth
|
@@ -751,7 +758,7 @@ module EBNF::LL1
|
|
751
758
|
# @option options [Symbol] :production (nil)
|
752
759
|
# @option options [String] :token (nil)
|
753
760
|
# @option options [Integer] :lineno (nil)
|
754
|
-
def initialize(message, options
|
761
|
+
def initialize(message, **options)
|
755
762
|
@production = options[:production]
|
756
763
|
@token = options[:token]
|
757
764
|
@lineno = options[:lineno] || (@token.lineno if @token.respond_to?(:lineno))
|
data/lib/ebnf/ll1/scanner.rb
CHANGED
@@ -20,11 +20,11 @@ module EBNF::LL1
|
|
20
20
|
##
|
21
21
|
# If we don't have an IO input, simply use StringScanner directly
|
22
22
|
# @private
|
23
|
-
def self.new(input, options
|
23
|
+
def self.new(input, **options)
|
24
24
|
input ||= ""
|
25
25
|
if input.respond_to?(:read)
|
26
26
|
scanner = self.allocate
|
27
|
-
scanner.send(:initialize, input, options)
|
27
|
+
scanner.send(:initialize, input, **options)
|
28
28
|
else
|
29
29
|
if input.encoding != Encoding::UTF_8
|
30
30
|
input = input.dup if input.frozen?
|
@@ -42,7 +42,7 @@ module EBNF::LL1
|
|
42
42
|
# @option options[Integer] :high_water (HIGH_WATER)
|
43
43
|
# @option options[Integer] :low_water (LOW_WATER)
|
44
44
|
# @return [Scanner]
|
45
|
-
def initialize(input, options
|
45
|
+
def initialize(input, **options)
|
46
46
|
@options = options.merge(high_water: HIGH_WATER, low_water: LOW_WATER)
|
47
47
|
|
48
48
|
@input = input
|
data/lib/ebnf/rule.rb
CHANGED
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: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gregg Kellogg
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-12-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sxp
|
@@ -16,42 +16,42 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1.
|
19
|
+
version: '1.1'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '1.
|
26
|
+
version: '1.1'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rdf
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '3.
|
33
|
+
version: '3.1'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '3.
|
40
|
+
version: '3.1'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rdf-spec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '3.
|
47
|
+
version: '3.1'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '3.
|
54
|
+
version: '3.1'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: haml
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -72,56 +72,56 @@ dependencies:
|
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '3.
|
75
|
+
version: '3.9'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '3.
|
82
|
+
version: '3.9'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: rspec-its
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '1.
|
89
|
+
version: '1.3'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '1.
|
96
|
+
version: '1.3'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: yard
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: 0.9
|
103
|
+
version: '0.9'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: 0.9
|
110
|
+
version: '0.9'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: rake
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: '
|
117
|
+
version: '13.0'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: '
|
124
|
+
version: '13.0'
|
125
125
|
description: EBNF is a Ruby parser for W3C EBNF and a parser generator for compliant
|
126
126
|
LL(1) grammars.
|
127
127
|
email: public-rdf-ruby@w3.org
|
@@ -175,15 +175,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
175
175
|
requirements:
|
176
176
|
- - ">="
|
177
177
|
- !ruby/object:Gem::Version
|
178
|
-
version: 2.
|
178
|
+
version: '2.4'
|
179
179
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
180
180
|
requirements:
|
181
181
|
- - ">="
|
182
182
|
- !ruby/object:Gem::Version
|
183
183
|
version: '0'
|
184
184
|
requirements: []
|
185
|
-
|
186
|
-
rubygems_version: 2.7.6
|
185
|
+
rubygems_version: 3.0.6
|
187
186
|
signing_key:
|
188
187
|
specification_version: 4
|
189
188
|
summary: EBNF parser and parser generator.
|