diff options
| author | Matthew Hall <hallmatthew314@gmail.com> | 2023-03-30 20:39:50 +1300 |
|---|---|---|
| committer | Matthew Hall <hallmatthew314@gmail.com> | 2023-03-30 20:39:50 +1300 |
| commit | f4a7dcce562ff672651f36306423d37eaaa01fed (patch) | |
| tree | 842265e7833d1662daa7e945dd6f68bb8732671e | |
| parent | 9f32fd6424386336a332b0b50a7fd6ebce95345e (diff) | |
Move Result and Tokens to their own files
| -rw-r--r-- | src/parcom.cr | 70 | ||||
| -rw-r--r-- | src/parcom/result.cr | 24 | ||||
| -rw-r--r-- | src/parcom/tokens.cr | 54 |
3 files changed, 78 insertions, 70 deletions
diff --git a/src/parcom.cr b/src/parcom.cr index 7f0e475..b75cb0f 100644 --- a/src/parcom.cr +++ b/src/parcom.cr @@ -51,75 +51,5 @@ module Parcom .parse(tokens) end end - - # `Tokens` is an `Array` wrapper struct to store the input - # stream of one or more `Parser` objects. - # A `Tokens` can be created from any `Iterable`, along with - # `String` objects using a special constructor. - struct Tokens(T) - getter tokens - - # Constructs a `Tokens(Char)` from a `String`. - def self.from_string(s : String) : Tokens(Char) - Tokens.new(s.chars) - end - - # Constructs a `Tokens` from an `Iterable`. - def initialize(ts : Iterable(T)) - if ts.responds_to?(:to_a) - @tokens = ts.to_a - else - @tokens = [] of T - ts.each { |t| @tokens << t } - end - end - - # Exposes `Array#[](Int)`. - def [](index : Int) : T - @tokens[index] - end - - # Exposes `Array#[](Int, Int)`, but wraps the returned array in a new `Tokens`. - def [](start : Int, count : Int) : Tokens(T) - Tokens.new(@tokens[start, count]) - end - - # Exposes `Array#[](Range)`, but wraps the returned array in a new `Tokens`. - def [](range : Range) : Tokens(T) - Tokens.new(@tokens[range]) - end - - # Like `#[]`, but returns `nil` instead of raising an `IndexError`. - def []?(*args) - self.[](*args) - rescue IndexError - nil - end - - # Exposes `Array#empty?`. - def empty? : Bool - @tokens.empty? - end - end - - # A `Result` stores a `Tokens` object and a parsed value, - # and is effectively used to store the state of a parser chain. - # This is used instead of a `Tuple` or `NamedTuple` because: - # 1. This is more idiomatic than a `Tuple`. - # 2. Crystal does not support generic named tuples. - struct Result(T, U) - getter tokens, value - - def initialize(@tokens : Tokens(T), @value : U) - end - - def map(f : U -> V) : Result(T, V) forall V - Result.new(@tokens, f.call(@value)) - end - - def map(&block : U -> V) : Result(T, V) forall V - map(block) - end - end end diff --git a/src/parcom/result.cr b/src/parcom/result.cr new file mode 100644 index 0000000..4a21a16 --- /dev/null +++ b/src/parcom/result.cr @@ -0,0 +1,24 @@ +require "../parcom.cr" + +module Parcom + # A `Result` stores a `Tokens` object and a parsed value, + # and is effectively used to store the state of a parser chain. + # This is used instead of a `Tuple` or `NamedTuple` because: + # 1. This is more idiomatic than a `Tuple`. + # 2. Crystal does not support generic named tuples. + struct Result(T, U) + getter tokens, value + + def initialize(@tokens : Tokens(T), @value : U) + end + + def map(f : U -> V) : Result(T, V) forall V + Result.new(@tokens, f.call(@value)) + end + + def map(&block : U -> V) : Result(T, V) forall V + map(block) + end + end +end + diff --git a/src/parcom/tokens.cr b/src/parcom/tokens.cr new file mode 100644 index 0000000..21c0e10 --- /dev/null +++ b/src/parcom/tokens.cr @@ -0,0 +1,54 @@ +require "../parcom.cr" + +module Parcom + # `Tokens` is an `Array` wrapper struct to store the input + # stream of one or more `Parser` objects. + # A `Tokens` can be created from any `Iterable`, along with + # `String` objects using a special constructor. + struct Tokens(T) + getter tokens + + # Constructs a `Tokens(Char)` from a `String`. + def self.from_string(s : String) : Tokens(Char) + Tokens.new(s.chars) + end + + # Constructs a `Tokens` from an `Iterable`. + def initialize(ts : Iterable(T)) + if ts.responds_to?(:to_a) + @tokens = ts.to_a + else + @tokens = [] of T + ts.each { |t| @tokens << t } + end + end + + # Exposes `Array#[](Int)`. + def [](index : Int) : T + @tokens[index] + end + + # Exposes `Array#[](Int, Int)`, but wraps the returned array in a new `Tokens`. + def [](start : Int, count : Int) : Tokens(T) + Tokens.new(@tokens[start, count]) + end + + # Exposes `Array#[](Range)`, but wraps the returned array in a new `Tokens`. + def [](range : Range) : Tokens(T) + Tokens.new(@tokens[range]) + end + + # Like `#[]`, but returns `nil` instead of raising an `IndexError`. + def []?(*args) + self.[](*args) + rescue IndexError + nil + end + + # Exposes `Array#empty?`. + def empty? : Bool + @tokens.empty? + end + end +end + |
