aboutsummaryrefslogtreecommitdiff
path: root/spec/parser_chain_spec.cr
diff options
context:
space:
mode:
Diffstat (limited to 'spec/parser_chain_spec.cr')
-rw-r--r--spec/parser_chain_spec.cr79
1 files changed, 79 insertions, 0 deletions
diff --git a/spec/parser_chain_spec.cr b/spec/parser_chain_spec.cr
new file mode 100644
index 0000000..3f1e3a0
--- /dev/null
+++ b/spec/parser_chain_spec.cr
@@ -0,0 +1,79 @@
+require "./spec_helper"
+
+include Parcom
+
+describe "parser_chain" do
+ it "works with zero intermediate steps" do
+ p = parser_chain "test", Char, Char, finally: Parser(Char, Char).pure('x')
+ tokens = Tokens.from_string("abcd")
+ result = p.parse(tokens)
+
+ result.value.should eq('x')
+ result.tokens.should eq(tokens)
+ end
+
+ it "works with one intermediate step" do
+ p = parser_chain "test", Char, Char,
+ {c, Parser(Char, Char).any_token},
+ finally: Parser(Char, Char).pure(c)
+ tokens = Tokens.from_string("abcd")
+ result = p.parse(tokens)
+
+ result.value.should eq('a')
+ result.tokens.should eq(tokens[1..])
+ end
+
+ it "works with many intermediate steps" do
+ digit = Parser(Char, Char).satisfy(&.number?)
+ p = parser_chain "float", Char, Float64,
+ {sign, Parser.token('-').map_const(-1).recover(1)},
+ {front, digit.many},
+ {point, Parser.token('.').optional},
+ {back, digit.many},
+ finally: case {front.empty?, point.nil?, back.empty?}
+ when {false, _, true}
+ Parser(Char, Float64).pure(front.join.to_f64 * sign)
+ when {true, false, false}
+ Parser(Char, Float64).pure("0.#{back.join}".to_f64 * sign)
+ when {false, false, false}
+ Parser(Char, Float64).pure("#{front.join}.#{back.join}".to_f64 * sign)
+ else
+ Parser(Char, Float64).flunk
+ end
+ {
+ {"1", 1_f64},
+ {"-1", -1_f64},
+ {"2.", 2_f64},
+ {"-2.", -2_f64},
+ {".3", 0.3_f64},
+ {"-.3", -0.3_f64},
+ {"0.4", 0.4_f64},
+ {"-0.4", -0.4_f64},
+ }.each do |s, v|
+ tokens = Tokens.from_string(s)
+ result = p.parse(tokens)
+
+ result.value.should eq(v)
+ result.tokens.empty?.should be_true
+ end
+ end
+
+ it "allows ignoring results with underscores" do
+ any_word = Parser(Char, String).satisfy(&.letter?).some.map(&.join)
+ ws = Parser(Char, Array(Char)).satisfy(&.whitespace?).many
+ two_words = parser_chain "two words", Char, {String, String},
+ {word, any_word},
+ {_, ws},
+ finally: Parser.token_sequence(word.chars).map_const({word, word})
+
+ tokens = Tokens.from_string("foo \n foo")
+ result = two_words.parse(tokens)
+ result.value.should eq({"foo", "foo"})
+
+ tokens = Tokens.from_string("foo bar")
+ expect_raises(ParserFail) { two_words.parse(tokens) }
+ tokens = Tokens.from_string("foofoo")
+ expect_raises(ParserFail) { two_words.parse(tokens) }
+ end
+end
+