abnf-parser 0.8.1 → 0.9.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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/lib/abnf/parser.rb +23 -25
  3. data/lib/abnf/parser/common.rb +63 -0
  4. data/lib/abnf/parser/compiler.rb +73 -33
  5. data/lib/abnf/parser/compiler/alternation.rb +54 -0
  6. data/lib/abnf/parser/compiler/concatenation.rb +55 -0
  7. data/lib/abnf/parser/compiler/element.rb +87 -0
  8. data/lib/abnf/parser/compiler/group.rb +19 -0
  9. data/lib/abnf/parser/compiler/option.rb +19 -0
  10. data/lib/abnf/parser/compiler/repetition.rb +50 -0
  11. data/lib/abnf/parser/compiler/rule_builder.rb +32 -0
  12. data/lib/abnf/parser/compiler/rule_list.rb +67 -0
  13. data/lib/abnf/parser/compiler/token.rb +34 -0
  14. data/lib/abnf/parser/compiler/tokenizer.rb +95 -0
  15. data/lib/abnf/parser/controls.rb +5 -3
  16. data/lib/abnf/parser/controls/abnf.rb +237 -0
  17. data/lib/abnf/parser/controls/compiler/tokens.rb +97 -0
  18. data/lib/abnf/parser/controls/nodes.rb +113 -0
  19. data/lib/abnf/parser/controls/rule_lists.rb +63 -0
  20. data/lib/abnf/parser/controls/rule_lists/multiples_of_three.rb +146 -0
  21. data/lib/abnf/parser/controls/rules.rb +40 -17
  22. data/lib/abnf/parser/{errors.rb → error.rb} +0 -2
  23. data/lib/abnf/parser/node.rb +138 -0
  24. data/lib/abnf/parser/rule_list.rb +50 -11
  25. data/lib/abnf/parser/rules/alternation.rb +38 -0
  26. data/lib/abnf/parser/rules/concatenation.rb +36 -0
  27. data/lib/abnf/parser/rules/prose_val.rb +18 -0
  28. data/lib/abnf/parser/rules/reference.rb +22 -0
  29. data/lib/abnf/parser/rules/regexp_pattern.rb +35 -0
  30. data/lib/abnf/parser/rules/repetition.rb +46 -0
  31. data/lib/abnf/parser/rules/terminal.rb +63 -0
  32. metadata +31 -31
  33. data/lib/abnf/parser/ast.rb +0 -67
  34. data/lib/abnf/parser/controls/ast.rb +0 -28
  35. data/lib/abnf/parser/controls/grammar.rb +0 -32
  36. data/lib/abnf/parser/controls/text_stream.rb +0 -15
  37. data/lib/abnf/parser/grammar.rb +0 -17
  38. data/lib/abnf/parser/grammar/alternative.rb +0 -27
  39. data/lib/abnf/parser/grammar/char_val.rb +0 -15
  40. data/lib/abnf/parser/grammar/concatenation.rb +0 -21
  41. data/lib/abnf/parser/grammar/element.rb +0 -57
  42. data/lib/abnf/parser/grammar/num_val.rb +0 -72
  43. data/lib/abnf/parser/grammar/prose_val.rb +0 -15
  44. data/lib/abnf/parser/grammar/repetition.rb +0 -58
  45. data/lib/abnf/parser/grammar/rule.rb +0 -31
  46. data/lib/abnf/parser/grammar/rulename.rb +0 -15
  47. data/lib/abnf/parser/rule.rb +0 -10
  48. data/lib/abnf/parser/rule/alternative.rb +0 -43
  49. data/lib/abnf/parser/rule/concatenation.rb +0 -29
  50. data/lib/abnf/parser/rule/none.rb +0 -17
  51. data/lib/abnf/parser/rule/optional.rb +0 -24
  52. data/lib/abnf/parser/rule/reference.rb +0 -19
  53. data/lib/abnf/parser/rule/repetition.rb +0 -41
  54. data/lib/abnf/parser/rule/terminal_value.rb +0 -32
  55. data/lib/abnf/parser/rule/value_range.rb +0 -33
  56. data/lib/abnf/parser/rule_list/entry.rb +0 -21
  57. data/lib/abnf/parser/text_stream.rb +0 -67
