rfc-822-validator 0.0.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.
data/.README.md.swp ADDED
Binary file
data/.bnsignore ADDED
@@ -0,0 +1,18 @@
1
+ # The list of files that should be ignored by Mr Bones.
2
+ # Lines that start with '#' are comments.
3
+ #
4
+ # A .gitignore file can be used instead by setting it as the ignore
5
+ # file in your Rakefile:
6
+ #
7
+ # Bones {
8
+ # ignore_file '.gitignore'
9
+ # }
10
+ #
11
+ # For a project with a C extension, the following would be a good set of
12
+ # exclude patterns (uncomment them if you want to use them):
13
+ # *.[oa]
14
+ # *~
15
+ announcement.txt
16
+ coverage
17
+ doc
18
+ pkg
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ == 1.0.0 / 2011-03-22
2
+
3
+ * 1 major enhancement
4
+ * Birthday!
data/README.md ADDED
@@ -0,0 +1,64 @@
1
+ rfc-822
2
+ ===========
3
+
4
+ Implementation of RFC-822
5
+
6
+ Features
7
+ --------
8
+
9
+ Validates RFC-822 Addresses
10
+
11
+ More usefully, it validates the addr_spec portion of the addresses
12
+
13
+ Examples
14
+ --------
15
+
16
+ # Validate an address as per the RFC
17
+ RFC822.validate('example@example.net')
18
+
19
+ # Validate an address per the addr_spec portion of the RFC
20
+ # This is what most people actually expect in an address
21
+ RFC822.validate_addr('example@example.net')
22
+
23
+ A note on the RFC
24
+ -----------------
25
+ RFC 822 has some oddities, it does things most people don't expect, such as
26
+
27
+ * It does not validate domains
28
+ * It supports groups, multiple labeled lists of addresses. ex: MyGroup: "John Higgins" <john@example.net>, mark mark@example.net;
29
+ * It supports routes, a sequence of mailservers the message is supposed to travel. ex: test@mymailserver@othermailserver.com
30
+ * It support sdouble quoted strings as the local part of an address, with crazy chars in them. ex: "my@funkyaddress"@example.net
31
+ * It supports phrases before angle bracketed addresses. ex: "Test" <test@example.net>.
32
+
33
+
34
+ Authors
35
+ ------
36
+
37
+ Evan Phoenix (evanphx)
38
+ Andrew Cholakian (andrewvc)
39
+
40
+ License
41
+ -------
42
+
43
+ (The MIT License) FIXME (different license?)
44
+
45
+ Copyright (c) 2011 FIXME (author's name)
46
+
47
+ Permission is hereby granted, free of charge, to any person obtaining
48
+ a copy of this software and associated documentation files (the
49
+ 'Software'), to deal in the Software without restriction, including
50
+ without limitation the rights to use, copy, modify, merge, publish,
51
+ distribute, sublicense, and/or sell copies of the Software, and to
52
+ permit persons to whom the Software is furnished to do so, subject to
53
+ the following conditions:
54
+
55
+ The above copyright notice and this permission notice shall be
56
+ included in all copies or substantial portions of the Software.
57
+
58
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
59
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
60
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
61
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
62
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
63
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
64
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+
2
+ begin
3
+ require 'bones'
4
+ rescue LoadError
5
+ abort '### Please install the "bones" gem ###'
6
+ end
7
+
8
+ task :default => 'test:run'
9
+ task 'gem:release' => 'test:run'
10
+
11
+ task "parser" do
12
+ sh "kpeg -s -o lib/rfc-822/parser.rb -f email.kpeg"
13
+ end
14
+
15
+ Bones {
16
+ name 'rfc-822-validator'
17
+ authors 'Evan Phoenix, Andrew Cholakian'
18
+ email 'andrew@andrewvc.com'
19
+ url 'https://github.com/andrewvc/rfc-822'
20
+ }
21
+
data/bin/rfc-822 ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path(
4
+ File.join(File.dirname(__FILE__), %w[.. lib rfc-822]))
5
+
6
+ # Put your code here
7
+
data/email.kpeg ADDED
@@ -0,0 +1,72 @@
1
+ %% name = RFC822::Parser
2
+
3
+ HTAB = /\x09/
4
+ LF = /\x0A/
5
+ CR = /\x0D/
6
+ SPACE = " "
7
+ - = SPACE*
8
+ AT = "@"
9
+
10
+ LWSP_char = SPACE | HTAB
11
+ CHAR = /[\x00-\x7f]/
12
+ CTL = /[\x00-\x1f\x7f]/
13
+
14
+ special = /[\]()<>@,;:\\".\[]/
15
+
16
+ CRLF = CR LF
17
+
18
+ linear_white_space = (CRLF? LWSP_char)+
19
+
20
+ atom = /[^\]\x00-\x20 \x7F\x80-\xFF()<>@,;:\\".\[]+/
21
+
22
+ ctext = /[^)\\\x0D\x80-\xFF(]+/
23
+ | linear_white_space
24
+
25
+
26
+ dtext = /[^\]\\\x0D\x80-\xFF\[]+/
27
+ | linear_white_space
28
+
29
+ qtext = /[^"\\\x0D\x80-\xFF]+/
30
+ | linear_white_space
31
+
32
+
33
+ quoted_pair = "\\" CHAR
34
+
35
+ quoted_string = "\"" (qtext | quoted_pair)* "\""
36
+
37
+ domain_literal = "[" (dtext | quoted_pair)* "]"
38
+
39
+ comment = "(" (ctext | quoted_pair | comment)* ")"
40
+
41
+ ocms = comment*
42
+
43
+ word = atom | quoted_string
44
+
45
+ phrase = (word -)+
46
+
47
+ valid = ocms address ocms
48
+
49
+ address = mailbox | group
50
+
51
+ group = phrase ocms ":" ocms mailbox (ocms "," ocms mailbox)* ocms ";"
52
+
53
+ mailbox = addr_spec
54
+ | phrase - ocms - angle_addr
55
+
56
+ angle_addr = "<" ocms route? ocms addr_spec ">"
57
+
58
+ route = (AT ocms domain)+ ":"
59
+
60
+ addr_spec = local_part ocms "@" ocms domain
61
+
62
+ local_part = word ocms ("." ocms word)*
63
+
64
+ domain = sub_domain ocms ("." ocms sub_domain)*
65
+
66
+ sub_domain = domain_ref | domain_literal
67
+
68
+ domain_ref = atom
69
+
70
+ root = valid !.
71
+
72
+ only_addr_spec = addr_spec !.
data/lib/rfc-822.rb ADDED
@@ -0,0 +1,72 @@
1
+
2
+ module RFC822
3
+
4
+ # :stopdoc:
5
+ LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
6
+ PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
7
+ VERSION = ::File.read(PATH + 'version.txt').strip
8
+ # :startdoc:
9
+
10
+ # Returns the library path for the module. If any arguments are given,
11
+ # they will be joined to the end of the libray path using
12
+ # <tt>File.join</tt>.
13
+ #
14
+ def self.libpath( *args )
15
+ rv = args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten)
16
+ if block_given?
17
+ begin
18
+ $LOAD_PATH.unshift LIBPATH
19
+ rv = yield
20
+ ensure
21
+ $LOAD_PATH.shift
22
+ end
23
+ end
24
+ return rv
25
+ end
26
+
27
+ # Returns the lpath for the module. If any arguments are given,
28
+ # they will be joined to the end of the path using
29
+ # <tt>File.join</tt>.
30
+ #
31
+ def self.path( *args )
32
+ rv = args.empty? ? PATH : ::File.join(PATH, args.flatten)
33
+ if block_given?
34
+ begin
35
+ $LOAD_PATH.unshift PATH
36
+ rv = yield
37
+ ensure
38
+ $LOAD_PATH.shift
39
+ end
40
+ end
41
+ return rv
42
+ end
43
+
44
+ # Utility method used to require all files ending in .rb that lie in the
45
+ # directory below this file that has the same name as the filename passed
46
+ # in. Optionally, a specific _directory_ name can be passed in such that
47
+ # the _filename_ does not have to be equivalent to the directory.
48
+ #
49
+ def self.require_all_libs_relative_to( fname, dir = nil )
50
+ dir ||= ::File.basename(fname, '.*')
51
+ search_me = ::File.expand_path(
52
+ ::File.join(::File.dirname(fname), dir, '**', '*.rb'))
53
+
54
+ Dir.glob(search_me).sort.each {|rb| require rb}
55
+ end
56
+
57
+
58
+ def self.validate(addr)
59
+ parser = Parser.new(addr)
60
+ parser.parse
61
+ end
62
+
63
+ def self.validate_addr(addr)
64
+ parser = Parser.new(addr, "only_addr_spec")
65
+ parser.parse
66
+ end
67
+
68
+
69
+ end # module RFC822
70
+
71
+ RFC822.require_all_libs_relative_to(__FILE__)
72
+
@@ -0,0 +1,1292 @@
1
+ class RFC822::Parser
2
+ # STANDALONE START
3
+ def setup_parser(str, debug=false)
4
+ @string = str
5
+ @pos = 0
6
+ @memoizations = Hash.new { |h,k| h[k] = {} }
7
+ @result = nil
8
+ @failed_rule = nil
9
+ @failing_rule_offset = -1
10
+
11
+ setup_foreign_grammar
12
+ end
13
+
14
+ def setup_foreign_grammar
15
+ end
16
+
17
+ # This is distinct from setup_parser so that a standalone parser
18
+ # can redefine #initialize and still have access to the proper
19
+ # parser setup code.
20
+ #
21
+ def initialize(str, debug=false)
22
+ setup_parser(str, debug)
23
+ end
24
+
25
+ attr_reader :string
26
+ attr_reader :result, :failing_rule_offset
27
+ attr_accessor :pos
28
+
29
+ # STANDALONE START
30
+ def current_column(target=pos)
31
+ if c = string.rindex("\n", target-1)
32
+ return target - c - 1
33
+ end
34
+
35
+ target + 1
36
+ end
37
+
38
+ def current_line(target=pos)
39
+ cur_offset = 0
40
+ cur_line = 0
41
+
42
+ string.each_line do |line|
43
+ cur_line += 1
44
+ cur_offset += line.size
45
+ return cur_line if cur_offset >= target
46
+ end
47
+
48
+ -1
49
+ end
50
+
51
+ def lines
52
+ lines = []
53
+ string.each_line { |l| lines << l }
54
+ lines
55
+ end
56
+
57
+ #
58
+
59
+ def get_text(start)
60
+ @string[start..@pos-1]
61
+ end
62
+
63
+ def show_pos
64
+ width = 10
65
+ if @pos < width
66
+ "#{@pos} (\"#{@string[0,@pos]}\" @ \"#{@string[@pos,width]}\")"
67
+ else
68
+ "#{@pos} (\"... #{@string[@pos - width, width]}\" @ \"#{@string[@pos,width]}\")"
69
+ end
70
+ end
71
+
72
+ def failure_info
73
+ l = current_line @failing_rule_offset
74
+ c = current_column @failing_rule_offset
75
+
76
+ if @failed_rule.kind_of? Symbol
77
+ info = self.class::Rules[@failed_rule]
78
+ "line #{l}, column #{c}: failed rule '#{info.name}' = '#{info.rendered}'"
79
+ else
80
+ "line #{l}, column #{c}: failed rule '#{@failed_rule}'"
81
+ end
82
+ end
83
+
84
+ def failure_caret
85
+ l = current_line @failing_rule_offset
86
+ c = current_column @failing_rule_offset
87
+
88
+ line = lines[l-1]
89
+ "#{line}\n#{' ' * (c - 1)}^"
90
+ end
91
+
92
+ def failure_character
93
+ l = current_line @failing_rule_offset
94
+ c = current_column @failing_rule_offset
95
+ lines[l-1][c-1, 1]
96
+ end
97
+
98
+ def failure_oneline
99
+ l = current_line @failing_rule_offset
100
+ c = current_column @failing_rule_offset
101
+
102
+ char = lines[l-1][c-1, 1]
103
+
104
+ if @failed_rule.kind_of? Symbol
105
+ info = self.class::Rules[@failed_rule]
106
+ "@#{l}:#{c} failed rule '#{info.name}', got '#{char}'"
107
+ else
108
+ "@#{l}:#{c} failed rule '#{@failed_rule}', got '#{char}'"
109
+ end
110
+ end
111
+
112
+ class ParseError < RuntimeError
113
+ end
114
+
115
+ def raise_error
116
+ raise ParseError, failure_oneline
117
+ end
118
+
119
+ def show_error(io=STDOUT)
120
+ error_pos = @failing_rule_offset
121
+ line_no = current_line(error_pos)
122
+ col_no = current_column(error_pos)
123
+
124
+ io.puts "On line #{line_no}, column #{col_no}:"
125
+
126
+ if @failed_rule.kind_of? Symbol
127
+ info = self.class::Rules[@failed_rule]
128
+ io.puts "Failed to match '#{info.rendered}' (rule '#{info.name}')"
129
+ else
130
+ io.puts "Failed to match rule '#{@failed_rule}'"
131
+ end
132
+
133
+ io.puts "Got: #{string[error_pos,1].inspect}"
134
+ line = lines[line_no-1]
135
+ io.puts "=> #{line}"
136
+ io.print(" " * (col_no + 3))
137
+ io.puts "^"
138
+ end
139
+
140
+ def set_failed_rule(name)
141
+ if @pos > @failing_rule_offset
142
+ @failed_rule = name
143
+ @failing_rule_offset = @pos
144
+ end
145
+ end
146
+
147
+ attr_reader :failed_rule
148
+
149
+ def match_string(str)
150
+ len = str.size
151
+ if @string[pos,len] == str
152
+ @pos += len
153
+ return str
154
+ end
155
+
156
+ return nil
157
+ end
158
+
159
+ def scan(reg)
160
+ if m = reg.match(@string[@pos..-1])
161
+ width = m.end(0)
162
+ @pos += width
163
+ return true
164
+ end
165
+
166
+ return nil
167
+ end
168
+
169
+ if "".respond_to? :getbyte
170
+ def get_byte
171
+ if @pos >= @string.size
172
+ return nil
173
+ end
174
+
175
+ s = @string.getbyte @pos
176
+ @pos += 1
177
+ s
178
+ end
179
+ else
180
+ def get_byte
181
+ if @pos >= @string.size
182
+ return nil
183
+ end
184
+
185
+ s = @string[@pos]
186
+ @pos += 1
187
+ s
188
+ end
189
+ end
190
+
191
+ def parse(rule=nil)
192
+ if !rule
193
+ _root ? true : false
194
+ else
195
+ # This is not shared with code_generator.rb so this can be standalone
196
+ method = rule.gsub("-","_hyphen_")
197
+ __send__("_#{method}") ? true : false
198
+ end
199
+ end
200
+
201
+ class LeftRecursive
202
+ def initialize(detected=false)
203
+ @detected = detected
204
+ end
205
+
206
+ attr_accessor :detected
207
+ end
208
+
209
+ class MemoEntry
210
+ def initialize(ans, pos)
211
+ @ans = ans
212
+ @pos = pos
213
+ @uses = 1
214
+ @result = nil
215
+ end
216
+
217
+ attr_reader :ans, :pos, :uses, :result
218
+
219
+ def inc!
220
+ @uses += 1
221
+ end
222
+
223
+ def move!(ans, pos, result)
224
+ @ans = ans
225
+ @pos = pos
226
+ @result = result
227
+ end
228
+ end
229
+
230
+ def external_invoke(other, rule, *args)
231
+ old_pos = @pos
232
+ old_string = @string
233
+
234
+ @pos = other.pos
235
+ @string = other.string
236
+
237
+ begin
238
+ if val = __send__(rule, *args)
239
+ other.pos = @pos
240
+ else
241
+ other.set_failed_rule "#{self.class}##{rule}"
242
+ end
243
+ val
244
+ ensure
245
+ @pos = old_pos
246
+ @string = old_string
247
+ end
248
+ end
249
+
250
+ def apply(rule)
251
+ if m = @memoizations[rule][@pos]
252
+ m.inc!
253
+
254
+ prev = @pos
255
+ @pos = m.pos
256
+ if m.ans.kind_of? LeftRecursive
257
+ m.ans.detected = true
258
+ return nil
259
+ end
260
+
261
+ @result = m.result
262
+
263
+ return m.ans
264
+ else
265
+ lr = LeftRecursive.new(false)
266
+ m = MemoEntry.new(lr, @pos)
267
+ @memoizations[rule][@pos] = m
268
+ start_pos = @pos
269
+
270
+ ans = __send__ rule
271
+
272
+ m.move! ans, @pos, @result
273
+
274
+ # Don't bother trying to grow the left recursion
275
+ # if it's failing straight away (thus there is no seed)
276
+ if ans and lr.detected
277
+ return grow_lr(rule, start_pos, m)
278
+ else
279
+ return ans
280
+ end
281
+
282
+ return ans
283
+ end
284
+ end
285
+
286
+ def grow_lr(rule, start_pos, m)
287
+ while true
288
+ @pos = start_pos
289
+ @result = m.result
290
+
291
+ ans = __send__ rule
292
+ return nil unless ans
293
+
294
+ break if @pos <= m.pos
295
+
296
+ m.move! ans, @pos, @result
297
+ end
298
+
299
+ @result = m.result
300
+ @pos = m.pos
301
+ return m.ans
302
+ end
303
+
304
+ class RuleInfo
305
+ def initialize(name, rendered)
306
+ @name = name
307
+ @rendered = rendered
308
+ end
309
+
310
+ attr_reader :name, :rendered
311
+ end
312
+
313
+ def self.rule_info(name, rendered)
314
+ RuleInfo.new(name, rendered)
315
+ end
316
+
317
+ #
318
+ def setup_foreign_grammar; end
319
+
320
+ # HTAB = /\x09/
321
+ def _HTAB
322
+ _tmp = scan(/\A(?-mix:\x09)/)
323
+ set_failed_rule :_HTAB unless _tmp
324
+ return _tmp
325
+ end
326
+
327
+ # LF = /\x0A/
328
+ def _LF
329
+ _tmp = scan(/\A(?-mix:\x0A)/)
330
+ set_failed_rule :_LF unless _tmp
331
+ return _tmp
332
+ end
333
+
334
+ # CR = /\x0D/
335
+ def _CR
336
+ _tmp = scan(/\A(?-mix:\x0D)/)
337
+ set_failed_rule :_CR unless _tmp
338
+ return _tmp
339
+ end
340
+
341
+ # SPACE = " "
342
+ def _SPACE
343
+ _tmp = match_string(" ")
344
+ set_failed_rule :_SPACE unless _tmp
345
+ return _tmp
346
+ end
347
+
348
+ # - = SPACE*
349
+ def __hyphen_
350
+ while true
351
+ _tmp = apply(:_SPACE)
352
+ break unless _tmp
353
+ end
354
+ _tmp = true
355
+ set_failed_rule :__hyphen_ unless _tmp
356
+ return _tmp
357
+ end
358
+
359
+ # AT = "@"
360
+ def _AT
361
+ _tmp = match_string("@")
362
+ set_failed_rule :_AT unless _tmp
363
+ return _tmp
364
+ end
365
+
366
+ # LWSP_char = (SPACE | HTAB)
367
+ def _LWSP_char
368
+
369
+ _save = self.pos
370
+ while true # choice
371
+ _tmp = apply(:_SPACE)
372
+ break if _tmp
373
+ self.pos = _save
374
+ _tmp = apply(:_HTAB)
375
+ break if _tmp
376
+ self.pos = _save
377
+ break
378
+ end # end choice
379
+
380
+ set_failed_rule :_LWSP_char unless _tmp
381
+ return _tmp
382
+ end
383
+
384
+ # CHAR = /[\x00-\x7f]/
385
+ def _CHAR
386
+ _tmp = scan(/\A(?-mix:[\x00-\x7f])/)
387
+ set_failed_rule :_CHAR unless _tmp
388
+ return _tmp
389
+ end
390
+
391
+ # CTL = /[\x00-\x1f\x7f]/
392
+ def _CTL
393
+ _tmp = scan(/\A(?-mix:[\x00-\x1f\x7f])/)
394
+ set_failed_rule :_CTL unless _tmp
395
+ return _tmp
396
+ end
397
+
398
+ # special = /[\]()<>@,;:\\".\[]/
399
+ def _special
400
+ _tmp = scan(/\A(?-mix:[\]()<>@,;:\\".\[])/)
401
+ set_failed_rule :_special unless _tmp
402
+ return _tmp
403
+ end
404
+
405
+ # CRLF = CR LF
406
+ def _CRLF
407
+
408
+ _save = self.pos
409
+ while true # sequence
410
+ _tmp = apply(:_CR)
411
+ unless _tmp
412
+ self.pos = _save
413
+ break
414
+ end
415
+ _tmp = apply(:_LF)
416
+ unless _tmp
417
+ self.pos = _save
418
+ end
419
+ break
420
+ end # end sequence
421
+
422
+ set_failed_rule :_CRLF unless _tmp
423
+ return _tmp
424
+ end
425
+
426
+ # linear_white_space = (CRLF? LWSP_char)+
427
+ def _linear_white_space
428
+ _save = self.pos
429
+
430
+ _save1 = self.pos
431
+ while true # sequence
432
+ _save2 = self.pos
433
+ _tmp = apply(:_CRLF)
434
+ unless _tmp
435
+ _tmp = true
436
+ self.pos = _save2
437
+ end
438
+ unless _tmp
439
+ self.pos = _save1
440
+ break
441
+ end
442
+ _tmp = apply(:_LWSP_char)
443
+ unless _tmp
444
+ self.pos = _save1
445
+ end
446
+ break
447
+ end # end sequence
448
+
449
+ if _tmp
450
+ while true
451
+
452
+ _save3 = self.pos
453
+ while true # sequence
454
+ _save4 = self.pos
455
+ _tmp = apply(:_CRLF)
456
+ unless _tmp
457
+ _tmp = true
458
+ self.pos = _save4
459
+ end
460
+ unless _tmp
461
+ self.pos = _save3
462
+ break
463
+ end
464
+ _tmp = apply(:_LWSP_char)
465
+ unless _tmp
466
+ self.pos = _save3
467
+ end
468
+ break
469
+ end # end sequence
470
+
471
+ break unless _tmp
472
+ end
473
+ _tmp = true
474
+ else
475
+ self.pos = _save
476
+ end
477
+ set_failed_rule :_linear_white_space unless _tmp
478
+ return _tmp
479
+ end
480
+
481
+ # atom = /[^\]\x00-\x20 \x7F\x80-\xFF()<>@,;:\\".\[]+/
482
+ def _atom
483
+ _tmp = scan(/\A(?-mix:[^\]\x00-\x20 \x7F\x80-\xFF()<>@,;:\\".\[]+)/)
484
+ set_failed_rule :_atom unless _tmp
485
+ return _tmp
486
+ end
487
+
488
+ # ctext = (/[^)\\\x0D\x80-\xFF(]+/ | linear_white_space)
489
+ def _ctext
490
+
491
+ _save = self.pos
492
+ while true # choice
493
+ _tmp = scan(/\A(?-mix:[^)\\\x0D\x80-\xFF(]+)/)
494
+ break if _tmp
495
+ self.pos = _save
496
+ _tmp = apply(:_linear_white_space)
497
+ break if _tmp
498
+ self.pos = _save
499
+ break
500
+ end # end choice
501
+
502
+ set_failed_rule :_ctext unless _tmp
503
+ return _tmp
504
+ end
505
+
506
+ # dtext = (/[^\]\\\x0D\x80-\xFF\[]+/ | linear_white_space)
507
+ def _dtext
508
+
509
+ _save = self.pos
510
+ while true # choice
511
+ _tmp = scan(/\A(?-mix:[^\]\\\x0D\x80-\xFF\[]+)/)
512
+ break if _tmp
513
+ self.pos = _save
514
+ _tmp = apply(:_linear_white_space)
515
+ break if _tmp
516
+ self.pos = _save
517
+ break
518
+ end # end choice
519
+
520
+ set_failed_rule :_dtext unless _tmp
521
+ return _tmp
522
+ end
523
+
524
+ # qtext = (/[^"\\\x0D\x80-\xFF]+/ | linear_white_space)
525
+ def _qtext
526
+
527
+ _save = self.pos
528
+ while true # choice
529
+ _tmp = scan(/\A(?-mix:[^"\\\x0D\x80-\xFF]+)/)
530
+ break if _tmp
531
+ self.pos = _save
532
+ _tmp = apply(:_linear_white_space)
533
+ break if _tmp
534
+ self.pos = _save
535
+ break
536
+ end # end choice
537
+
538
+ set_failed_rule :_qtext unless _tmp
539
+ return _tmp
540
+ end
541
+
542
+ # quoted_pair = "\\" CHAR
543
+ def _quoted_pair
544
+
545
+ _save = self.pos
546
+ while true # sequence
547
+ _tmp = match_string("\\")
548
+ unless _tmp
549
+ self.pos = _save
550
+ break
551
+ end
552
+ _tmp = apply(:_CHAR)
553
+ unless _tmp
554
+ self.pos = _save
555
+ end
556
+ break
557
+ end # end sequence
558
+
559
+ set_failed_rule :_quoted_pair unless _tmp
560
+ return _tmp
561
+ end
562
+
563
+ # quoted_string = "\"" (qtext | quoted_pair)* "\""
564
+ def _quoted_string
565
+
566
+ _save = self.pos
567
+ while true # sequence
568
+ _tmp = match_string("\"")
569
+ unless _tmp
570
+ self.pos = _save
571
+ break
572
+ end
573
+ while true
574
+
575
+ _save2 = self.pos
576
+ while true # choice
577
+ _tmp = apply(:_qtext)
578
+ break if _tmp
579
+ self.pos = _save2
580
+ _tmp = apply(:_quoted_pair)
581
+ break if _tmp
582
+ self.pos = _save2
583
+ break
584
+ end # end choice
585
+
586
+ break unless _tmp
587
+ end
588
+ _tmp = true
589
+ unless _tmp
590
+ self.pos = _save
591
+ break
592
+ end
593
+ _tmp = match_string("\"")
594
+ unless _tmp
595
+ self.pos = _save
596
+ end
597
+ break
598
+ end # end sequence
599
+
600
+ set_failed_rule :_quoted_string unless _tmp
601
+ return _tmp
602
+ end
603
+
604
+ # domain_literal = "[" (dtext | quoted_pair)* "]"
605
+ def _domain_literal
606
+
607
+ _save = self.pos
608
+ while true # sequence
609
+ _tmp = match_string("[")
610
+ unless _tmp
611
+ self.pos = _save
612
+ break
613
+ end
614
+ while true
615
+
616
+ _save2 = self.pos
617
+ while true # choice
618
+ _tmp = apply(:_dtext)
619
+ break if _tmp
620
+ self.pos = _save2
621
+ _tmp = apply(:_quoted_pair)
622
+ break if _tmp
623
+ self.pos = _save2
624
+ break
625
+ end # end choice
626
+
627
+ break unless _tmp
628
+ end
629
+ _tmp = true
630
+ unless _tmp
631
+ self.pos = _save
632
+ break
633
+ end
634
+ _tmp = match_string("]")
635
+ unless _tmp
636
+ self.pos = _save
637
+ end
638
+ break
639
+ end # end sequence
640
+
641
+ set_failed_rule :_domain_literal unless _tmp
642
+ return _tmp
643
+ end
644
+
645
+ # comment = "(" (ctext | quoted_pair | comment)* ")"
646
+ def _comment
647
+
648
+ _save = self.pos
649
+ while true # sequence
650
+ _tmp = match_string("(")
651
+ unless _tmp
652
+ self.pos = _save
653
+ break
654
+ end
655
+ while true
656
+
657
+ _save2 = self.pos
658
+ while true # choice
659
+ _tmp = apply(:_ctext)
660
+ break if _tmp
661
+ self.pos = _save2
662
+ _tmp = apply(:_quoted_pair)
663
+ break if _tmp
664
+ self.pos = _save2
665
+ _tmp = apply(:_comment)
666
+ break if _tmp
667
+ self.pos = _save2
668
+ break
669
+ end # end choice
670
+
671
+ break unless _tmp
672
+ end
673
+ _tmp = true
674
+ unless _tmp
675
+ self.pos = _save
676
+ break
677
+ end
678
+ _tmp = match_string(")")
679
+ unless _tmp
680
+ self.pos = _save
681
+ end
682
+ break
683
+ end # end sequence
684
+
685
+ set_failed_rule :_comment unless _tmp
686
+ return _tmp
687
+ end
688
+
689
+ # ocms = comment*
690
+ def _ocms
691
+ while true
692
+ _tmp = apply(:_comment)
693
+ break unless _tmp
694
+ end
695
+ _tmp = true
696
+ set_failed_rule :_ocms unless _tmp
697
+ return _tmp
698
+ end
699
+
700
+ # word = (atom | quoted_string)
701
+ def _word
702
+
703
+ _save = self.pos
704
+ while true # choice
705
+ _tmp = apply(:_atom)
706
+ break if _tmp
707
+ self.pos = _save
708
+ _tmp = apply(:_quoted_string)
709
+ break if _tmp
710
+ self.pos = _save
711
+ break
712
+ end # end choice
713
+
714
+ set_failed_rule :_word unless _tmp
715
+ return _tmp
716
+ end
717
+
718
+ # phrase = (word -)+
719
+ def _phrase
720
+ _save = self.pos
721
+
722
+ _save1 = self.pos
723
+ while true # sequence
724
+ _tmp = apply(:_word)
725
+ unless _tmp
726
+ self.pos = _save1
727
+ break
728
+ end
729
+ _tmp = apply(:__hyphen_)
730
+ unless _tmp
731
+ self.pos = _save1
732
+ end
733
+ break
734
+ end # end sequence
735
+
736
+ if _tmp
737
+ while true
738
+
739
+ _save2 = self.pos
740
+ while true # sequence
741
+ _tmp = apply(:_word)
742
+ unless _tmp
743
+ self.pos = _save2
744
+ break
745
+ end
746
+ _tmp = apply(:__hyphen_)
747
+ unless _tmp
748
+ self.pos = _save2
749
+ end
750
+ break
751
+ end # end sequence
752
+
753
+ break unless _tmp
754
+ end
755
+ _tmp = true
756
+ else
757
+ self.pos = _save
758
+ end
759
+ set_failed_rule :_phrase unless _tmp
760
+ return _tmp
761
+ end
762
+
763
+ # valid = ocms address ocms
764
+ def _valid
765
+
766
+ _save = self.pos
767
+ while true # sequence
768
+ _tmp = apply(:_ocms)
769
+ unless _tmp
770
+ self.pos = _save
771
+ break
772
+ end
773
+ _tmp = apply(:_address)
774
+ unless _tmp
775
+ self.pos = _save
776
+ break
777
+ end
778
+ _tmp = apply(:_ocms)
779
+ unless _tmp
780
+ self.pos = _save
781
+ end
782
+ break
783
+ end # end sequence
784
+
785
+ set_failed_rule :_valid unless _tmp
786
+ return _tmp
787
+ end
788
+
789
+ # address = (mailbox | group)
790
+ def _address
791
+
792
+ _save = self.pos
793
+ while true # choice
794
+ _tmp = apply(:_mailbox)
795
+ break if _tmp
796
+ self.pos = _save
797
+ _tmp = apply(:_group)
798
+ break if _tmp
799
+ self.pos = _save
800
+ break
801
+ end # end choice
802
+
803
+ set_failed_rule :_address unless _tmp
804
+ return _tmp
805
+ end
806
+
807
+ # group = phrase ocms ":" ocms mailbox (ocms "," ocms mailbox)* ocms ";"
808
+ def _group
809
+
810
+ _save = self.pos
811
+ while true # sequence
812
+ _tmp = apply(:_phrase)
813
+ unless _tmp
814
+ self.pos = _save
815
+ break
816
+ end
817
+ _tmp = apply(:_ocms)
818
+ unless _tmp
819
+ self.pos = _save
820
+ break
821
+ end
822
+ _tmp = match_string(":")
823
+ unless _tmp
824
+ self.pos = _save
825
+ break
826
+ end
827
+ _tmp = apply(:_ocms)
828
+ unless _tmp
829
+ self.pos = _save
830
+ break
831
+ end
832
+ _tmp = apply(:_mailbox)
833
+ unless _tmp
834
+ self.pos = _save
835
+ break
836
+ end
837
+ while true
838
+
839
+ _save2 = self.pos
840
+ while true # sequence
841
+ _tmp = apply(:_ocms)
842
+ unless _tmp
843
+ self.pos = _save2
844
+ break
845
+ end
846
+ _tmp = match_string(",")
847
+ unless _tmp
848
+ self.pos = _save2
849
+ break
850
+ end
851
+ _tmp = apply(:_ocms)
852
+ unless _tmp
853
+ self.pos = _save2
854
+ break
855
+ end
856
+ _tmp = apply(:_mailbox)
857
+ unless _tmp
858
+ self.pos = _save2
859
+ end
860
+ break
861
+ end # end sequence
862
+
863
+ break unless _tmp
864
+ end
865
+ _tmp = true
866
+ unless _tmp
867
+ self.pos = _save
868
+ break
869
+ end
870
+ _tmp = apply(:_ocms)
871
+ unless _tmp
872
+ self.pos = _save
873
+ break
874
+ end
875
+ _tmp = match_string(";")
876
+ unless _tmp
877
+ self.pos = _save
878
+ end
879
+ break
880
+ end # end sequence
881
+
882
+ set_failed_rule :_group unless _tmp
883
+ return _tmp
884
+ end
885
+
886
+ # mailbox = (addr_spec | phrase - ocms - angle_addr)
887
+ def _mailbox
888
+
889
+ _save = self.pos
890
+ while true # choice
891
+ _tmp = apply(:_addr_spec)
892
+ break if _tmp
893
+ self.pos = _save
894
+
895
+ _save1 = self.pos
896
+ while true # sequence
897
+ _tmp = apply(:_phrase)
898
+ unless _tmp
899
+ self.pos = _save1
900
+ break
901
+ end
902
+ _tmp = apply(:__hyphen_)
903
+ unless _tmp
904
+ self.pos = _save1
905
+ break
906
+ end
907
+ _tmp = apply(:_ocms)
908
+ unless _tmp
909
+ self.pos = _save1
910
+ break
911
+ end
912
+ _tmp = apply(:__hyphen_)
913
+ unless _tmp
914
+ self.pos = _save1
915
+ break
916
+ end
917
+ _tmp = apply(:_angle_addr)
918
+ unless _tmp
919
+ self.pos = _save1
920
+ end
921
+ break
922
+ end # end sequence
923
+
924
+ break if _tmp
925
+ self.pos = _save
926
+ break
927
+ end # end choice
928
+
929
+ set_failed_rule :_mailbox unless _tmp
930
+ return _tmp
931
+ end
932
+
933
+ # angle_addr = "<" ocms route? ocms addr_spec ">"
934
+ def _angle_addr
935
+
936
+ _save = self.pos
937
+ while true # sequence
938
+ _tmp = match_string("<")
939
+ unless _tmp
940
+ self.pos = _save
941
+ break
942
+ end
943
+ _tmp = apply(:_ocms)
944
+ unless _tmp
945
+ self.pos = _save
946
+ break
947
+ end
948
+ _save1 = self.pos
949
+ _tmp = apply(:_route)
950
+ unless _tmp
951
+ _tmp = true
952
+ self.pos = _save1
953
+ end
954
+ unless _tmp
955
+ self.pos = _save
956
+ break
957
+ end
958
+ _tmp = apply(:_ocms)
959
+ unless _tmp
960
+ self.pos = _save
961
+ break
962
+ end
963
+ _tmp = apply(:_addr_spec)
964
+ unless _tmp
965
+ self.pos = _save
966
+ break
967
+ end
968
+ _tmp = match_string(">")
969
+ unless _tmp
970
+ self.pos = _save
971
+ end
972
+ break
973
+ end # end sequence
974
+
975
+ set_failed_rule :_angle_addr unless _tmp
976
+ return _tmp
977
+ end
978
+
979
+ # route = (AT ocms domain)+ ":"
980
+ def _route
981
+
982
+ _save = self.pos
983
+ while true # sequence
984
+ _save1 = self.pos
985
+
986
+ _save2 = self.pos
987
+ while true # sequence
988
+ _tmp = apply(:_AT)
989
+ unless _tmp
990
+ self.pos = _save2
991
+ break
992
+ end
993
+ _tmp = apply(:_ocms)
994
+ unless _tmp
995
+ self.pos = _save2
996
+ break
997
+ end
998
+ _tmp = apply(:_domain)
999
+ unless _tmp
1000
+ self.pos = _save2
1001
+ end
1002
+ break
1003
+ end # end sequence
1004
+
1005
+ if _tmp
1006
+ while true
1007
+
1008
+ _save3 = self.pos
1009
+ while true # sequence
1010
+ _tmp = apply(:_AT)
1011
+ unless _tmp
1012
+ self.pos = _save3
1013
+ break
1014
+ end
1015
+ _tmp = apply(:_ocms)
1016
+ unless _tmp
1017
+ self.pos = _save3
1018
+ break
1019
+ end
1020
+ _tmp = apply(:_domain)
1021
+ unless _tmp
1022
+ self.pos = _save3
1023
+ end
1024
+ break
1025
+ end # end sequence
1026
+
1027
+ break unless _tmp
1028
+ end
1029
+ _tmp = true
1030
+ else
1031
+ self.pos = _save1
1032
+ end
1033
+ unless _tmp
1034
+ self.pos = _save
1035
+ break
1036
+ end
1037
+ _tmp = match_string(":")
1038
+ unless _tmp
1039
+ self.pos = _save
1040
+ end
1041
+ break
1042
+ end # end sequence
1043
+
1044
+ set_failed_rule :_route unless _tmp
1045
+ return _tmp
1046
+ end
1047
+
1048
+ # addr_spec = local_part ocms "@" ocms domain
1049
+ def _addr_spec
1050
+
1051
+ _save = self.pos
1052
+ while true # sequence
1053
+ _tmp = apply(:_local_part)
1054
+ unless _tmp
1055
+ self.pos = _save
1056
+ break
1057
+ end
1058
+ _tmp = apply(:_ocms)
1059
+ unless _tmp
1060
+ self.pos = _save
1061
+ break
1062
+ end
1063
+ _tmp = match_string("@")
1064
+ unless _tmp
1065
+ self.pos = _save
1066
+ break
1067
+ end
1068
+ _tmp = apply(:_ocms)
1069
+ unless _tmp
1070
+ self.pos = _save
1071
+ break
1072
+ end
1073
+ _tmp = apply(:_domain)
1074
+ unless _tmp
1075
+ self.pos = _save
1076
+ end
1077
+ break
1078
+ end # end sequence
1079
+
1080
+ set_failed_rule :_addr_spec unless _tmp
1081
+ return _tmp
1082
+ end
1083
+
1084
+ # local_part = word ocms ("." ocms word)*
1085
+ def _local_part
1086
+
1087
+ _save = self.pos
1088
+ while true # sequence
1089
+ _tmp = apply(:_word)
1090
+ unless _tmp
1091
+ self.pos = _save
1092
+ break
1093
+ end
1094
+ _tmp = apply(:_ocms)
1095
+ unless _tmp
1096
+ self.pos = _save
1097
+ break
1098
+ end
1099
+ while true
1100
+
1101
+ _save2 = self.pos
1102
+ while true # sequence
1103
+ _tmp = match_string(".")
1104
+ unless _tmp
1105
+ self.pos = _save2
1106
+ break
1107
+ end
1108
+ _tmp = apply(:_ocms)
1109
+ unless _tmp
1110
+ self.pos = _save2
1111
+ break
1112
+ end
1113
+ _tmp = apply(:_word)
1114
+ unless _tmp
1115
+ self.pos = _save2
1116
+ end
1117
+ break
1118
+ end # end sequence
1119
+
1120
+ break unless _tmp
1121
+ end
1122
+ _tmp = true
1123
+ unless _tmp
1124
+ self.pos = _save
1125
+ end
1126
+ break
1127
+ end # end sequence
1128
+
1129
+ set_failed_rule :_local_part unless _tmp
1130
+ return _tmp
1131
+ end
1132
+
1133
+ # domain = sub_domain ocms ("." ocms sub_domain)+
1134
+ def _domain
1135
+
1136
+ _save = self.pos
1137
+ while true # sequence
1138
+ _tmp = apply(:_sub_domain)
1139
+ unless _tmp
1140
+ self.pos = _save
1141
+ break
1142
+ end
1143
+ _tmp = apply(:_ocms)
1144
+ unless _tmp
1145
+ self.pos = _save
1146
+ break
1147
+ end
1148
+ _save1 = self.pos
1149
+
1150
+ _save2 = self.pos
1151
+ while true # sequence
1152
+ _tmp = match_string(".")
1153
+ unless _tmp
1154
+ self.pos = _save2
1155
+ break
1156
+ end
1157
+ _tmp = apply(:_ocms)
1158
+ unless _tmp
1159
+ self.pos = _save2
1160
+ break
1161
+ end
1162
+ _tmp = apply(:_sub_domain)
1163
+ unless _tmp
1164
+ self.pos = _save2
1165
+ end
1166
+ break
1167
+ end # end sequence
1168
+
1169
+ if _tmp
1170
+ while true
1171
+
1172
+ _save3 = self.pos
1173
+ while true # sequence
1174
+ _tmp = match_string(".")
1175
+ unless _tmp
1176
+ self.pos = _save3
1177
+ break
1178
+ end
1179
+ _tmp = apply(:_ocms)
1180
+ unless _tmp
1181
+ self.pos = _save3
1182
+ break
1183
+ end
1184
+ _tmp = apply(:_sub_domain)
1185
+ unless _tmp
1186
+ self.pos = _save3
1187
+ end
1188
+ break
1189
+ end # end sequence
1190
+
1191
+ break unless _tmp
1192
+ end
1193
+ _tmp = true
1194
+ else
1195
+ self.pos = _save1
1196
+ end
1197
+ unless _tmp
1198
+ self.pos = _save
1199
+ end
1200
+ break
1201
+ end # end sequence
1202
+
1203
+ set_failed_rule :_domain unless _tmp
1204
+ return _tmp
1205
+ end
1206
+
1207
+ # sub_domain = (domain_ref | domain_literal)
1208
+ def _sub_domain
1209
+
1210
+ _save = self.pos
1211
+ while true # choice
1212
+ _tmp = apply(:_domain_ref)
1213
+ break if _tmp
1214
+ self.pos = _save
1215
+ _tmp = apply(:_domain_literal)
1216
+ break if _tmp
1217
+ self.pos = _save
1218
+ break
1219
+ end # end choice
1220
+
1221
+ set_failed_rule :_sub_domain unless _tmp
1222
+ return _tmp
1223
+ end
1224
+
1225
+ # domain_ref = atom
1226
+ def _domain_ref
1227
+ _tmp = apply(:_atom)
1228
+ set_failed_rule :_domain_ref unless _tmp
1229
+ return _tmp
1230
+ end
1231
+
1232
+ # root = valid !.
1233
+ def _root
1234
+
1235
+ _save = self.pos
1236
+ while true # sequence
1237
+ _tmp = apply(:_valid)
1238
+ unless _tmp
1239
+ self.pos = _save
1240
+ break
1241
+ end
1242
+ _save1 = self.pos
1243
+ _tmp = get_byte
1244
+ _tmp = _tmp ? nil : true
1245
+ self.pos = _save1
1246
+ unless _tmp
1247
+ self.pos = _save
1248
+ end
1249
+ break
1250
+ end # end sequence
1251
+
1252
+ set_failed_rule :_root unless _tmp
1253
+ return _tmp
1254
+ end
1255
+
1256
+ Rules = {}
1257
+ Rules[:_HTAB] = rule_info("HTAB", "/\\x09/")
1258
+ Rules[:_LF] = rule_info("LF", "/\\x0A/")
1259
+ Rules[:_CR] = rule_info("CR", "/\\x0D/")
1260
+ Rules[:_SPACE] = rule_info("SPACE", "\" \"")
1261
+ Rules[:__hyphen_] = rule_info("-", "SPACE*")
1262
+ Rules[:_AT] = rule_info("AT", "\"@\"")
1263
+ Rules[:_LWSP_char] = rule_info("LWSP_char", "(SPACE | HTAB)")
1264
+ Rules[:_CHAR] = rule_info("CHAR", "/[\\x00-\\x7f]/")
1265
+ Rules[:_CTL] = rule_info("CTL", "/[\\x00-\\x1f\\x7f]/")
1266
+ Rules[:_special] = rule_info("special", "/[\\]()<>@,;:\\\\\".\\[]/")
1267
+ Rules[:_CRLF] = rule_info("CRLF", "CR LF")
1268
+ Rules[:_linear_white_space] = rule_info("linear_white_space", "(CRLF? LWSP_char)+")
1269
+ Rules[:_atom] = rule_info("atom", "/[^\\]\\x00-\\x20 \\x7F\\x80-\\xFF()<>@,;:\\\\\".\\[]+/")
1270
+ Rules[:_ctext] = rule_info("ctext", "(/[^)\\\\\\x0D\\x80-\\xFF(]+/ | linear_white_space)")
1271
+ Rules[:_dtext] = rule_info("dtext", "(/[^\\]\\\\\\x0D\\x80-\\xFF\\[]+/ | linear_white_space)")
1272
+ Rules[:_qtext] = rule_info("qtext", "(/[^\"\\\\\\x0D\\x80-\\xFF]+/ | linear_white_space)")
1273
+ Rules[:_quoted_pair] = rule_info("quoted_pair", "\"\\\\\" CHAR")
1274
+ Rules[:_quoted_string] = rule_info("quoted_string", "\"\\\"\" (qtext | quoted_pair)* \"\\\"\"")
1275
+ Rules[:_domain_literal] = rule_info("domain_literal", "\"[\" (dtext | quoted_pair)* \"]\"")
1276
+ Rules[:_comment] = rule_info("comment", "\"(\" (ctext | quoted_pair | comment)* \")\"")
1277
+ Rules[:_ocms] = rule_info("ocms", "comment*")
1278
+ Rules[:_word] = rule_info("word", "(atom | quoted_string)")
1279
+ Rules[:_phrase] = rule_info("phrase", "(word -)+")
1280
+ Rules[:_valid] = rule_info("valid", "ocms address ocms")
1281
+ Rules[:_address] = rule_info("address", "(mailbox | group)")
1282
+ Rules[:_group] = rule_info("group", "phrase ocms \":\" ocms mailbox (ocms \",\" ocms mailbox)* ocms \";\"")
1283
+ Rules[:_mailbox] = rule_info("mailbox", "(addr_spec | phrase - ocms - angle_addr)")
1284
+ Rules[:_angle_addr] = rule_info("angle_addr", "\"<\" ocms route? ocms addr_spec \">\"")
1285
+ Rules[:_route] = rule_info("route", "(AT ocms domain)+ \":\"")
1286
+ Rules[:_addr_spec] = rule_info("addr_spec", "local_part ocms \"@\" ocms domain")
1287
+ Rules[:_local_part] = rule_info("local_part", "word ocms (\".\" ocms word)*")
1288
+ Rules[:_domain] = rule_info("domain", "sub_domain ocms (\".\" ocms sub_domain)+")
1289
+ Rules[:_sub_domain] = rule_info("sub_domain", "(domain_ref | domain_literal)")
1290
+ Rules[:_domain_ref] = rule_info("domain_ref", "atom")
1291
+ Rules[:_root] = rule_info("root", "valid !.")
1292
+ end