ebnf 2.1.0 → 2.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dc55292610eb978d5751361069f3b993d35db3a597442e2027cf0fd2ff886ba5
4
- data.tar.gz: cc74cd0257a36fa3591f54becfdb51dfffbf44662598f2d67c6a36bf4e969e61
3
+ metadata.gz: 0ab4040409eda92f9a201dded001390d8b49d9e84b5c4811c1899f8e09f4833e
4
+ data.tar.gz: dfe6ff5a7b9bc499744cd76a813bbd951dcb6e5ed34ac6b60208c3543da124a7
5
5
  SHA512:
6
- metadata.gz: bf7c7df32e027a0739b4830651dcff1f4b5186ff2177e1f57b4e952db33619660c4025a29ffc8dba5c7d0f5f5b95f2cbd432a379bc2ffb02d22f7ec6913a48e2
7
- data.tar.gz: 909a8ff438172431054a33fb067198e32d98d5b88fa630978831af4f1dd728f0197512ee1f341667eb3039662db618122d7da5d0cc4cc55838625f685f7d7a9b
6
+ metadata.gz: 15add7561aca320bfc785472ce4fbfe4b4f90bd663452b0de86aa9642610f7dadbcd4a881ff94b38209173a4790b415543a406a547264909121118e66eb26e66
7
+ data.tar.gz: 187c9239e788592a88679d55531d6b642ac53c3d384b2591c703472b48c35d0fea93267069ce2f1cc5c2c5ac8b7a608d14484bc10ffbb6c555dd9ad597c0214d
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.1.0
1
+ 2.1.1
@@ -13,10 +13,17 @@
13
13
  doap:homepage <https://github.com/dryruby/ebnf> ;
14
14
  doap:license <https://unlicense.org/1.0/> ;
15
15
  doap:shortdesc "EBNF parser and parser generator"@en ;
16
- doap:description "EBNF is a Ruby parser for W3C EBNF and a parser generator for compliant LL(1) grammars."@en ;
16
+ doap:description "EBNF is a Ruby parser for W3C EBNF and a parser generator for PEG and LL(1). Also includes parsing modes for ISO EBNF and ABNF."@en ;
17
17
  doap:created "2011-08-29"^^xsd:date ;
18
18
  doap:programming-language "Ruby" ;
19
- doap:implements <http://dbpedia.org/resource/Compiler-compiler> ;
19
+ doap:implements <http://dbpedia.org/resource/Compiler-compiler>,
20
+ <https://en.wikipedia.org/wiki/LL_parser>,
21
+ <https://en.wikipedia.org/wiki/Parsing_expression_grammar>,
22
+ <https://pdos.csail.mit.edu/~baford/packrat/thesis/>,
23
+ <https://www.w3.org/TR/REC-xml/#sec-notation>,
24
+ <https://en.wikipedia.org/wiki/Backus–Naur_form>,
25
+ <https://www.iso.org/standard/26153.html>,
26
+ <https://www.rfc-editor.org/rfc/rfc5234>;
20
27
  doap:category <http://dbpedia.org/resource/Resource_Description_Framework>,
21
28
  <http://dbpedia.org/resource/Ruby_(programming_language)> ;
22
29
  doap:download-page <> ;
@@ -28,6 +35,6 @@
28
35
  doap:documenter <https://greggkellogg.net/foaf#me> ;
29
36
  foaf:maker <https://greggkellogg.net/foaf#me> ;
30
37
  dc:title "ebnf" ;
31
- dc:description "EBNF is a Ruby parser for W3C EBNF and a parser generator for compliant LL(1) grammars."@en ;
38
+ dc:description "EBNF is a Ruby parser for W3C EBNF and a parser generator for PEG and LL(1). Also includes parsing modes for ISO EBNF and ABNF."@en ;
32
39
  dc:date "2011-08-29"^^xsd:date ;
33
40
  dc:creator <https://greggkellogg.net/foaf#me> .
@@ -69,7 +69,6 @@ module EBNF::LL1
69
69
  # @return [String]
70
70
  def rest
71
71
  feed_me
72
- @lineno += 1 if eos?
73
72
  encode_utf8 super
74
73
  end
75
74
 
@@ -75,8 +75,6 @@ module EBNF::PEG
75
75
  # @option options [Hash{String => String}] :map ({})
76
76
  # A mapping from terminals, in lower-case form, to
77
77
  # their canonical value
78
- # @option options [Boolean] :unescape
79
- # Cause strings and codepoints to be unescaped.
80
78
  # @yield [value, prod]
