Class: Python::Parser::Combinator
- Inherits:
-
Object
- Object
- Python::Parser::Combinator
show all
- Defined in:
- lib/python/parser/combinator.rb
Constant Summary
collapse
- ParserDefinitionError =
Class.new(RuntimeError)
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
Constructor Details
#initialize(&proc) ⇒ Combinator
Returns a new instance of Combinator.
18
19
20
|
# File 'lib/python/parser/combinator.rb', line 18
def initialize(&proc)
@f = proc
end
|
Instance Attribute Details
#f ⇒ Object
Returns the value of attribute f.
17
18
19
|
# File 'lib/python/parser/combinator.rb', line 17
def f
@f
end
|
Class Method Details
.any_char(x) ⇒ Object
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
# File 'lib/python/parser/combinator.rb', line 127
def self.any_char(x)
case x
when String
chars = x.cahrs.map{|c| char(c)}
if chars.length < 0
raise ParserDefinitionError.new
else
chars.inject(&:|)
end
when Range
chars = x.map{|c| char(c)}
if chars.length < 0
raise ParserDefinitionError.new
else
chars.inject(&:|)
end
else
raise ParserDefinitionError.new
end
end
|
.binopl(parser, op_proc_parser) ⇒ Object
178
179
180
181
182
183
184
185
186
187
188
|
# File 'lib/python/parser/combinator.rb', line 178
def self.binopl(parser, op_proc_parser)
rest = proc{|a|
op_proc_parser >> proc{|f|
parser >> proc{|b|
rest.call(f.call(a, b))
}} | ret(a)
}
parser >> proc{|a|
rest.call(a)
}
end
|
.char(char) ⇒ Object
123
124
125
|
# File 'lib/python/parser/combinator.rb', line 123
def self.char(char)
sat{|c| c == char}
end
|
.discardl(parser1, parser2) ⇒ Object
80
81
82
|
# File 'lib/python/parser/combinator.rb', line 80
def self.discardl(parser1, parser2)
parser1 >> proc{parser2}
end
|
.discardr(parser1, parser2) ⇒ Object
84
85
86
87
88
89
|
# File 'lib/python/parser/combinator.rb', line 84
def self.discardr(parser1, parser2)
parser1 >> proc{|x|
parser2 >> proc{
ret(x)
}}
end
|
.either(parser1, parser2) ⇒ Object
67
68
69
70
71
72
73
74
75
76
77
78
|
# File 'lib/python/parser/combinator.rb', line 67
def self.either(parser1, parser2)
new{|inp|
case result = parser1.parse(inp)
when Failed
parser2.parse(inp)
when Succeeded
result
else
raise "error."
end
}
end
|
.failure ⇒ Object
46
47
48
|
# File 'lib/python/parser/combinator.rb', line 46
def self.failure
new{|inp| Failed.new}
end
|
.item ⇒ Object
50
51
52
|
# File 'lib/python/parser/combinator.rb', line 50
def self.item
new{|inp| inp.size == 0 ? Failed.new : Succeeded.new(inp[0], inp[1, inp.size - 1])}
end
|
.many(parser) ⇒ Object
106
107
108
|
# File 'lib/python/parser/combinator.rb', line 106
def self.many(parser)
many1(parser) | ret([])
end
|
.many1(parser) ⇒ Object
110
111
112
113
114
115
|
# File 'lib/python/parser/combinator.rb', line 110
def self.many1(parser)
parser >> proc{|x|
many(parser) >> proc{|xs|
ret([x] + xs)
}}
end
|
.optional(parser) ⇒ Object
102
103
104
|
# File 'lib/python/parser/combinator.rb', line 102
def self.optional(parser)
(parser >> proc{|x| ret([x])}) | ret([])
end
|
.parser(name, &proc) ⇒ Object
190
191
192
193
194
195
196
197
198
199
200
201
202
203
|
# File 'lib/python/parser/combinator.rb', line 190
def self.parser(name, &proc)
@cache ||= {}
spcls = class << self; self end
spcls.send(:define_method, name) do |*args|
key = [name, args]
if @cache[key]
return @cache[key]
else
@cache[key] = self.new{}
@cache[key].f = proc.call(*args).f
return @cache[key]
end
end
end
|
.ret(something) ⇒ Object
42
43
44
|
# File 'lib/python/parser/combinator.rb', line 42
def self.ret(something)
new{|inp| Succeeded.new(something, inp)}
end
|
.sat(&proc) ⇒ Object
117
118
119
120
121
|
# File 'lib/python/parser/combinator.rb', line 117
def self.sat(&proc)
item >> proc{|c|
proc.call(c) ? ret(c) : failure
}
end
|
.separator(element_parser, separating_token_str) ⇒ Object
91
92
93
94
95
96
|
# File 'lib/python/parser/combinator.rb', line 91
def self.separator(element_parser, separating_token_str)
element_parser >> proc{|x|
many(token_str(separating_token_str) + element_parser) >> proc{|xs|
ret([x] + xs)
}}
end
|
.separator_allow_empty(element_parser, separating_token_str) ⇒ Object
98
99
100
|
# File 'lib/python/parser/combinator.rb', line 98
def self.separator_allow_empty(element_parser, separating_token_str)
separator(element_parser, separating_token_str) | ret([])
end
|
.so(parser, &proc) ⇒ Object
54
55
56
57
58
59
60
61
62
63
64
65
|
# File 'lib/python/parser/combinator.rb', line 54
def self.so(parser, &proc)
new{|inp|
case result = parser.parse(inp)
when Failed
result
when Succeeded
proc.call(result.parsed).parse(result.rest)
else
raise "error."
end
}
end
|
.string(str) ⇒ Object
148
149
150
151
152
153
154
155
156
157
158
|
# File 'lib/python/parser/combinator.rb', line 148
def self.string(str)
if str.size == 0
ret(str)
else
char(str[0]) >> proc{|c|
string(str[1, str.size - 1]) >> proc{
ret(str)
}
}
end
end
|
.token(parser) ⇒ Object
166
167
168
169
170
171
172
|
# File 'lib/python/parser/combinator.rb', line 166
def self.token(parser)
whitespace >> proc{
parser >> proc{|x|
whitespace >> proc{
ret(x)
}}}
end
|
.token_str(str) ⇒ Object
174
175
176
|
# File 'lib/python/parser/combinator.rb', line 174
def self.token_str(str)
token(string(str))
end
|
.whitespace ⇒ Object
160
161
162
163
164
|
# File 'lib/python/parser/combinator.rb', line 160
def self.whitespace
many(char("\s") | char("\t")) >> proc{|ws|
ret(:whitespace)
}
end
|
Instance Method Details
#+(other) ⇒ Object
34
35
36
|
# File 'lib/python/parser/combinator.rb', line 34
def +(other)
self.class.discardl(self, other)
end
|
#-(other) ⇒ Object
38
39
40
|
# File 'lib/python/parser/combinator.rb', line 38
def -(other)
self.class.discardr(self, other)
end
|
#>>(proc) ⇒ Object
26
27
28
|
# File 'lib/python/parser/combinator.rb', line 26
def >>(proc)
self.class.so(self, &proc)
end
|
#parse(inp) ⇒ Object
22
23
24
|
# File 'lib/python/parser/combinator.rb', line 22
def parse(inp)
@f.call(inp)
end
|
#|(other) ⇒ Object
30
31
32
|
# File 'lib/python/parser/combinator.rb', line 30
def |(other)
self.class.either(self, other)
end
|