Class: RParsec::Parser

Inherits:
Object
  • Object
show all
Includes:
Functors, Monad
Defined in:
lib/rparsec/parser.rb

Overview

Represents a parser that parses a certain grammar rule.

Constant Summary collapse

MyMonad =
ParserMonad.new

Constants included from Functors

Functors::And, Functors::At, Functors::BitAnd, Functors::Call, Functors::Compare, Functors::Dec, Functors::Div, Functors::Eq, Functors::Feed, Functors::Fst, Functors::Ge, Functors::Gt, Functors::Id, Functors::Idn, Functors::Inc, Functors::Le, Functors::Lt, Functors::Match, Functors::Minus, Functors::Mod, Functors::Mul, Functors::Ne, Functors::Neg, Functors::Not, Functors::Or, Functors::Plus, Functors::Power, Functors::Snd, Functors::Succ, Functors::To_a, Functors::To_f, Functors::To_i, Functors::To_s, Functors::To_sym, Functors::Union, Functors::Xor

Instance Attribute Summary collapse

Attributes included from Monad

#this

Instance Method Summary collapse

Methods included from Monad

#bind, #initMonad, #plus, #value

Methods included from Functors

#compose, #const, #curry, #flip, make_curry, make_reverse_curry, #nth, #power, #reverse_curry, #reverse_uncurry, #uncurry

Instance Attribute Details

#nameObject

Returns the value of attribute name.



21
22
23
# File 'lib/rparsec/parser.rb', line 21

def name
  @name
end

Instance Method Details

#>>(other) ⇒ Object

Similar to #seq. other is auto-boxed if it is not of type Parser.



446
447
448
# File 'lib/rparsec/parser.rb', line 446

def >>(other)
  seq(autobox_parser(other))
end

#atomizeObject

Create a new parser that’s atomic, meaning that when it fails, input consumption is undone.



125
126
127
# File 'lib/rparsec/parser.rb', line 125

def atomize
  AtomParser.new(self).tap { |p| p.name = @name }
end

#bindn(&block) ⇒ Object

self is first executed, the parser result is then passed as parameter to the associated block, which evaluates to another Parser object at runtime. This new Parser object is then executed to get the final parser result.

Different from #bind, parser result of self will be expanded first if it is an array.



105
106
107
108
# File 'lib/rparsec/parser.rb', line 105

def bindn(&block)
  return self unless block
  BoundnParser.new(self, block)
end

#catchp(symbol) ⇒ Object

a.catchp(:somesymbol) will catch the :somesymbol thrown by a.



311
312
313
# File 'lib/rparsec/parser.rb', line 311

def catchp(symbol)
  CatchParser.new(symbol, self)
end

#delimited(delim) ⇒ Object

To create a parser that repeats self for unlimited times, with the pattern recognized by delim as separator that separates each occurrence and also possibly ends the pattern. Return values of self are collected in an array.



279
280
281
# File 'lib/rparsec/parser.rb', line 279

def delimited delim
  delimited1(delim).plus value([])
end

#delimited1(delim) ⇒ Object

To create a parser that repeats self for unlimited times, with the pattern recognized by delim as separator that separates each occurrence and also possibly ends the pattern. self has to match for at least once. Return values of self are collected in an array.



265
266
267
268
269
270
271
# File 'lib/rparsec/parser.rb', line 265

def delimited1 delim
  rest = delim >> (self.plus Parsers.throwp(:__end_delimiter__))
  self.bind do |v0|
    result = [v0]
    (rest.map { |v| result << v }).many_.catchp(:__end_delimiter__) >> value(result)
  end
end

#expect(msg) ⇒ Object

To create a parser that fails with a given error message.



156
157
158
# File 'lib/rparsec/parser.rb', line 156

def expect msg
  ExpectParser.new(self, msg)
end

#followed(other) ⇒ Object Also known as: <<

a.followed b will sequentially run a and b; result of a is preserved as the ultimate return value.



164
165
166
# File 'lib/rparsec/parser.rb', line 164

def followed(other)
  FollowedParser.new(self, other)
end

#fragmentObject

a.fragment will return the string matched by a.



318
319
320
# File 'lib/rparsec/parser.rb', line 318

def fragment
  FragmentParser.new(self)
end

#infixl(op) ⇒ Object

For left-associative infix binary operator. op has to return a Proc that takes two parameters, who are returned by the self parser as operands.



389
390
391
392
393
394
395
396
397
# File 'lib/rparsec/parser.rb', line 389