81
79
  # @yieldparam [String] value
82
80
  # The scanned terminal value.
@@ -269,7 +267,8 @@ module EBNF::PEG
269
267
  # @param [String] message Error string
270
268
  # @param [Hash{Symbol => Object}] options
271
269
  # @option options [URI, #to_s] :production
272
- # @option options [Token] :token
270
+ # @option options [Boolean] :raise abort furhter processing
271
+ # @option options [Array] :backtrace state where error occured
273
272
  # @see #debug
274
273
  def error(node, message, **options)
275
274
  lineno = options[:lineno] || (scanner.lineno if scanner)
@@ -282,7 +281,11 @@ module EBNF::PEG
282
281
  @recovering = true
283
282
  debug(node, m, level: 3, **options)
284
283
  if options[:raise] || @options[:validate]
285
- raise Error.new(m, lineno: lineno, rest: options[:rest], production: options[:production])
284
+ raise Error.new(m,
285
+ lineno: lineno,
286
+ rest: options[:rest],
287
+ production: options[:production],
288
+ backtrace: options[:backtrace])
286
289
  end
287
290
  end
288
291
 
@@ -365,25 +368,27 @@ module EBNF::PEG
365
368
  @productions << prod
366
369
  debug("#{prod}(:start)", "",
367
370
  lineno: (scanner.lineno if scanner),
368
- pos: (scanner.pos if scanner),
369
- depth: (depth + 1)) {"#{prod}, pos: #{scanner ? scanner.pos : '?'}, rest: #{scanner ? scanner.rest[0..20].inspect : '?'}"}
371
+ pos: (scanner.pos if scanner)
372
+ ) do
373
+ "#{prod}, pos: #{scanner ? scanner.pos : '?'}, rest: #{scanner ? scanner.rest[0..20].inspect : '?'}"
374
+ end
370
375
  if handler
371
376
  # Create a new production data element, potentially allowing handler
372
377
  # to customize before pushing on the @prod_data stack
373
- data = {}
378
+ data = {_production: prod}
374
379
  begin
375
380
  self.class.eval_with_binding(self) {
376
381
  handler.call(data, @parse_callback)
377
382
  }
378
383
  rescue ArgumentError, Error => e
379
- error("start", "#{e.class}: #{e.message}", production: prod)
384
+ error("start", "#{e.class}: #{e.message}", production: prod, backtrace: e.backtrace)
380
385
  @recovering = false
381
386
  end
382
387
  @prod_data << data
383
388
  elsif self.class.production_handlers[prod]
384
389
  # Make sure we push as many was we pop, even if there is no
385
390
  # explicit start handler
386
- @prod_data << {}
391
+ @prod_data << {_production: prod}
387
392
  end
388
393
  return self.class.start_options.fetch(prod, {}) # any options on this production
389
394
  end
@@ -397,6 +402,9 @@ module EBNF::PEG
397
402
  prod = @productions.last
398
403
  handler, clear_packrat = self.class.production_handlers[prod]
399
404
  data = @prod_data.pop if handler || self.class.start_handlers[prod]
405
+ error("finish",
406
+ "prod_data production mismatch: expected #{prod.inspect}, got #{data[:_production].inspect}",
407
+ production: prod, prod_data: @prod_data) if data && prod != data[:_production]
400
408
  if handler && !@recovering && result != :unmatched
401
409
  # Pop production data element from stack, potentially allowing handler to use it
402
410
  result = begin
@@ -404,14 +412,13 @@ module EBNF::PEG
404
412
  handler.call(result, data, @parse_callback)
405
413
  }
406
414
  rescue ArgumentError, Error => e
407
- error("finish", "#{e.class}: #{e.message}", production: prod)
415
+ error("finish", "#{e.class}: #{e.message}", production: prod, backtrace: e.backtrace)
408
416
  @recovering = false
409
417
  end
410
418
  end
411
- progress("#{prod}(:finish)", "",
412
- depth: (depth + 1),
413
- lineno: (scanner.lineno if scanner),
414
- level: result == :unmatched ? 0 : 1) do
419
+ debug("#{prod}(:finish)", "",
420
+ lineno: (scanner.lineno if scanner),
421
+ level: result == :unmatched ? 0 : 1) do
415
422
  "#{result.inspect}@(#{scanner ? scanner.pos : '?'}), rest: #{scanner ? scanner.rest[0..20].inspect : '?'}"
416
423
  end
417
424
  self.clear_packrat if clear_packrat