@@ -1,7 +1,5 @@
1
1
  module ABNF
2
2
  module Parser
3
3
  Error = Class.new StandardError
4
- ParsingError = Class.new Error
5
- CompileError = Class.new Error
6
4
  end
7
5
  end
@@ -0,0 +1,138 @@
1
+ module ABNF
2
+ module Parser
3
+ module Node
4
+ def self.alternation node, abnf
5
+ Alternation.new node, abnf
6
+ end
7
+
8
+ def self.concatenation children=nil, abnf
9
+ children ||= Array(children)
10
+ Sequence.new children, abnf
11
+ end
12
+
13
+ def self.repetition children=nil, abnf
14
+ children ||= Array(children)
15
+ Sequence.new children, abnf
16
+ end
17
+
18
+ def self.pattern_match match_data, abnf
19
+ PatternMatch.new match_data, abnf
20
+ end
21
+
22
+ def self.terminal text, abnf
23
+ Single.new text, abnf
24
+ end
25
+
26
+ def == other_node
27
+ return false unless other_node.is_a? Node
28
+ self.text == other_node.text and self.abnf == other_node.abnf
29
+ end
30
+
31
+ def octets
32
+ text.bytesize
33
+ end
34
+
35
+ class Alternation
36
+ include Node
37
+
38
+ attr_reader :abnf
39
+ attr_reader :match
40
+
41
+ def initialize match, abnf
42
+ @abnf = abnf
43
+ @match = match
44
+ end
45
+
46
+ def text
47
+ match.text
48
+ end
49
+ end
50
+
51
+ class Sequence
52
+ include Enumerable
53
+ include Node
54
+
55
+ attr_reader :abnf
56
+ attr_reader :children
57
+
58
+ def initialize children, abnf
59
+ @abnf = abnf
60
+ @children = children
61
+ end
62
+
63
+ def [] index
64
+ children[index]
65
+ end
66
+
67
+ def add child
68
+ children << child
69
+ end
70
+ alias_method :<<, :add
71
+
72
+ def child_count
73
+ children.size
74
+ end
75
+
76
+ def each &block
77
+ children.each &block
78
+ end
79
+
80
+ def text
81
+ @text ||= to_a.join
82
+ end
83
+
84
+ def to_a
85
+ map do |child|
86
+ if child.respond_to? :to_a
87
+ child.to_a
88
+ else
89
+ child.text
90
+ end
91
+ end
92
+ end
93
+ end
94
+
95
+ class Single
96
+ include Node
97
+
98
+ attr_reader :abnf
99
+ attr_reader :text
100
+
101
+ def initialize text, abnf
102
+ @text = text
103
+ @abnf = abnf
104
+ end
105
+ end
106
+
107
+ class PatternMatch
108
+ include Node
109
+
110
+ attr_reader :abnf
111
+ attr_reader :match_data
112
+
113
+ def initialize match_data, abnf
114
+ @match_data = match_data
115
+ @abnf = abnf
116
+ end
117
+
118
+ def pattern
119
+ match_data.regexp
120
+ end
121
+
122
+ def text
123
+ match_data.to_s
124
+ end
125
+
126
+ def to_h
127
+ hash = {}
128
+
129
+ match_data.names.each do |name|
130
+ hash[name] = match_data[name]
131
+ end
132
+
133
+ hash
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
@@ -1,24 +1,63 @@
1
1
  module ABNF
2
2
  module Parser
3
3
  class RuleList
4
- attr_reader :rules
4
+ def == other_rule_list
5
+ return false unless other_rule_list.is_a? self.class
5
6
 
6
- def initialize
7
- @rules = {}
7
+ rules == other_rule_list.rules
8
8
  end
