Class: Paco::Parser
- Inherits:
-
Object
- Object
- Paco::Parser
- Defined in:
- lib/paco/parser.rb
Instance Attribute Summary collapse
-
#desc ⇒ Object
readonly
Returns the value of attribute desc.
Instance Method Summary collapse
- #_parse(ctx) ⇒ Object
-
#at_least(num) ⇒ Object
Returns a parser that runs ‘parser` at least `num` times, and returns an array of the results.
-
#at_most(num) ⇒ Object
Returns a parser that runs ‘parser` at most `num` times, and returns an array of the results.
-
#bind(&block) ⇒ Paco::Parser
(also: #chain)
Returns a new parser which tries ‘parser`, and on success calls the `block` with the result of the parse, which is expected to return another parser, which will be tried next.
-
#failure(ctx) ⇒ Object
Raises ParseError.
-
#fallback(value) ⇒ Paco::Parser
Returns a new parser which tries ‘parser` and, if it fails, returns `value` without consuming any input.
-
#fmap(&block) ⇒ Paco::Parser
Transforms the output of ‘parser` with the given block.
-
#initialize(desc = "", &block) ⇒ Parser
constructor
A new instance of Parser.
-
#join(separator = "") ⇒ Paco::Parser
Returns a parser that runs ‘parser` and concatenate it results with the `separator`.
-
#many ⇒ Paco::Parser
Expects ‘parser` zero or more times, and returns an array of the results.
-
#next(other) ⇒ Paco::Parser
(also: #>)
Expects ‘other` parser to follow `parser`, but returns only the value of `other` parser.
-
#not_followed_by(other) ⇒ Paco::Parser
Returns a parser that runs passed ‘other` parser without consuming the input, and returns result of the `parser` if the passed one _does not match_ the input.
-
#or(other) ⇒ Paco::Parser
(also: #|)
Returns a new parser which tries ‘parser`, and if it fails uses `other`.
- #parse(input, with_callstack: false) ⇒ Object
-
#result(value) ⇒ Paco::Parser
Returns a new parser with the same behavior, but which returns passed ‘value`.
-
#skip(other) ⇒ Paco::Parser
(also: #<)
Expects ‘other` parser to follow `parser`, but returns only the value of `parser`.
-
#times(min, max = nil) ⇒ Paco::Parser
Returns a parser that runs ‘parser` between `min` and `max` times, and returns an array of the results.
-
#trim(other) ⇒ Paco::Parser
Expects ‘other` parser before and after `parser`, and returns the result of the parser.
- #with_desc(desc) ⇒ Paco::Parser
-
#wrap(before, after) ⇒ Paco::Parser
Expects the parser ‘before` before `parser` and `after` after `parser.
Constructor Details
#initialize(desc = "", &block) ⇒ Parser
Returns a new instance of Parser.
10 11 12 13 |
# File 'lib/paco/parser.rb', line 10 def initialize(desc = "", &block) @desc = desc @block = block end |
Instance Attribute Details
#desc ⇒ Object (readonly)
Returns the value of attribute desc.
7 8 9 |
# File 'lib/paco/parser.rb', line 7 def desc @desc end |
Instance Method Details
#_parse(ctx) ⇒ Object
30 31 32 33 34 35 |
# File 'lib/paco/parser.rb', line 30 def _parse(ctx) ctx.start_parse(self) res = @block.call(ctx, self) ctx.success_parse(res, self) res end |
#at_least(num) ⇒ Object
Returns a parser that runs ‘parser` at least `num` times, and returns an array of the results.
168 169 170 171 172 |
# File 'lib/paco/parser.rb', line 168 def at_least(num) Paco::Combinators.seq(times(num), many) do |head, rest| head + rest end end |
#at_most(num) ⇒ Object
Returns a parser that runs ‘parser` at most `num` times, and returns an array of the results.
176 177 178 |
# File 'lib/paco/parser.rb', line 176 def at_most(num) times(0, num) end |
#bind(&block) ⇒ Paco::Parser Also known as: chain
Returns a new parser which tries ‘parser`, and on success calls the `block` with the result of the parse, which is expected to return another parser, which will be tried next. This allows you to dynamically decide how to continue the parse, which is impossible with the other Paco::Combinators.
88 89 90 91 92 |
# File 'lib/paco/parser.rb', line 88 def bind(&block) Parser.new("#{desc}.bind") do |ctx| block.call(_parse(ctx))._parse(ctx) end end |
#failure(ctx) ⇒ Object
Raises ParseError
40 41 42 43 |
# File 'lib/paco/parser.rb', line 40 def failure(ctx) ctx.failure_parse(self) raise ParseError.new(ctx, desc), "", [] end |
#fallback(value) ⇒ Paco::Parser
Returns a new parser which tries ‘parser` and, if it fails, returns `value` without consuming any input.
109 110 111 |
# File 'lib/paco/parser.rb', line 109 def fallback(value) self.or(Paco::Combinators.succeed(value)) end |
#fmap(&block) ⇒ Paco::Parser
Transforms the output of ‘parser` with the given block.
76 77 78 79 80 |
# File 'lib/paco/parser.rb', line 76 def fmap(&block) Parser.new("#{desc}.fmap") do |ctx| block.call(_parse(ctx)) end end |
#join(separator = "") ⇒ Paco::Parser
Returns a parser that runs ‘parser` and concatenate it results with the `separator`.
139 140 141 |
# File 'lib/paco/parser.rb', line 139 def join(separator = "") fmap { |result| result.join(separator) } end |
#many ⇒ Paco::Parser
Expects ‘parser` zero or more times, and returns an array of the results.
97 98 99 |
# File 'lib/paco/parser.rb', line 97 def many Paco::Combinators.many(self) end |
#next(other) ⇒ Paco::Parser Also known as: >
Expects ‘other` parser to follow `parser`, but returns only the value of `other` parser.
68 69 70 71 |
# File 'lib/paco/parser.rb', line 68 def next(other) Paco::Combinators.seq(self, other).fmap { |results| results[1] } .with_desc("#{desc}.next(#{other.desc})") end |
#not_followed_by(other) ⇒ Paco::Parser
Returns a parser that runs passed ‘other` parser without consuming the input, and returns result of the `parser` if the passed one _does not match_ the input. Fails otherwise.
132 133 134 |
# File 'lib/paco/parser.rb', line 132 def not_followed_by(other) skip(Paco::Combinators.not_followed_by(other)) end |
#or(other) ⇒ Paco::Parser Also known as: |
Returns a new parser which tries ‘parser`, and if it fails uses `other`.
48 49 50 51 52 53 54 |
# File 'lib/paco/parser.rb', line 48 def or(other) Parser.new("or(#{desc}, #{other.desc})") do |ctx| _parse(ctx) rescue ParseError other._parse(ctx) end end |
#parse(input, with_callstack: false) ⇒ Object
24 25 26 27 |
# File 'lib/paco/parser.rb', line 24 def parse(input, with_callstack: false) ctx = input.is_a?(Context) ? input : Context.new(input, with_callstack: with_callstack) skip(Paco::Combinators.eof)._parse(ctx) end |
#result(value) ⇒ Paco::Parser
Returns a new parser with the same behavior, but which returns passed ‘value`.
103 104 105 |
# File 'lib/paco/parser.rb', line 103 def result(value) fmap { value } end |
#skip(other) ⇒ Paco::Parser Also known as: <
Expects ‘other` parser to follow `parser`, but returns only the value of `parser`.
60 61 62 |
# File 'lib/paco/parser.rb', line 60 def skip(other) Paco::Combinators.seq(self, other).fmap { |results| results[0] }.with_desc("#{desc}.skip(#{other.desc})") end |
#times(min, max = nil) ⇒ Paco::Parser
Returns a parser that runs ‘parser` between `min` and `max` times, and returns an array of the results. When `max` is not specified, `max` = `min`.
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/paco/parser.rb', line 148 def times(min, max = nil) max ||= min if min < 0 || max < min raise ArgumentError, "invalid attributes: min `#{min}`, max `#{max}`" end Parser.new("#{desc}.times(#{min}, #{max})") do |ctx| results = min.times.map { _parse(ctx) } (max - min).times.each do results << _parse(ctx) rescue ParseError break end results end end |
#trim(other) ⇒ Paco::Parser
Expects ‘other` parser before and after `parser`, and returns the result of the parser.
116 117 118 |
# File 'lib/paco/parser.rb', line 116 def trim(other) other.next(self).skip(other) end |
#with_desc(desc) ⇒ Paco::Parser
17 18 19 20 |
# File 'lib/paco/parser.rb', line 17 def with_desc(desc) @desc = desc self end |
#wrap(before, after) ⇒ Paco::Parser
Expects the parser ‘before` before `parser` and `after` after `parser. Returns the result of the parser.
124 125 126 |
# File 'lib/paco/parser.rb', line 124 def wrap(before, after) Paco::Combinators.wrap(before, after, self) end |