abnf-parser 0.8.1 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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