9
9
 
10
- def compile abnf
11
- stream = Parser::TextStream(abnf)
10
+ def [] rule_name
11
+ rules[rule_name]
12
+ end
13
+
14
+ def []= rule_name, rule
15
+ rules[rule_name] = rule
16
+ end
17
+
18
+ def apply rule_name, io
19
+ rule = fetch rule_name
20
+
21
+ call_method = rule.method :call
12
22
 
13
- until stream.eof?
14
- stream.match Grammar::C_WSP
15
- stream.match Grammar::C_NL
23
+ io = StringIO.new io if io.is_a? String
16
24
 
17
- rule = Grammar::Rule.compile stream
18
- next unless rule
25
+ rules[rule_name].(io, self)
26
+ end
27
+
28
+ def fetch rule_name
29
+ rule = rules[rule_name]
19
30
 
20
- rules[rule.name] = rule
31
+ unless rule
32
+ raise Error.new "Rule not found: #{rule_name.inspect}"
21
33
  end
34
+
35
+ rule
36
+ end
37
+
38
+ def names
39
+ rules.keys
40
+ end
41
+
42
+ def replace rule_name, regexp, max_octets
43
+ existing_rule = fetch rule_name
44
+ abnf = existing_rule
45
+
46
+ rule = Rules::RegexpPattern.new regexp, abnf, max_octets
47
+ rules[rule_name] = rule
48
+ end
49
+
50
+ def rules
51
+ @rules ||= {}
52
+ end
53
+
54
+ def update additional_rules
55
+ rules.update additional_rules
56
+ end
57
+
58
+ def self.common
59
+ abnf = Common.to_s
60
+ Compiler.(abnf)
22
61
  end
23
62
  end
24
63
  end
