ghazel-parslet 1.4.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/HISTORY.txt +195 -0
- data/LICENSE +23 -0
- data/README +70 -0
- data/Rakefile +49 -0
- data/example/boolean_algebra.rb +70 -0
- data/example/calc.rb +153 -0
- data/example/comments.rb +35 -0
- data/example/deepest_errors.rb +131 -0
- data/example/documentation.rb +18 -0
- data/example/email_parser.rb +52 -0
- data/example/empty.rb +13 -0
- data/example/erb.rb +47 -0
- data/example/ignore.rb +33 -0
- data/example/ip_address.rb +125 -0
- data/example/json.rb +128 -0
- data/example/local.rb +34 -0
- data/example/mathn.rb +44 -0
- data/example/minilisp.rb +94 -0
- data/example/modularity.rb +47 -0
- data/example/nested_errors.rb +132 -0
- data/example/output/boolean_algebra.out +4 -0
- data/example/output/calc.out +1 -0
- data/example/output/comments.out +8 -0
- data/example/output/deepest_errors.out +54 -0
- data/example/output/documentation.err +4 -0
- data/example/output/documentation.out +1 -0
- data/example/output/email_parser.out +2 -0
- data/example/output/empty.err +1 -0
- data/example/output/erb.out +7 -0
- data/example/output/ignore.out +1 -0
- data/example/output/ignore_whitespace.out +1 -0
- data/example/output/ip_address.out +9 -0
- data/example/output/json.out +5 -0
- data/example/output/local.out +3 -0
- data/example/output/mathn.out +4 -0
- data/example/output/minilisp.out +5 -0
- data/example/output/modularity.out +0 -0
- data/example/output/nested_errors.out +54 -0
- data/example/output/parens.out +8 -0
- data/example/output/readme.out +1 -0
- data/example/output/seasons.out +28 -0
- data/example/output/sentence.out +1 -0
- data/example/output/simple_xml.out +2 -0
- data/example/output/string_parser.out +3 -0
- data/example/parens.rb +42 -0
- data/example/readme.rb +30 -0
- data/example/seasons.rb +46 -0
- data/example/sentence.rb +36 -0
- data/example/simple.lit +3 -0
- data/example/simple_xml.rb +54 -0
- data/example/string_parser.rb +77 -0
- data/example/test.lit +4 -0
- data/lib/parslet.rb +254 -0
- data/lib/parslet/atoms.rb +32 -0
- data/lib/parslet/atoms/alternative.rb +50 -0
- data/lib/parslet/atoms/base.rb +124 -0
- data/lib/parslet/atoms/can_flatten.rb +137 -0
- data/lib/parslet/atoms/context.rb +94 -0
- data/lib/parslet/atoms/dsl.rb +98 -0
- data/lib/parslet/atoms/entity.rb +41 -0
- data/lib/parslet/atoms/lookahead.rb +49 -0
- data/lib/parslet/atoms/named.rb +32 -0
- data/lib/parslet/atoms/re.rb +38 -0
- data/lib/parslet/atoms/repetition.rb +63 -0
- data/lib/parslet/atoms/rule.rb +12 -0
- data/lib/parslet/atoms/rule/position.rb +143 -0
- data/lib/parslet/atoms/sequence.rb +38 -0
- data/lib/parslet/atoms/str.rb +37 -0
- data/lib/parslet/atoms/visitor.rb +89 -0
- data/lib/parslet/cause.rb +94 -0
- data/lib/parslet/convenience.rb +35 -0
- data/lib/parslet/error_reporter.rb +7 -0
- data/lib/parslet/error_reporter/deepest.rb +95 -0
- data/lib/parslet/error_reporter/tree.rb +57 -0
- data/lib/parslet/export.rb +162 -0
- data/lib/parslet/expression.rb +51 -0
- data/lib/parslet/expression/treetop.rb +92 -0
- data/lib/parslet/parser.rb +67 -0
- data/lib/parslet/pattern.rb +114 -0
- data/lib/parslet/pattern/binding.rb +49 -0
- data/lib/parslet/rig/rspec.rb +51 -0
- data/lib/parslet/slice.rb +101 -0
- data/lib/parslet/source.rb +62 -0
- data/lib/parslet/source/line_cache.rb +95 -0
- data/lib/parslet/transform.rb +236 -0
- data/lib/parslet/transform/context.rb +32 -0
- metadata +264 -0
data/example/comments.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# A small example on how to parse common types of comments. The example
|
2
|
+
# started out with parser code from Stephen Waits.
|
3
|
+
|
4
|
+
$:.unshift File.dirname(__FILE__) + "/../lib"
|
5
|
+
|
6
|
+
require 'pp'
|
7
|
+
require 'parslet'
|
8
|
+
require 'parslet/convenience'
|
9
|
+
|
10
|
+
class ALanguage < Parslet::Parser
|
11
|
+
root(:lines)
|
12
|
+
|
13
|
+
rule(:lines) { line.repeat }
|
14
|
+
rule(:line) { spaces >> expression.repeat >> newline }
|
15
|
+
rule(:newline) { str("\n") >> str("\r").maybe }
|
16
|
+
|
17
|
+
rule(:expression) { (str('a').as(:a) >> spaces).as(:exp) }
|
18
|
+
|
19
|
+
rule(:spaces) { space.repeat }
|
20
|
+
rule(:space) { multiline_comment | line_comment | str(' ') }
|
21
|
+
|
22
|
+
rule(:line_comment) { (str('//') >> (newline.absent? >> any).repeat).as(:line) }
|
23
|
+
rule(:multiline_comment) { (str('/*') >> (str('*/').absent? >> any).repeat >> str('*/')).as(:multi) }
|
24
|
+
end
|
25
|
+
|
26
|
+
code = %q(
|
27
|
+
a
|
28
|
+
// line comment
|
29
|
+
a a a // line comment
|
30
|
+
a /* inline comment */ a
|
31
|
+
/* multiline
|
32
|
+
comment */
|
33
|
+
)
|
34
|
+
|
35
|
+
pp ALanguage.new.parse_with_debug(code)
|
@@ -0,0 +1,131 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__) + "/../lib"
|
2
|
+
|
3
|
+
# This example demonstrates how to do deepest error reporting, as invented
|
4
|
+
# by John Mettraux (issue #64).
|
5
|
+
|
6
|
+
require 'parslet'
|
7
|
+
require 'parslet/convenience'
|
8
|
+
|
9
|
+
def prettify(str)
|
10
|
+
puts " "*3 + " "*4 + "." + " "*4 + "10" + " "*3 + "." + " "*4 + "20"
|
11
|
+
str.lines.each_with_index do |line, index|
|
12
|
+
printf "%02d %s\n",
|
13
|
+
index+1,
|
14
|
+
line.chomp
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class Parser < Parslet::Parser
|
19
|
+
# commons
|
20
|
+
|
21
|
+
rule(:space) { match('[ \t]').repeat(1) }
|
22
|
+
rule(:space?) { space.maybe }
|
23
|
+
|
24
|
+
rule(:newline) { match('[\r\n]') }
|
25
|
+
|
26
|
+
rule(:comment) { str('#') >> match('[^\r\n]').repeat }
|
27
|
+
|
28
|
+
rule(:line_separator) {
|
29
|
+
(space? >> ((comment.maybe >> newline) | str(';')) >> space?).repeat(1)
|
30
|
+
}
|
31
|
+
|
32
|
+
rule(:blank) { line_separator | space }
|
33
|
+
rule(:blank?) { blank.maybe }
|
34
|
+
|
35
|
+
rule(:identifier) { match('[a-zA-Z0-9_]').repeat(1) }
|
36
|
+
|
37
|
+
# res_statement
|
38
|
+
|
39
|
+
rule(:reference) {
|
40
|
+
(str('@').repeat(1,2) >> identifier).as(:reference)
|
41
|
+
}
|
42
|
+
|
43
|
+
rule(:res_action_or_link) {
|
44
|
+
str('.').as(:dot) >> (identifier >> str('?').maybe ).as(:name) >> str('()')
|
45
|
+
}
|
46
|
+
|
47
|
+
rule(:res_actions) {
|
48
|
+
(
|
49
|
+
reference
|
50
|
+
).as(:resources) >>
|
51
|
+
(
|
52
|
+
res_action_or_link.as(:res_action)
|
53
|
+
).repeat(0).as(:res_actions)
|
54
|
+
}
|
55
|
+
|
56
|
+
rule(:res_statement) {
|
57
|
+
res_actions >>
|
58
|
+
(str(':') >> identifier.as(:name)).maybe.as(:res_field)
|
59
|
+
}
|
60
|
+
|
61
|
+
# expression
|
62
|
+
|
63
|
+
rule(:expression) {
|
64
|
+
res_statement
|
65
|
+
}
|
66
|
+
|
67
|
+
# body
|
68
|
+
|
69
|
+
rule(:body) {
|
70
|
+
(line_separator >> (block | expression)).repeat(1).as(:body) >>
|
71
|
+
line_separator
|
72
|
+
}
|
73
|
+
|
74
|
+
# blocks
|
75
|
+
|
76
|
+
rule(:begin_block) {
|
77
|
+
(str('concurrent').as(:type) >> space).maybe.as(:pre) >>
|
78
|
+
str('begin').as(:begin) >>
|
79
|
+
body >>
|
80
|
+
str('end')
|
81
|
+
}
|
82
|
+
|
83
|
+
rule(:define_block) {
|
84
|
+
str('define').as(:define) >> space >>
|
85
|
+
identifier.as(:name) >> str('()') >>
|
86
|
+
body >>
|
87
|
+
str('end')
|
88
|
+
}
|
89
|
+
|
90
|
+
rule(:block) {
|
91
|
+
define_block | begin_block
|
92
|
+
}
|
93
|
+
|
94
|
+
# root
|
95
|
+
|
96
|
+
rule(:radix) {
|
97
|
+
line_separator.maybe >> block >> line_separator.maybe
|
98
|
+
}
|
99
|
+
|
100
|
+
root(:radix)
|
101
|
+
end
|
102
|
+
|
103
|
+
ds = [
|
104
|
+
%{
|
105
|
+
define f()
|
106
|
+
@res.name
|
107
|
+
end
|
108
|
+
},
|
109
|
+
%{
|
110
|
+
define f()
|
111
|
+
begin
|
112
|
+
@res.name
|
113
|
+
end
|
114
|
+
end
|
115
|
+
}
|
116
|
+
]
|
117
|
+
|
118
|
+
ds.each do |d|
|
119
|
+
|
120
|
+
puts '-' * 80
|
121
|
+
prettify(d)
|
122
|
+
|
123
|
+
parser = Parser.new
|
124
|
+
|
125
|
+
begin
|
126
|
+
parser.parse_with_debug(d,
|
127
|
+
:reporter => Parslet::ErrorReporter::Deepest.new)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
puts '-' * 80
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# A small example that shows a really small parser and what happens on parser
|
2
|
+
# errors.
|
3
|
+
|
4
|
+
$:.unshift File.dirname(__FILE__) + "/../lib"
|
5
|
+
|
6
|
+
require 'pp'
|
7
|
+
require 'parslet'
|
8
|
+
|
9
|
+
class MyParser < Parslet::Parser
|
10
|
+
rule(:a) { str('a').repeat }
|
11
|
+
|
12
|
+
def parse(str)
|
13
|
+
a.parse(str)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
pp MyParser.new.parse('aaaa')
|
18
|
+
pp MyParser.new.parse('bbbb')
|
@@ -0,0 +1,52 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Example contributed by Hal Brodigan (postmodern). Thanks!
|
4
|
+
|
5
|
+
$:.unshift File.dirname(__FILE__) + "/../lib"
|
6
|
+
require 'parslet'
|
7
|
+
require 'parslet/convenience'
|
8
|
+
|
9
|
+
class EmailParser < Parslet::Parser
|
10
|
+
rule(:space) { match('\s').repeat(1) }
|
11
|
+
rule(:space?) { space.maybe }
|
12
|
+
rule(:dash?) { match['_-'].maybe }
|
13
|
+
|
14
|
+
rule(:at) {
|
15
|
+
str('@') |
|
16
|
+
(dash? >> (str('at') | str('AT')) >> dash?)
|
17
|
+
}
|
18
|
+
rule(:dot) {
|
19
|
+
str('.') |
|
20
|
+
(dash? >> (str('dot') | str('DOT')) >> dash?)
|
21
|
+
}
|
22
|
+
|
23
|
+
rule(:word) { match('[a-z0-9]').repeat(1).as(:word) >> space? }
|
24
|
+
rule(:separator) { dot.as(:dot) >> space? | space }
|
25
|
+
rule(:words) { word >> (separator >> word).repeat }
|
26
|
+
|
27
|
+
rule(:email) {
|
28
|
+
(words.as(:username) >> space? >> at >> space? >> words).as(:email)
|
29
|
+
}
|
30
|
+
|
31
|
+
root(:email)
|
32
|
+
end
|
33
|
+
|
34
|
+
class EmailSanitizer < Parslet::Transform
|
35
|
+
rule(:dot => simple(:dot), :word => simple(:word)) { ".#{word}" }
|
36
|
+
rule(:word => simple(:word)) { word }
|
37
|
+
|
38
|
+
rule(:username => sequence(:username)) { username.join + "@" }
|
39
|
+
rule(:username => simple(:username)) { username.to_s + "@" }
|
40
|
+
|
41
|
+
rule(:email => sequence(:email)) { email.join }
|
42
|
+
end
|
43
|
+
|
44
|
+
parser = EmailParser.new
|
45
|
+
sanitizer = EmailSanitizer.new
|
46
|
+
|
47
|
+
unless ARGV[0]
|
48
|
+
STDERR.puts "usage: #{$0} \"EMAIL_ADDR\""
|
49
|
+
STDOUT.puts "since you haven't specified any EMAIL_ADDR, for testing purposes we're using a.b.c.d@gmail.com"
|
50
|
+
end
|
51
|
+
|
52
|
+
p sanitizer.apply(parser.parse_with_debug(ARGV[0] || 'a.b.c.d@gmail.com'))
|
data/example/empty.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Basically just demonstrates that you can leave rules empty and get a nice
|
2
|
+
# NotImplementedError. A way to quickly spec out your parser rules?
|
3
|
+
|
4
|
+
$:.unshift File.dirname(__FILE__) + "/../lib"
|
5
|
+
|
6
|
+
require 'parslet'
|
7
|
+
|
8
|
+
class Parser < Parslet::Parser
|
9
|
+
rule(:empty) { }
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
Parser.new.empty.parslet
|
data/example/erb.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# Example that demonstrates how a simple erb-like parser could be constructed.
|
2
|
+
|
3
|
+
$:.unshift File.dirname(__FILE__) + "/../lib"
|
4
|
+
|
5
|
+
require 'parslet'
|
6
|
+
|
7
|
+
class ErbParser < Parslet::Parser
|
8
|
+
rule(:ruby) { (str('%>').absent? >> any).repeat.as(:ruby) }
|
9
|
+
|
10
|
+
rule(:expression) { (str('=') >> ruby).as(:expression) }
|
11
|
+
rule(:comment) { (str('#') >> ruby).as(:comment) }
|
12
|
+
rule(:code) { ruby.as(:code) }
|
13
|
+
rule(:erb) { expression | comment | code }
|
14
|
+
|
15
|
+
rule(:erb_with_tags) { str('<%') >> erb >> str('%>') }
|
16
|
+
rule(:text) { (str('<%').absent? >> any).repeat(1) }
|
17
|
+
|
18
|
+
rule(:text_with_ruby) { (text.as(:text) | erb_with_tags).repeat.as(:text) }
|
19
|
+
root(:text_with_ruby)
|
20
|
+
end
|
21
|
+
|
22
|
+
parser = ErbParser.new
|
23
|
+
p parser.parse "The value of x is <%= x %>."
|
24
|
+
p parser.parse "<% 1 + 2 %>"
|
25
|
+
p parser.parse "<%# commented %>"
|
26
|
+
|
27
|
+
|
28
|
+
evaluator = Parslet::Transform.new do
|
29
|
+
|
30
|
+
erb_binding = binding
|
31
|
+
|
32
|
+
rule(:code => { :ruby => simple(:ruby) }) { eval(ruby, erb_binding); '' }
|
33
|
+
rule(:expression => { :ruby => simple(:ruby) }) { eval(ruby, erb_binding) }
|
34
|
+
rule(:comment => { :ruby => simple(:ruby) }) { '' }
|
35
|
+
|
36
|
+
rule(:text => simple(:text)) { text }
|
37
|
+
rule(:text => sequence(:texts)) { texts.join }
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
puts evaluator.apply(parser.parse(<<-ERB
|
42
|
+
The <% a = 2 %>not printed result of "a = 2".
|
43
|
+
The <%# a = 1 %>not printed non-evaluated comment "a = 1", see the value of a below.
|
44
|
+
The <%= 'nicely' %> printed result.
|
45
|
+
The <% b = 3 %>value of a is <%= a %>, and b is <%= b %>.
|
46
|
+
ERB
|
47
|
+
))
|
data/example/ignore.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# A small example on how to make parslet ignore parts of the parse tree.
|
2
|
+
|
3
|
+
$:.unshift File.dirname(__FILE__) + "/../lib"
|
4
|
+
require 'parslet'
|
5
|
+
|
6
|
+
class IgnoreParslet < Parslet::Atoms::Base
|
7
|
+
def initialize(parslet)
|
8
|
+
@parslet = parslet
|
9
|
+
end
|
10
|
+
def to_s_inner(prec)
|
11
|
+
@parslet.to_s(prec)
|
12
|
+
end
|
13
|
+
def try(source, context)
|
14
|
+
success, value = result = @parslet.try(source, context)
|
15
|
+
|
16
|
+
return succ(nil) if success
|
17
|
+
return result
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
module IgnoreDSL
|
22
|
+
def ignore
|
23
|
+
IgnoreParslet.new(self)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class Parslet::Atoms::Base
|
28
|
+
include IgnoreDSL
|
29
|
+
end
|
30
|
+
|
31
|
+
include Parslet
|
32
|
+
p (str('a') >> str('b').ignore >> str('c')).
|
33
|
+
parse('abc')
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# This example is heavily inspired by citrus' ip.citrus. Have a look at both
|
2
|
+
# of these to get some choice!
|
3
|
+
|
4
|
+
# The grammars in this file conform to the ABNF given in Appendix A of RFC 3986
|
5
|
+
# Uniform Resource Identifier (URI): Generic Syntax.
|
6
|
+
#
|
7
|
+
# See http://tools.ietf.org/html/rfc3986#appendix-A for more information.
|
8
|
+
|
9
|
+
$:.unshift File.dirname(__FILE__) + "/../lib"
|
10
|
+
|
11
|
+
require 'pp'
|
12
|
+
require 'parslet'
|
13
|
+
|
14
|
+
module IPv4
|
15
|
+
include Parslet
|
16
|
+
|
17
|
+
# A host identified by an IPv4 literal address is represented in
|
18
|
+
# dotted-decimal notation (a sequence of four decimal numbers in the range 0
|
19
|
+
# to 255, separated by "."), as described in [RFC1123] by reference to
|
20
|
+
# [RFC0952]. Note that other forms of dotted notation may be interpreted on
|
21
|
+
# some platforms, as described in Section 7.4, but only the dotted-decimal
|
22
|
+
# form of four octets is allowed by this grammar.
|
23
|
+
rule(:ipv4) {
|
24
|
+
(dec_octet >> str('.') >> dec_octet >> str('.') >>
|
25
|
+
dec_octet >> str('.') >> dec_octet).as(:ipv4)
|
26
|
+
}
|
27
|
+
|
28
|
+
rule(:dec_octet) {
|
29
|
+
str('25') >> match("[0-5]") |
|
30
|
+
str('2') >> match("[0-4]") >> digit |
|
31
|
+
str('1') >> digit >> digit |
|
32
|
+
match('[1-9]') >> digit |
|
33
|
+
digit
|
34
|
+
}
|
35
|
+
|
36
|
+
rule(:digit) {
|
37
|
+
match('[0-9]')
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
# Must be used in concert with IPv4
|
42
|
+
module IPv6
|
43
|
+
include Parslet
|
44
|
+
|
45
|
+
rule(:colon) { str(':') }
|
46
|
+
rule(:dcolon) { colon >> colon }
|
47
|
+
|
48
|
+
# h16 :
|
49
|
+
def h16r(times)
|
50
|
+
(h16 >> colon).repeat(times, times)
|
51
|
+
end
|
52
|
+
|
53
|
+
# : h16
|
54
|
+
def h16l(times)
|
55
|
+
(colon >> h16).repeat(0,times)
|
56
|
+
end
|
57
|
+
|
58
|
+
# A 128-bit IPv6 address is divided into eight 16-bit pieces. Each piece is
|
59
|
+
# represented numerically in case-insensitive hexadecimal, using one to four
|
60
|
+
# hexadecimal digits (leading zeroes are permitted). The eight encoded
|
61
|
+
# pieces are given most-significant first, separated by colon characters.
|
62
|
+
# Optionally, the least-significant two pieces may instead be represented in
|
63
|
+
# IPv4 address textual format. A sequence of one or more consecutive
|
64
|
+
# zero-valued 16-bit pieces within the address may be elided, omitting all
|
65
|
+
# their digits and leaving exactly two consecutive colons in their place to
|
66
|
+
# mark the elision.
|
67
|
+
rule(:ipv6) {
|
68
|
+
(
|
69
|
+
(
|
70
|
+
h16r(6) |
|
71
|
+
dcolon >> h16r(5) |
|
72
|
+
h16.maybe >> dcolon >> h16r(4) |
|
73
|
+
(h16 >> h16l(1)).maybe >> dcolon >> h16r(3) |
|
74
|
+
(h16 >> h16l(2)).maybe >> dcolon >> h16r(2) |
|
75
|
+
(h16 >> h16l(3)).maybe >> dcolon >> h16r(1) |
|
76
|
+
(h16 >> h16l(4)).maybe >> dcolon
|
77
|
+
) >> ls32 |
|
78
|
+
(h16 >> h16l(5)).maybe >> dcolon >> h16 |
|
79
|
+
(h16 >> h16l(6)).maybe >> dcolon
|
80
|
+
).as(:ipv6)
|
81
|
+
}
|
82
|
+
|
83
|
+
rule(:h16) {
|
84
|
+
hexdigit.repeat(1,4)
|
85
|
+
}
|
86
|
+
|
87
|
+
rule(:ls32) {
|
88
|
+
(h16 >> colon >> h16) |
|
89
|
+
ipv4
|
90
|
+
}
|
91
|
+
|
92
|
+
rule(:hexdigit) {
|
93
|
+
digit | match("[a-fA-F]")
|
94
|
+
}
|
95
|
+
end
|
96
|
+
|
97
|
+
class Parser
|
98
|
+
include IPv4
|
99
|
+
include IPv6
|
100
|
+
|
101
|
+
def parse(str)
|
102
|
+
(ipv4 | ipv6).parse(str)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
%W(
|
107
|
+
0.0.0.0
|
108
|
+
255.255.255.255
|
109
|
+
255.255.255
|
110
|
+
1:2:3:4:5:6:7:8
|
111
|
+
12AD:34FC:A453:1922::
|
112
|
+
12AD::34FC
|
113
|
+
12AD::
|
114
|
+
::
|
115
|
+
1:2
|
116
|
+
).each do |address|
|
117
|
+
parser = Parser.new
|
118
|
+
printf "%30s -> ", address
|
119
|
+
begin
|
120
|
+
result = parser.parse(address)
|
121
|
+
puts result.inspect
|
122
|
+
rescue Parslet::ParseFailed => m
|
123
|
+
puts "Failed: #{m}"
|
124
|
+
end
|
125
|
+
end
|