def infixl(op)
  Parsers.sequence(self, _infix_rest(op, self).many) do |v, rests|
    rests.each do |r|
      f, v1 = *r
      v = f.call(v, v1)
    end
    v
  end
end

#infixn(op) ⇒ Object

For non-associative infix binary operator. op has to return a Proc that takes two parameters, who are returned by the self parser as operands.



375
376
377
378
379
380
381
382
# File 'lib/rparsec/parser.rb', line 375

def infixn(op)
  bind do |v1|
    bin = Parsers.sequence(op, self) do |f, v2|
      f.call(v1, v2)
    end
    bin | value(v1)
  end
end

#infixr(op) ⇒ Object

For right-associative infix binary operator. op has to return a Proc that takes two parameters, who are returned by the self parser as operands.



404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
# File 'lib/rparsec/parser.rb', line 404

def infixr(op)
  Parsers.sequence(self, _infix_rest(op, self).many) do |v, rests|
    if rests.empty?
      v
    else
      f, seed = *rests.last
      for i in (0...rests.length - 1)
        cur = rests.length - 2 - i
        f1, v1 = *rests[cur]
        seed = f.call(v1, seed)
        f = f1
      end
      f.call(v, seed)
    end
  end
end

#lexeme(delim = Parsers.whitespaces) ⇒ Object

a.lexeme(delim) will parse a for 0 or more times and ignore all patterns recognized by delim. Values returned by a are collected in an array.



335
336
337
338
# File 'lib/rparsec/parser.rb', line 335

def lexeme(delim = Parsers.whitespaces)
  delim = delim.many_
  delim >> self.delimited(delim)
end

#lookahead(_n) ⇒ Object

To create a parser that does “look ahead” for n inputs.

WARNING: Not implemented yet?



149
150
151
# File 'lib/rparsec/parser.rb', line 149

def lookahead _n # :nodoc:
  self
end

#many(least = 0) ⇒ Object

To create a parser that repeats self for at least least times. All return values are collected in an array.



214
215
216
# File 'lib/rparsec/parser.rb', line 214

def many(least = 0)
  ManyParser.new(self, least)
end

#many_(least = 0) ⇒ Object

To create a parser that repeats self for at least least times. parser.many_ is equivalent to bnf notation parser*. Only the return value of the last execution is preserved.



206
207
208
# File 'lib/rparsec/parser.rb', line 206

def many_(least = 0)
  Many_Parser.new(self, least)
end

#map(&block) ⇒ Object

a.map { |x| x + 1 } will first execute parser a, when it succeeds, the associated block is executed to transform the result to a new value (increment it in this case).



91
92
93
94
# File 'lib/rparsec/parser.rb', line 91

def map(&block)
  return self unless block
  MapParser.new(self, block)
end

#mapn(&block) ⇒ Object

a.mapn { |x, y| x + y } will first execute parser a, when it succeeds, the array result (if any) is expanded and passed as parameters to the associated block. The result of the block is then used as the parsing result.



116
117
118
119
# File 'lib/rparsec/parser.rb', line 116

def mapn(&block)
  return self unless block
  MapnParser.new(self, block)
end

#nested(parser) ⇒ Object

a.nested b will feed the token array returned by parser a to parser b for a nested parsing.



326
327
328
# File 'lib/rparsec/parser.rb', line 326

def nested(parser)
  NestedParser.new(self, parser)
end

#not(msg = "#{self} unexpected") ⇒ Object Also known as: ~

To create a new parser that succeed only if self fails.



139
140
141
# File 'lib/rparsec/parser.rb', line 139

def not(msg = "#{self} unexpected")
  NotParser.new(self, msg)
end

#optional(default = nil) ⇒ Object

a.optional(default) is equivalent to a.plus(value(default)). See also #plus and #value.



303
304
305
# File 'lib/rparsec/parser.rb', line 303

def optional(default = nil)
  self.plus(value(default))
end

#parse(src) ⇒ Object

parses a string.

Raises:



75
76
77
78
79
80
81
82
83
84
# File 'lib/rparsec/parser.rb', line 75

def parse(src)
  ctxt = ParseContext.new(src)
  return ctxt.result if _parse ctxt
  ctxt.prepare_error
  locator = CodeLocator.new(src)
  raise ParserException.new(ctxt.error.index),
    _add_location_to_error(locator, ctxt,
      _add_encountered_error(ctxt.to_msg,
         _display_current_input(ctxt.error.input, src, ctxt.index)), src)
end

#peekObject

Create a new parser that looks at inputs whthout consuming them.



