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
@@ -0,0 +1,19 @@
1
+ module ABNF
2
+ module Parser
3
+ class Compiler
4
+ class Group < RuleBuilder
5
+ attr_accessor :rule
6
+
7
+ def group_stop _
8
+ compiler.pop rule
9
+ end
10
+
11
+ def start_rule token
12
+ compiler.push Alternation do |rule|
13
+ self.rule = rule
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module ABNF
2
+ module Parser
3
+ class Compiler
4
+ class Option < RuleBuilder
5
+ attr_accessor :rule
6
+
7
+ def option_stop _
8
+ compiler.pop rule
9
+ end
10
+
11
+ def start_rule token
12
+ compiler.push Alternation do |rule|
13
+ self.rule = rule
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,50 @@
1
+ module ABNF
2
+ module Parser
3
+ class Compiler
4
+ class Repetition < RuleBuilder
5
+ attr_writer :abnf
6
+ attr_accessor :element
7
+ attr_accessor :range
8
+
9
+ def abnf
10
+ @abnf ||= ''
11
+ end
12
+
13
+ def finished element
14
+ abnf << element.abnf
15
+
16
+ if range
17
+ rule = Rules::Repetition.new element, range, abnf
18
+ else
19
+ rule = element
20
+ end
21
+
22
+ compiler.pop rule
23
+ end
24
+
25
+ def repeat_exact token
26
+ number = token.lexeme.to_i
27
+
28
+ self.abnf = token.abnf
29
+ self.range = (number..number)
30
+ end
31
+
32
+ def repeat_range token
33
+ minimum, maximum = token.lexeme.split '*'
34
+
35
+ if minimum then minimum = minimum.to_i else minimum = 0 end
36
+ if maximum then maximum = maximum.to_i else maximum = Float::INFINITY end
37
+
38
+ self.abnf = token.abnf
39
+ self.range = (minimum..maximum)
40
+ end
41
+
42
+ def start_rule token
43
+ compiler.push Element do |element|
44
+ finished element
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,32 @@
1
+ module ABNF
2
+ module Parser
3
+ class Compiler
4
+ class RuleBuilder
5
+ attr_reader :compiler
6
+
7
+ def initialize compiler
8
+ @compiler = compiler
9
+ end
10
+
11
+ def call token
12
+ send token.underscore_type, token
13
+ end
14
+
15
+ def start_rule token
16
+ fail
17
+ end
18
+
19
+ %i(
20
+ prose_val hex_val_range hex_val_sequence dec_val_range
21
+ dec_val_sequence bin_val_range bin_val_sequence char_val group_start
22
+ option_start repeat_range repeat_exact rulename
23
+ ).each do |token_type|
24
+ define_method token_type do |token|
25
+ start_rule token
26
+ compiler.handle token
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,67 @@
1
+ module ABNF
2
+ module Parser
3
+ class Compiler
4
+ class RuleList < RuleBuilder
5
+ attr_accessor :rulename
6
+
7
+ def c_nl token
8
+ end
9
+
10
+ def coerce_alternation rule
11
+ if rule.is_a? Rules::Alternation
12
+ rule
13
+ else
14
+ Rules::Alternation.new [rule], rule.abnf
15
+ end
16
+ end
17
+
18
+ def handle_rule name, rule
19
+ actual_rule = rule.inner_rule
20
+
21
+ if rule.operator == '=/'
22
+ original_rule = coerce_alternation rule_list[name]
23
+ new_rule = coerce_alternation actual_rule
24
+
25
+ alternatives = original_rule.alternatives + new_rule.alternatives
26
+ abnf = alternatives.map &:abnf
27
+ abnf *= ' / '
28
+ actual_rule = Rules::Alternation.new alternatives, abnf
29
+ end
30
+
31
+ rule_list[name] = actual_rule
32
+ end
33
+
34
+ def rule_list
35
+ compiler.rule_list
36
+ end
37
+
38
+ def rulename token
39
+ rulename = token.lexeme
40
+
41
+ compiler.push Rule do |rule|
42
+ handle_rule rulename, rule
43
+ end
44
+ end
45
+
46
+ class Rule < RuleBuilder
47
+ attr_accessor :operator
48
+ attr_accessor :inner_rule
49
+
50
+ def c_wsp _
51
+ end
52
+
53
+ def defined_as token
54
+ self.operator = token.lexeme
55
+ end
56
+
57
+ def start_rule token
58
+ compiler.push Alternation do |rule|
59
+ self.inner_rule = rule
60
+ compiler.pop self
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,34 @@
1
+ module ABNF
2
+ module Parser
3
+ class Compiler
4
+ class Token
5
+ attr_reader :abnf
6
+ attr_reader :type
7
+
8
+ def initialize type, abnf=nil
9
+ @abnf = abnf
10
+ @type = type
11
+ end
12
+
13
+ def == other_token
14
+ return false unless other_token.respond_to? :abnf
15
+ return false unless other_token.respond_to? :type
16
+
17
+ self.abnf == other_token.abnf and self.type == other_token.type
18
+ end
19
+
20
+ def lexeme
21
+ abnf
22
+ end
23
+
24
+ def inspect
25
+ "(#{type} #{abnf.inspect})"
26
+ end
27
+
28
+ def underscore_type
29
+ @underscore_type ||= type.downcase.gsub('-', '_')
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,95 @@
1
+ module ABNF
2
+ module Parser
3
+ class Compiler
4
+ class Tokenizer
5
+ C_NL = "(?:;[[:graph:][:blank:]]*)?\\r\\n".freeze
6
+ C_WSP = '(?:(?:#{C_NL})?[[:blank:]])'.freeze
7
+
8
+ attr_reader :abnf
9
+
10
+ def initialize abnf
11
+ @abnf = abnf
12
+ end
13
+
14
+ def self.build abnf
15
+ new abnf.dup
16
+ end
17
+
18
+ def self.call abnf
19
+ instance = build abnf
20
+ instance.()
21
+ end
22
+
23
+ def apply regexp
24
+ match_data = regexp.match abnf
25
+ return if match_data.nil? or not match_data.pre_match.empty?
26
+ abnf.slice! 0, match_data.to_s.size
27
+ match_data
28
+ end
29
+
30
+ def call &block
31
+ tokens = []
32
+
33
+ each do |token|
34
+ tokens << token
35
+ end
36
+
37
+ tokens
38
+ end
39
+
40
+ def each &block
41
+ until abnf.empty?
42
+ length = abnf.bytesize
43
+
44
+ token = self.next
45
+ block.(token) if block
46
+
47
+ fail "Parse error" unless abnf.bytesize < length
48
+ end
49
+ end
50
+
51
+ def next
52
+ possible_tokens.each do |type, regexp|
53
+ match_data = apply regexp
54
+ next unless match_data
55
+
56
+ token = Token.new type, match_data.to_s
57
+ return token
58
+ end
59
+
60
+ nil
61
+ end
62
+
63
+ def possible_tokens
64
+ @@possible_tokens ||= {
65
+ 'prose-val'.freeze => %r{\A<[\x20-\x3D\x3F-\x7E]*>}n,
66
+ 'hex-val-RANGE'.freeze => %r{\A%x[[:xdigit:]]+-[[:xdigit:]]+}n,
67
+ 'hex-val-SEQUENCE'.freeze => %r{\A%x[[:xdigit:]]+(?:\.[[:xdigit:]]+)*}n,
68
+ 'dec-val-RANGE'.freeze => %r{\A%d[[:digit:]]+-[[:digit:]]+}n,
69
+ 'dec-val-SEQUENCE'.freeze => %r{\A%d[[:digit:]]+(?:\.[[:digit:]]+)*}n,
70
+ 'bin-val-RANGE'.freeze => %r{\A%b[01]+-[01]+}n,
71
+ 'bin-val-SEQUENCE'.freeze => %r{\A%b[01]+(?:\.[01]+)*}n,
72
+ 'char-val'.freeze => %r{\A"[\x20-\x21\x23-\x7E]*"}n,
73
+ 'option-START'.freeze => %r{\A\[#{C_WSP}*}n,
74
+ 'option-STOP'.freeze => %r{\A#{C_WSP}*\]}n,
75
+ 'group-START'.freeze => %r{\A\(#{C_WSP}*}n,
76
+ 'group-STOP'.freeze => %r{\A#{C_WSP}*\)}n,
77
+ 'repeat-RANGE'.freeze => %r{\A[[:digit:]]*\*[[:digit:]]*}n,
78
+ 'repeat-EXACT'.freeze => %r{\A[[:digit:]]+}n,
79
+ 'alternation-SLASH'.freeze => %r{\A#{C_WSP}*/#{C_WSP}*}n,
80
+ 'defined-as'.freeze => %r{\A#{C_WSP}*=/?#{C_WSP}*}n,
81
+ 'rulename'.freeze => %r{\A[[:alpha:]][-[:alnum:]]*}n,
82
+ 'c-wsp'.freeze => %r{\A(?:(?:#{C_NL})?[[:blank:]])+}n,
83
+ 'c-nl'.freeze => %r{\A#{C_NL}}n,
84
+ }
85
+ end
86
+
87
+ def to_enum
88
+ Enumerator::Lazy.new self do |yielder, token|
89
+ yielder << token
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -1,4 +1,6 @@
1
- require 'abnf/parser/controls/ast'
2
- require 'abnf/parser/controls/grammar'
1
+ require 'abnf/parser/controls/abnf'
2
+ require 'abnf/parser/controls/nodes'
3
+ require 'abnf/parser/controls/rule_lists'
4
+ require 'abnf/parser/controls/rule_lists/multiples_of_three'
3
5
  require 'abnf/parser/controls/rules'
4
- require 'abnf/parser/controls/text_stream'
6
+ require 'abnf/parser/controls/compiler/tokens'
@@ -0,0 +1,237 @@
1
+ module ABNF
2
+ module Parser
3
+ module Controls
4
+ module ABNF
5
+ extend self
6
+
7
+ def alternation
8
+ %{#{ABNF.foo} / #{ABNF.bar} / #{ABNF.baz}}
9
+ end
10
+
11
+ def bar
12
+ '%x62.61.72'
13
+ end
14
+
15
+ def baz
16
+ '%x62.61.7A'
17
+ end
18
+
19
+ def concatenation
20
+ %{"[" #{foo} "]"}
21
+ end
22
+
23
+ def foo
24
+ '%x66.6F.6F'
25
+ end
26
+ alias_method :terminal, :foo
27
+
28
+ def foobar
29
+ '%x66.6F.6F.62.61.72'
30
+ end
31
+
32
+ def example
33
+ '(1*ALPHA "-" 1*ALPHA) / "~"'
34
+ end
35
+ alias_method :regexp_pattern, :example
36
+
37
+ def recursion
38
+ <<-ABNF
39
+ s0 = n0 s0 / n1 s2 / n2 s1 / ""\r
40
+ s1 = n0 s1 / n1 s0 / n2 s2\r
41
+ s2 = n0 s2 / n1 s1 / n2 s0\r
42
+ n0 = "0" / "3" / "6" / "9"\r
43
+ n1 = "1" / "4" / "7"\r
44
+ n2 = "2" / "5" / "8"\r
45
+ ABNF
46
+ end
47
+
48
+ def rfc5234
49
+ @rfc5234 ||= <<-ABNF
50
+ rulelist = 1*( rule / (*c-wsp c-nl) )\r
51
+ \r
52
+ rule = rulename defined-as elements c-nl\r
53
+ ; continues if next line starts\r
54
+ ; with white space\r
55
+ \r
56
+ rulename = ALPHA *(ALPHA / DIGIT / "-")\r
57
+ \r
58
+ defined-as = *c-wsp ("=" / "=/") *c-wsp\r
59
+ ; basic rules definition and\r
60
+ ; incremental alternatives\r
61
+ \r
62
+ elements = alternation *c-wsp\r
63
+ \r
64
+ c-wsp = WSP / (c-nl WSP)\r
65
+ \r
66
+ c-nl = comment / CRLF\r
67
+ ; comment or newline\r
68
+ \r
69
+ comment = ";" *(WSP / VCHAR) CRLF\r
70
+ \r
71
+ alternation = concatenation\r
72
+ *(*c-wsp "/" *c-wsp concatenation)\r
73
+ \r
74
+ concatenation = repetition *(1*c-wsp repetition)\r
75
+ \r
76
+ repetition = [repeat] element\r
77
+ \r
78
+ repeat = 1*DIGIT / (*DIGIT "*" *DIGIT)\r
79
+ \r
80
+ element = rulename / group / option /\r
81
+ char-val / num-val / prose-val\r
82
+ \r
83
+ group = "(" *c-wsp alternation *c-wsp ")"\r
84
+ \r
85
+ option = "[" *c-wsp alternation *c-wsp "]"\r
86
+ \r
87
+ char-val = DQUOTE *(%x20-21 / %x23-7E) DQUOTE\r
88
+ ; quoted string of SP and VCHAR\r
89
+ ; without DQUOTE\r
90
+ \r
91
+ num-val = "%" (bin-val / dec-val / hex-val)\r
92
+ \r
93
+ bin-val = "b" 1*BIT\r
94
+ [ 1*("." 1*BIT) / ("-" 1*BIT) ]\r
95
+ ; series of concatenated bit values\r
96
+ ; or single ONEOF range\r
97
+ \r
98
+ dec-val = "d" 1*DIGIT\r
99
+ [ 1*("." 1*DIGIT) / ("-" 1*DIGIT) ]\r
100
+ \r
101
+ hex-val = "x" 1*HEXDIG\r
102
+ [ 1*("." 1*HEXDIG) / ("-" 1*HEXDIG) ]\r
103
+ \r
104
+ prose-val = "<" *(%x20-3D / %x3F-7E) ">"\r
105
+ ; bracketed string of SP and VCHAR\r
106
+ ; without angles\r
107
+ ; prose description, to be used as\r
108
+ ; last resort\r
109
+ ABNF
110
+ end
111
+
112
+ def rfc7230
113
+ @rfc7230 ||= <<-ABNF
114
+ BWS = OWS\r
115
+ \r
116
+ Connection = *( "," OWS ) connection-option *( OWS "," [ OWS\r
117
+ connection-option ] )\r
118
+ \r
119
+ Content-Length = 1*DIGIT\r
120
+ \r
121
+ HTTP-message = start-line *( header-field CRLF ) CRLF [ message-body\r
122
+ ]\r
123
+ HTTP-name = %x48.54.54.50 ; HTTP\r
124
+ HTTP-version = HTTP-name "/" DIGIT "." DIGIT\r
125
+ Host = uri-host [ ":" port ]\r
126
+ \r
127
+ OWS = *( SP / HTAB )\r
128
+ \r
129
+ RWS = 1*( SP / HTAB )\r
130
+ \r
131
+ TE = [ ( "," / t-codings ) *( OWS "," [ OWS t-codings ] ) ]\r
132
+ Trailer = *( "," OWS ) field-name *( OWS "," [ OWS field-name ] )\r
133
+ Transfer-Encoding = *( "," OWS ) transfer-coding *( OWS "," [ OWS\r
134
+ transfer-coding ] )\r
135
+ \r
136
+ URI-reference = <URI-reference, see [RFC3986], Section 4.1>\r
137
+ Upgrade = *( "," OWS ) protocol *( OWS "," [ OWS protocol ] )\r
138
+ \r
139
+ Via = *( "," OWS ) ( received-protocol RWS received-by [ RWS comment\r
140
+ ] ) *( OWS "," [ OWS ( received-protocol RWS received-by [ RWS\r
141
+ comment ] ) ] )\r
142
+ \r
143
+ absolute-URI = <absolute-URI, see [RFC3986], Section 4.3>\r
144
+ absolute-form = absolute-URI\r
145
+ absolute-path = 1*( "/" segment )\r
146
+ asterisk-form = "*"\r
147
+ authority = <authority, see [RFC3986], Section 3.2>\r
148
+ authority-form = authority\r
149
+ \r
150
+ chunk = chunk-size [ chunk-ext ] CRLF chunk-data CRLF\r
151
+ chunk-data = 1*OCTET\r
152
+ chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-val ] )\r
153
+ chunk-ext-name = token\r
154
+ chunk-ext-val = token / quoted-string\r
155
+ chunk-size = 1*HEXDIG\r
156
+ chunked-body = *chunk last-chunk trailer-part CRLF\r
157
+ comment = "(" *( ctext / quoted-pair / comment ) ")"\r
158
+ connection-option = token\r
159
+ ctext = HTAB / SP / %x21-27 ; '!'-'''\r
160
+ / %x2A-5B ; '*'-'['\r
161
+ / %x5D-7E ; ']'-'~'\r
162
+ / obs-text\r
163
+ \r
164
+ field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]\r
165
+ field-name = token\r
166
+ field-value = *( field-content / obs-fold )\r
167
+ field-vchar = VCHAR / obs-text\r
168
+ fragment = <fragment, see [RFC3986], Section 3.5>\r
169
+ \r
170
+ header-field = field-name ":" OWS field-value OWS\r
171
+ http-URI = "http://" authority path-abempty [ "?" query ] [ "#"\r
172
+ fragment ]\r
173
+ https-URI = "https://" authority path-abempty [ "?" query ] [ "#"\r
174
+ fragment ]\r
175
+ \r
176
+ last-chunk = 1*"0" [ chunk-ext ] CRLF\r
177
+ \r
178
+ message-body = *OCTET\r
179
+ method = token\r
180
+ \r
181
+ obs-fold = CRLF 1*( SP / HTAB )\r
182
+ obs-text = %x80-FF\r
183
+ origin-form = absolute-path [ "?" query ]\r
184
+ \r
185
+ partial-URI = relative-part [ "?" query ]\r
186
+ path-abempty = <path-abempty, see [RFC3986], Section 3.3>\r
187
+ port = <port, see [RFC3986], Section 3.2.3>\r
188
+ protocol = protocol-name [ "/" protocol-version ]\r
189
+ protocol-name = token\r
190
+ protocol-version = token\r
191
+ pseudonym = token\r
192
+ \r
193
+ qdtext = HTAB / SP / "!" / %x23-5B ; '#'-'['\r
194
+ / %x5D-7E ; ']'-'~'\r
195
+ / obs-text\r
196
+ query = <query, see [RFC3986], Section 3.4>\r
197
+ quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )\r
198
+ \r
199
+ quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE\r
200
+ \r
201
+ rank = ( "0" [ "." *3DIGIT ] ) / ( "1" [ "." *3"0" ] )\r
202
+ reason-phrase = *( HTAB / SP / VCHAR / obs-text )\r
203
+ received-by = ( uri-host [ ":" port ] ) / pseudonym\r
204
+ received-protocol = [ protocol-name "/" ] protocol-version\r
205
+ relative-part = <relative-part, see [RFC3986], Section 4.2>\r
206
+ request-line = method SP request-target SP HTTP-version CRLF\r
207
+ request-target = origin-form / absolute-form / authority-form /\r
208
+ asterisk-form\r
209
+ \r
210
+ scheme = <scheme, see [RFC3986], Section 3.1>\r
211
+ segment = <segment, see [RFC3986], Section 3.3>\r
212
+ start-line = request-line / status-line\r
213
+ status-code = 3DIGIT\r
214
+ status-line = HTTP-version SP status-code SP reason-phrase CRLF\r
215
+ \r
216
+ t-codings = "trailers" / ( transfer-coding [ t-ranking ] )\r
217
+ t-ranking = OWS ";" OWS "q=" rank\r
218
+ tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /\r
219
+ "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA\r
220
+ token = 1*tchar\r
221
+ trailer-part = *( header-field CRLF )\r
222
+ transfer-coding = "chunked" / "compress" / "deflate" / "gzip" /\r
223
+ transfer-extension\r
224
+ transfer-extension = token *( OWS ";" OWS transfer-parameter )\r
225
+ transfer-parameter = token BWS "=" BWS ( token / quoted-string )\r
226
+ \r
227
+ uri-host = <host, see [RFC3986], Section 3.2.2>\r
228
+ ABNF
229
+ end
230
+
231
+ def rule
232
+ "some-rule = #{foo}\r\n"
233
+ end
234
+ end
235
+ end
236
+ end
237
+ end