Module: Rsec::Parser
- Included in:
- Binary, Cached, RepeatAtLeastN, RepeatN, RepeatRange, SeqOne, SeqOne_, Seq_, Unary
- Defined in:
- lib/rsec/parser.rb,
lib/rsec/helpers.rb
Overview
combinators attached to parsers
Instance Attribute Summary collapse
-
#name ⇒ Object
Returns the value of attribute name.
Instance Method Summary collapse
-
#&(other, &p) ⇒ Object
@ desc Lookahead predicate, note that other can be a very complex parser.
-
#*(n, &p) ⇒ Object
@ desc Repeat n or in a range.
-
#<<(other, &p) ⇒ Object
@ desc Short for seq_(parser, other).
-
#>>(other, &p) ⇒ Object
@ desc Short for seq_(parser, other).
-
#^(other, &p) ⇒ Object
@ desc Negative lookahead predicate.
-
#cached(&p) ⇒ Object
@ desc Packrat parser combinator, returns a parser that caches parse result, may optimize performance.
-
#eof(&p) ⇒ Object
@ desc Should be end of input after parse.
-
#fail(*tokens, &p) ⇒ Object
(also: #expect)
@ desc When parsing failed, show “expect tokens” error.
- #inspect ⇒ Object
-
#join(inter, &p) ⇒ Object
@ desc “p.join(‘+’)” parses strings like “p+p+p+p+p”.
-
#map(lambda_p = nil, &p) ⇒ Object
@ desc Transform result @ example parser = /w+/.r.map{|word| word * 2} assert_equal ‘hellohello’, parser.parse!(‘hello’).
-
#maybe(&p) ⇒ Object
(also: #_?)
@ desc Appears 0 or 1 times, result is wrapped in an array @ example parser = ‘a’.r.maybe assert_equal [‘a’], parser.parse(‘a’) assert_equal [], parser.parse(”).
-
#parse(str, source_name = 'source') ⇒ Object
parses string<br/> returns nil if unparsed.
-
#parse!(str, source_name = 'source') ⇒ Object
almost the same as parse<br/> but raises SyntaxError.
-
#star(&p) ⇒ Object
@ desc Kleen star, 0 or more any times.
-
#|(y, &p) ⇒ Object
@ desc Branch parser, note that rsec is a PEG parser generator, beware of the difference between PEG and CFG.
Instance Attribute Details
#name ⇒ Object
Returns the value of attribute name.
24 25 26 |
# File 'lib/rsec/parser.rb', line 24 def name @name end |
Instance Method Details
#&(other, &p) ⇒ Object
@ desc
Lookahead predicate, note that other can be a very complex parser
257 258 259 260 |
# File 'lib/rsec/helpers.rb', line 257 def & other, &p other = Rsec.make_parser other LookAhead[self, other].map p end |
#*(n, &p) ⇒ Object
@ desc
Repeat n or in a range.
If range.end < 0, repeat at least range.begin
(Infinity and -Infinity are considered)
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
# File 'lib/rsec/helpers.rb', line 217 def * n, &p # FIXME if self is an epsilon parser, will cause infinite loop parser = if n.is_a?(Range) raise "invalid n: #{n}" if n.begin < 0 Rsec.assert_type n.begin, Integer end_inf = (n.end.infinite? rescue false) (Rsec.assert_type n.end, Integer) unless end_inf if n.end > 0 RepeatRange[self, n] else RepeatAtLeastN[self, n.begin] end else Rsec.assert_type n, Integer raise "invalid n: #{n}" if n < 0 RepeatN[self, n] end parser.map p end |
#<<(other, &p) ⇒ Object
@ desc
Short for seq_(parser, other)[0]
287 288 289 290 291 |
# File 'lib/rsec/helpers.rb', line 287 def << other, &p other = Rsec.make_parser other right = Rsec.try_skip_pattern other SeqOne_[self, [right], SkipPattern[/\s*/], 0].map p end |
#>>(other, &p) ⇒ Object
@ desc
Short for seq_(parser, other)[1]
279 280 281 282 283 |
# File 'lib/rsec/helpers.rb', line 279 def >> other, &p other = Rsec.make_parser other left = Rsec.try_skip_pattern self SeqOne_[left, [other], SkipPattern[/\s*/], 1].map p end |
#^(other, &p) ⇒ Object
@ desc
Negative lookahead predicate
264 265 266 267 |
# File 'lib/rsec/helpers.rb', line 264 def ^ other, &p other = Rsec.make_parser other NegativeLookAhead[self, other].map p end |
#cached(&p) ⇒ Object
@ desc
Packrat parser combinator, returns a parser that caches parse result, may optimize performance
301 302 303 |
# File 'lib/rsec/helpers.rb', line 301 def cached &p Cached[self].map p end |
#eof(&p) ⇒ Object
@ desc
Should be end of input after parse
295 296 297 |
# File 'lib/rsec/helpers.rb', line 295 def eof &p Eof[self].map p end |
#fail(*tokens, &p) ⇒ Object Also known as: expect
@ desc
When parsing failed, show "expect tokens" error
271 272 273 274 |
# File 'lib/rsec/helpers.rb', line 271 def fail *tokens, &p return self if tokens.empty? Fail[self, tokens].map p end |
#inspect ⇒ Object
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/rsec/parser.rb', line 25 def inspect # TODO move @name ||= self.class.to_s[/\w+$/] case self when Lazy "<#{name}>" when Binary "<#{name} #{left.inspect} #{right.inspect}>" when Seq, Seq_, Branch # don't use redefined map! res = [] each{|e| res << e.inspect} "<#{name} #{res.join ' '}>" when Unary "<#{name} #{some.inspect}>" else "<#{name}>" end end |
#join(inter, &p) ⇒ Object
@ desc
"p.join('+')" parses strings like "p+p+p+p+p".
Note that at least 1 of p appears in the string.
Sometimes it is useful to reverse the joining:
/\s*/.r.join('p').odd parses string like " p p p "
194 195 196 197 |
# File 'lib/rsec/helpers.rb', line 194 def join inter, &p inter = Rsec.make_parser inter Join[self, inter].map p end |
#map(lambda_p = nil, &p) ⇒ Object
@ desc
Transform result
@ example
parser = /\w+/.r.map{|word| word * 2}
assert_equal 'hellohello', parser.parse!('hello')
182 183 184 185 186 187 |
# File 'lib/rsec/helpers.rb', line 182 def map lambda_p=nil, &p return self if (lambda_p.nil? and p.nil?) p = lambda_p || p raise TypeError, 'should give a proc or lambda' unless (p.is_a? Proc) Map[self, p] end |
#maybe(&p) ⇒ Object Also known as: _?
@ desc
Appears 0 or 1 times, result is wrapped in an array
@ example
parser = 'a'.r.maybe
assert_equal ['a'], parser.parse('a')
assert_equal [], parser.parse('')
244 245 246 |
# File 'lib/rsec/helpers.rb', line 244 def maybe &p Maybe[self].map &p end |
#parse(str, source_name = 'source') ⇒ Object
parses string<br/> returns nil if unparsed
8 9 10 11 |
# File 'lib/rsec/parser.rb', line 8 def parse str, source_name='source' ctx = ParseContext.new str, source_name _parse ctx end |
#parse!(str, source_name = 'source') ⇒ Object
almost the same as parse<br/> but raises SyntaxError
15 16 17 18 19 20 21 22 |
# File 'lib/rsec/parser.rb', line 15 def parse! str, source_name='source' ctx = ParseContext.new str, source_name ret = _parse ctx if INVALID[ret] raise ctx.generate_error source_name end ret end |
#star(&p) ⇒ Object
@ desc
Kleen star, 0 or more any times
251 252 253 |
# File 'lib/rsec/helpers.rb', line 251 def star &p self.* (0..-1), &p end |
#|(y, &p) ⇒ Object
@ desc
Branch parser, note that rsec is a PEG parser generator,
beware of the difference between PEG and CFG.
202 203 204 205 206 207 208 209 210 211 |
# File 'lib/rsec/helpers.rb', line 202 def | y, &p y = Rsec.make_parser y arr = if (is_a?(Branch) and !p) [*some, y] else [self, y] end Branch[arr].map p end |