@@ -433,12 +440,12 @@ module EBNF::PEG
433
440
  handler.call(value, parentProd, @parse_callback)
434
441
  }
435
442
  rescue ArgumentError, Error => e
436
- error("terminal", "#{e.class}: #{e.message}", value: value, production: prod)
443
+ error("terminal", "#{e.class}: #{e.message}", value: value, production: prod, backtrace: e.backtrace)
437
444
  @recovering = false
438
445
  end
439
446
  end
440
447
  progress("#{prod}(:terminal)", "",
441
- depth: (depth + 2),
448
+ depth: (depth + 1),
442
449
  lineno: (scanner.lineno if scanner),
443
450
  level: value == :unmatched ? 0 : 1) do
444
451
  "#{value.inspect}@(#{scanner ? scanner.pos : '?'})"
@@ -8,6 +8,7 @@ require "ostruct"
8
8
  module EBNF
9
9
  class Writer
10
10
  LINE_LENGTH = 80
11
+ LINE_LENGTH_HTML = 200
11
12
 
12
13
  # ASCII escape names
13
14
  ASCII_ESCAPE_NAMES = [
@@ -118,19 +119,21 @@ module EBNF
118
119
  lhs_fmt = "%<id>-#{max_id+2}s " + lhs_fmt
119
120
  lhs_length += max_id + 3
120
121
  end
121
- rhs_length = LINE_LENGTH - lhs_length
122
+ rhs_length = (html ? LINE_LENGTH_HTML : LINE_LENGTH) - lhs_length
122
123
 
123
124
  if html
124
125
  # Output as formatted HTML
125
126
  begin
126
127
  require 'erubis'
128
+ require 'htmlentities'
129
+ @coder = HTMLEntities.new
127
130
  eruby = Erubis::Eruby.new(ERB_DESC)
128
131
  formatted_rules = rules.map do |rule|
129
132
  if rule.kind == :terminals || rule.kind == :pass
130
133
  OpenStruct.new(id: ("@#{rule.kind}"),
131
134
  sym: nil,
132
135
  assign: nil,
133
- formatted: ("<strong>Productions for terminals</strong>" if rule.kind == :terminals))
136
+ formatted: ("<strong># Productions for terminals</strong>" if rule.kind == :terminals))
134
137
  else
135
138
  formatted_expr = self.send(format_meth, rule.expr)
136
139
  # Measure text without markup
@@ -151,7 +154,7 @@ module EBNF
151
154
  formatted.sub!(%r{\s*<code>\|</code>\s*}, '')
152
155
  (ndx > 0 ? (rule.alt? ? '|' : '') : '=')
153
156
  end