132
133
134
# File 'lib/rparsec/parser.rb', line 132

def peek
  PeekParser.new(self).tap { |p| p.name = @name }
end

#postfix(op) ⇒ Object

For postfix unary operator. a.postfix op will run parser a for once and then op for 0 or more times. op should return a Proc that accepts one parameter. Proc objects returned by op is then fed with the value returned by a from left to right. The final result is returned as return value.



363
364
365
366
367
368
# File 'lib/rparsec/parser.rb', line 363

def postfix(op)
  Parsers.sequence(self, op.many) do |v, funcs|
    funcs.each { |f| v = f.call(v) }
    v
  end
end

#prefix(op) ⇒ Object

For prefix unary operator. a.prefix op will run parser op for 0 or more times and eventually run parser a for one time. op should return a Proc that accepts one parameter. Proc objects returned by op is then fed with the value returned by a from right to left. The final result is returned as return value.



348
349
350
351
352
353
# File 'lib/rparsec/parser.rb', line 348

def prefix(op)
  Parsers.sequence(op.many, self) do |funcs, v|
    funcs.reverse_each { |f| v = f.call(v) }
    v
  end
end

#repeat(min, max = min) ⇒ Object

To create a parser that repeats self for a minimum min times, and maximally max times. All return values are collected in an array.



191
192
193
194
195
196
197
198
# File 'lib/rparsec/parser.rb', line 191

def repeat(min, max = min)
  return Parsers.failure("min=#{min}, max=#{max}") if min > max
  if min == max
    RepeatParser.new(self, max)
  else
    SomeParser.new(self, min, max)
  end
end

#repeat_(min, max = min) ⇒ Object Also known as: *

To create a parser that repeats self for a minimum min times, and maximally max times. Only the return value of the last execution is preserved.



174
175
176
177
178
179
180
181
182
183
# File 'lib/rparsec/parser.rb', line 174

def repeat_(min, max = min)
  return Parsers.failure("min=#{min}, max=#{max}") if min > max
  if min == max
    return Parsers.one if max <= 0
    return self if max == 1
    Repeat_Parser.new(self, max)
  else
    Some_Parser.new(self, min, max)
  end
end

#separated(delim) ⇒ Object

To create a parser that repeats self for unlimited times, with the pattern recognized by delim as separator that separates each occurrence. Return values of self are collected in an array.



254
255
256
# File 'lib/rparsec/parser.rb', line 254

def separated delim
  separated1(delim).plus value([])
end

#separated1(delim) ⇒ Object

To create a parser that repeats self for unlimited times, with the pattern recognized by delim as separator that separates each occurrence. self has to match for at least once. Return values of self are collected in an array.



240
241
242
243
244
245
246
# File 'lib/rparsec/parser.rb', line 240

def separated1 delim
  rest = delim >> self
  self.bind do |v0|
    result = [v0]
    (rest.map { |v| result << v }).many_ >> value(result)
  end
end

#seq(other, &block) ⇒ Object

a.seq b will sequentially run a then b. The result of b is preserved as return value. If a block is associated, values returned by a and b are passed into the block and the return value of the block is used as the final result of the parser.



438
439
440
# File 'lib/rparsec/parser.rb', line 438

def seq(other, &block)
  Parsers.sequence(self, other, &block)
end

#some(max) ⇒ Object

To create a parser that repeats self for at most max times. All return values are collected in an array.



230
231
232
# File 'lib/rparsec/parser.rb', line 230

def some(max)
  repeat(0, max)
end

#some_(max) ⇒ Object

To create a parser that repeats self for at most max times. Only the return value of the last execution is preserved.



222
223
224
# File 'lib/rparsec/parser.rb', line 222

def some_(max)
  repeat_(0, max)
end

#to_sObject

String representation



286
287
288
289
# File 'lib/rparsec/parser.rb', line 286

def to_s
  return name unless name.nil?
  self.class.to_s
end

#token(kind) ⇒ Object

a.token(:word_token) will return a Token object when a succeeds. The matched string (or the string returned by a, if any) is encapsulated in the token, together with the :word_token symbol and the starting index of the match.



427
428
429
# File 'lib/rparsec/parser.rb', line 427

def token(kind)
  TokenParser.new(kind, self)
end

#|(other) ⇒ Object

a | b will run b when a fails. b is auto-boxed to Parser when it is not of type Parser.



295
296
297
# File 'lib/rparsec/parser.rb', line 295

def | other
  AltParser.new([self, autobox_parser(other)])
end