aboutsummaryrefslogtreecommitdiff
path: root/src/__OLD_parcom.cr
diff options
context:
space:
mode:
Diffstat (limited to 'src/__OLD_parcom.cr')
-rw-r--r--src/__OLD_parcom.cr84
1 files changed, 84 insertions, 0 deletions
diff --git a/src/__OLD_parcom.cr b/src/__OLD_parcom.cr
new file mode 100644
index 0000000..ddb2e50
--- /dev/null
+++ b/src/__OLD_parcom.cr
@@ -0,0 +1,84 @@
+require "./parcom/*"
+
+module Parcom
+ VERSION = "0.1.0"
+
+ # A ParserFail exception should be raised by `Parser#parse` when
+ # a parse attempt is unsuccessful.
+ # Raising this exception in the `#parse` method of a Parser "Foo"
+ # usually follows this pattern to allow for error tracing:
+ #
+ # ```
+ # class Foo(T, V) < Parser(T, V)
+ # def parse(tokens : Tokens(T)) : Result(T, V)
+ # helper.parse(tokens)
+ # rescue ex : ParserFail
+ # raise ParserFail.new("Foo: #{ex.message}")
+ # end
+ # ```
+ class ParserFail < Exception
+ 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, V)
+ getter tokens, value
+
+ def initialize(@tokens : Tokens(T), @value : V)
+ end
+ end
+end
+