154
- lines << OpenStruct.new(id: ("[#{rule.id}]" if rule.id),
157
+ lines << OpenStruct.new(id: ((ndx == 0 ? "[#{rule.id}]" : "") if rule.id),
155
158
  sym: (rule.sym if ndx == 0 || format == :abnf),
156
159
  assign: assign,
157
160
  formatted: formatted)
@@ -171,7 +174,7 @@ module EBNF
171
174
  out.write eruby.evaluate(format: format, rules: formatted_rules)
172
175
  return
173
176
  rescue LoadError
174
- $stderr.puts "Generating HTML requires erubis gem to be loaded"
177
+ $stderr.puts "Generating HTML requires erubis and htmlentities gems to be loaded"
175
178
  end
176
179
  end
177
180
 
@@ -216,7 +219,7 @@ module EBNF
216
219
 
217
220
  # Format the expression part of a rule
218
221
  def format_ebnf(expr, sep: nil, embedded: false)
219
- return (@options[:html] ? %(<a href="#grammar-production-#{expr}">#{expr}</a>) : expr.to_s) if expr.is_a?(Symbol)
222
+ return (@options[:html] ? %(<a href="#grammar-production-#{@coder.encode expr}">#{@coder.encode expr}</a>) : expr.to_s) if expr.is_a?(Symbol)
220
223
  if expr.is_a?(String)
221
224
  return expr.length == 1 ?
222
225
  format_ebnf_char(expr) :
@@ -290,10 +293,10 @@ module EBNF
290
293
  # Format a single-character string, prefering hex for non-main ASCII
291
294
  def format_ebnf_char(c)
292
295
  case c.ord
293
- when (0x21) then (@options[:html] ? %("<code class="grammar-literal">#{c}</code>") : %{"#{c}"})
294
- when 0x22 then (@options[:html] ? %('<code class="grammar-literal">"</code>') : %{'"'})
295
- when (0x23..0x7e) then (@options[:html] ? %("<code class="grammar-literal">#{c}</code>") : %{"#{c}"})
296
- when (0x80..0xFFFD) then (@options[:html] ? %("<code class="grammar-literal">#{c}</code>") : %{"#{c}"})
296
+ when (0x21) then (@options[:html] ? %("<code class="grammar-literal">#{@coder.encode c}</code>") : %{"#{c}"})
297
+ when 0x22 then (@options[:html] ? %('<code class="grammar-literal">&quot;</code>') : %{'"'})
298
+ when (0x23..0x7e) then (@options[:html] ? %("<code class="grammar-literal">#{@coder.encode c}</code>") : %{"#{c}"})
299
+ when (0x80..0xFFFD) then (@options[:html] ? %("<code class="grammar-literal">#{@coder.encode c}</code>") : %{"#{c}"})
297
300
  else escape_ebnf_hex(c)
298
301
  end
299
302
  end
@@ -308,7 +311,7 @@ module EBNF
308
311
  while !s.eos?
309
312
  case
310
313
  when s.scan(/\A[!"\u0024-\u007e]+/)
311
- buffer << (@options[:html] ? %(<code class="grammar-literal">#{s.matched}</code>) : s.matched)
314
+ buffer << (@options[:html] ? %(<code class="grammar-literal">#{@coder.encode s.matched}</code>) : s.matched)
312
315
  when s.scan(/\A#x\h+/)
313
316
  buffer << escape_ebnf_hex(s.matched[2..-1].hex.chr(Encoding::UTF_8))
314
317
  else
@@ -328,7 +331,8 @@ module EBNF
328
331
  end
329
332
  end
330
333
 
331
- "#{quote}#{string}#{quote}"
334
+ res = "#{quote}#{string}#{quote}"
335
+ @options[:html] ? @coder.encode(res) : res
332
336
  end
333
337
 
334
338
  def escape_ebnf_hex(u)
@@ -341,11 +345,11 @@ module EBNF
341
345
  char = fmt % u.ord
342
346
  if @options[:html]
343
347
  if u.ord <= 0x20
344
- char = %(<abbr title="#{ASCII_ESCAPE_NAMES[u.ord]}">#{char}</abbr>)
348
+ char = %(<abbr title="#{ASCII_ESCAPE_NAMES[u.ord]}">#{@coder.encode char}</abbr>)
345
349
  elsif u.ord < 0x7F
346
- char = %(<abbr title="ascii '#{u}'">#{char}</abbr>)
350
+ char = %(<abbr title="ascii '#{@coder.encode u}'">#{@coder.encode char}</abbr>)
347
351
  elsif u.ord == 0x7F
348
- char = %(<abbr title="delete">#{char}</abbr>)
352
+ char = %(<abbr title="delete">#{@coder.encode char}</abbr>)
349
353
  elsif u.ord <= 0xFF
350
354
  char = %(<abbr title="extended ascii '#{u}'">#{char}</abbr>)
351
355
  else
@@ -363,7 +367,7 @@ module EBNF
363
367
 
364
368
  # Format the expression part of a rule
365
369
  def format_abnf(expr, sep: nil, embedded: false, sensitive: true)
366
- return (@options[:html] ? %(<a href="#grammar-production-#{expr}">#{expr}</a>) : expr.to_s) if expr.is_a?(Symbol)
370
+ return (@options[:html] ? %(<a href="#grammar-production-#{@coder.encode expr}">#{@coder.encode expr}</a>) : expr.to_s) if expr.is_a?(Symbol)
367
371
  if expr.is_a?(String)
368
372
  if expr.length == 1
369
373
  return format_abnf_char(expr)
@@ -380,7 +384,7 @@ module EBNF
380
384
  seq.unshift(:seq)
381
385
  return format_abnf(seq, sep: nil, embedded: false)
382
386
  else
383
- return (@options[:html] ? %("<code class="grammar-literal">#{'%s' if sensitive}#{expr}</code>") : %(#{'%s' if sensitive}"#{expr}"))
387
+ return (@options[:html] ? %("<code class="grammar-literal">#{'%s' if sensitive}#{@coder.encode expr}</code>") : %(#{'%s' if sensitive}"#{expr}"))
384
388
  end
385
389
  end
386
390
  parts = {
@@ -528,11 +532,11 @@ module EBNF
528
532
  char = "%x" + (fmt % u.ord)
529
533
  if @options[:html]
530
534
  if u.ord <= 0x20
531
- char = %(<abbr title="#{ASCII_ESCAPE_NAMES[u.ord]}">#{char}</abbr>)
535
+ char = %(<abbr title="#{ASCII_ESCAPE_NAMES[u.ord]}">#{@coder.encode char}</abbr>)
532
536
  elsif u.ord <= 0x7F
533
- char = %(<abbr title="ascii '#{u}'">#{char}</abbr>)
537
+ char = %(<abbr title="ascii '#{u}'">#{@coder.encode char}</abbr>)
534
538
  elsif u.ord == 0x7F
535
- char = %(<abbr title="delete">#{char}</abbr>)
539
+ char = %(<abbr title="delete">#{@coder.encode char}</abbr>)
536
540
  elsif u.ord <= 0xFF
537
541
  char = %(<abbr title="extended ascii '#{u}'">#{char}</abbr>)
538
542
  else
@@ -550,7 +554,7 @@ module EBNF
550
554
 
551
555
  # Format the expression part of a rule
552
556
  def format_isoebnf(expr, sep: nil, embedded: false)
553
- return (@options[:html] ? %(<a href="#grammar-production-#{expr}">#{expr}</a>) : expr.to_s) if expr.is_a?(Symbol)
557
+ return (@options[:html] ? %(<a href="#grammar-production-#{@coder.encode expr}">#{@coder.encode expr}</a>) : expr.to_s) if expr.is_a?(Symbol)
554
558
  if expr.is_a?(String)
555
559
  expr = expr[2..-1].hex.chr if expr =~ /\A#x\h+/
556
560
  expr.chars.each do |c|
@@ -558,9 +562,9 @@ module EBNF
558
562
  ISOEBNF::TERMINAL_CHARACTER.match?(c)
559
563
  end
560
564
  if expr =~ /"/
561
- return (@options[:html] ? %('<code class="grammar-literal">#{expr}</code>') : %('#{expr}'))
565
+ return (@options[:html] ? %('<code class="grammar-literal">#{@coder.encode expr}</code>') : %('#{expr}'))
562
566
  else
563
- return (@options[:html] ? %("<code class="grammar-literal">#{expr}</code>") : %("#{expr}"))
567
+ return (@options[:html] ? %("<code class="grammar-literal">#{@coder.encode expr}</code>") : %("#{expr}"))
564
568
  end
565
569
  end
566
570
  parts = {
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: 2.1.0
4
+ version: 2.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gregg Kellogg
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-13 00:00:00.000000000 Z
11
+ date: 2020-07-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sxp
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: htmlentities
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '4.3'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '4.3'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: rdf-spec
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -81,33 +95,33 @@ dependencies:
81
95
  - !ruby/object:Gem::Version
82
96
  version: '3.1'
83
97
  - !ruby/object:Gem::Dependency
84
- name: erubis
98
+ name: nokogiri
85
99
  requirement: !ruby/object:Gem::Requirement
86
100
  requirements:
87
101
  - - "~>"
88
102
  - !ruby/object:Gem::Version
89
- version: '2.7'
103
+ version: '1.10'
90
104
  type: :development
91
105
  prerelease: false
92
106
  version_requirements: !ruby/object:Gem::Requirement
93
107
  requirements:
94
108
  - - "~>"
95
109
  - !ruby/object:Gem::Version
96
- version: '2.7'
110
+ version: '1.10'
97
111
  - !ruby/object:Gem::Dependency
98
- name: nokogiri
112
+ name: erubis
99
113
  requirement: !ruby/object:Gem::Requirement
100
114
  requirements:
101
115
  - - "~>"
102
116
  - !ruby/object:Gem::Version
103
- version: '1.10'
117
+ version: '2.7'
104
118
  type: :development
105
119
  prerelease: false
106
120
  version_requirements: !ruby/object:Gem::Requirement
107
121
  requirements:
108
122
  - - "~>"
109
123
  - !ruby/object:Gem::Version
110
- version: '1.10'
124
+ version: '2.7'
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: rspec
113
127
  requirement: !ruby/object:Gem::Requirement
@@ -164,8 +178,8 @@ dependencies:
164
178
  - - "~>"
165
179
  - !ruby/object:Gem::Version
166
180
  version: '13.0'
167
- description: EBNF is a Ruby parser for W3C EBNF and a parser generator for compliant
168
- LL(1) grammars.
181
+ description: EBNF is a Ruby parser for W3C EBNF and a parser generator for PEG and
182
+ LL(1). Also includes parsing modes for ISO EBNF and ABNF.
169
183
  email: public-rdf-ruby@w3.org
170
184
  executables:
171
185
  - ebnf