@@ -0,0 +1,38 @@
1
+ module ABNF
2
+ module Parser
3
+ module Rules
4
+ class Alternation
5
+ attr_reader :abnf
6
+ attr_reader :alternatives
7
+
8
+ def initialize alternatives, abnf
9
+ @abnf = abnf
10
+ @alternatives = alternatives
11
+ end
12
+
13
+ def == other_rule
14
+ return unless other_rule.is_a? self.class
15
+ alternatives == other_rule.alternatives
16
+ end
17
+
18
+ def call io, rule_list=nil
19
+ best_match = nil
20
+
21
+ alternatives.each do |alternative|
22
+ node = alternative.(io, rule_list) or next
23
+
24
+ io.seek -node.octets, IO::SEEK_CUR
25
+
26
+ best_match ||= node
27
+ best_match = node if node.octets > best_match.octets
28
+ end
29
+
30
+ return unless best_match
31
+
32
+ io.seek best_match.octets, IO::SEEK_CUR
33
+ best_match
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,36 @@
1
+ module ABNF
2
+ module Parser
3
+ module Rules
4
+ class Concatenation
5
+ attr_reader :abnf
6
+ attr_reader :rules
7
+
8
+ def initialize rules, abnf
9
+ @abnf = abnf
10
+ @rules = rules
11
+ end
12
+
13
+ def == other_rule
14
+ return false unless other_rule.is_a? self.class
15
+ self.rules == other_rule.rules
16
+ end
17
+
18
+ def call io, rule_list=nil
19
+ node = Node.concatenation abnf
20
+
21
+ match = rules.all? do |rule|
22
+ child = rule.(io, rule_list) or break
23
+ node << child
24
+ end
25
+
26
+ if match
27
+ node
28
+ else
29
+ io.seek -node.octets, IO::SEEK_CUR
30
+ nil
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,18 @@
1
+ module ABNF
2
+ module Parser
3
+ module Rules
4
+ class ProseVal
5
+ attr_reader :abnf
6
+
7
+ def initialize abnf
8
+ @abnf = abnf
9
+ end
10
+
11
+ def call io, _=nil
12
+ error = ABNF::Parser::Error.new "Cannot parse prose #{abnf.inspect}"
13
+ raise error
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,22 @@
1
+ module ABNF
2
+ module Parser
3
+ module Rules
4
+ class Reference
5
+ attr_reader :rule_name
6
+
7
+ def initialize rule_name
8
+ @rule_name = rule_name
9
+ end
10
+
11
+ def abnf
12
+ rule_name
13
+ end
14
+
15
+ def call io, rule_list
16
+ rule = rule_list.fetch rule_name
17
+ rule.(io, rule_list)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,35 @@
1
+ module ABNF
2
+ module Parser
3
+ module Rules
4
+ class RegexpPattern
5
+ attr_reader :abnf
6
+ attr_reader :max_octets
7
+ attr_reader :regexp
8
+
9
+ def initialize regexp, abnf, max_octets
10
+ @abnf = abnf
11
+ @max_octets = max_octets
12
+ @regexp = regexp
13
+ end
14
+
15
+ def bounded_regexp
16
+ @bounded_regexp ||= %r{\A#{regexp}}
17
+ end
18
+
19
+ def call io, _=nil
20
+ string = io.read max_octets
21
+ return unless string
22
+ io.seek -string.bytesize, IO::SEEK_CUR
23
+
24
+ match_data = bounded_regexp.match string
25
+
26
+ if match_data
27
+ node = Node.pattern_match match_data, abnf
28
+ io.seek node.octets, IO::SEEK_CUR
29
+ node
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,46 @@
1
+ module ABNF
2
+ module Parser
3
+ module Rules
4
+ class Repetition
5
+ attr_reader :abnf
6
+ attr_reader :rule
7
+ attr_reader :range
8
+
9
+ def initialize rule, range, abnf
10
+ @abnf = abnf
11
+ @rule = rule
12
+ @range = range
13
+ end
14
+
15
+ def == other_rule
16
+ return false unless other_rule.is_a? self.class
17
+ rule == other_rule.rule and range == other_rule.range
18
+ end
19
+
20
+ def call io, rule_list=nil
21
+ node = Node.repetition abnf
22
+
23
+ (0...maximum).each do
24
+ child = rule.(io, rule_list) or break
25
+ node << child
26
+ end
27
+
28
+ if node.child_count >= minimum
29
+ node
30
+ else
31
+ io.seek -node.octets, IO::SEEK_CUR
32
+ nil
33
+ end
34
+ end
35
+
36
+ def maximum
37
+ range.last
38
+ end
39
+
40
+ def minimum
41
+ range.first
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,63 @@
1
+ module ABNF
2
+ module Parser
3
+ module Rules
4
+ class Terminal
5
+ attr_reader :abnf
6
+ attr_reader :pattern
7
+
8
+ def initialize pattern, abnf
9
+ @abnf = abnf
10
+ @pattern = pattern
11
+ fail if self.class == Terminal
12
+ end
13
+
14
+ def == other_rule
15
+ return false unless other_rule.is_a? self.class
16
+ pattern == other_rule.pattern
17
+ end
18
+
19
+ def call io, _=nil
20
+ potential_match = io.read octets
21
+ return unless potential_match
22
+
23
+ matches = match? potential_match
24
+
25
+ if matches
26
+ Node.terminal potential_match, abnf
27
+ else
28
+ io.seek -potential_match.bytesize, IO::SEEK_CUR
29
+ nil
30
+ end
31
+ end
32
+
33
+ class String < Terminal
34
+ def match? potential_match
35
+ pattern == potential_match
36
+ end
37
+
38
+ def octets
39
+ pattern.bytesize
40
+ end
41
+ end
42
+
43
+ def self.string *arguments
44
+ String.new *arguments
45
+ end
46
+
47
+ class CharacterRange < Terminal
48
+ def match? potential_match
49
+ pattern.include? potential_match
50
+ end
51
+
52
+ def octets
53
+ 1
54
+ end
55
+ end
56
+
57
+ def self.character_range *arguments
58
+ CharacterRange.new *arguments
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end