From c24c8df9e1c02cad80ea447d7224a3fece98647f Mon Sep 17 00:00:00 2001 From: rameel Date: Sun, 16 Feb 2025 00:54:09 +0500 Subject: [PATCH 1/2] Rename BeforeParser to ThenIgnoreParser to align with parser name --- src/Ramstack.Parsing/Parser.ThenIgnore.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Ramstack.Parsing/Parser.ThenIgnore.cs b/src/Ramstack.Parsing/Parser.ThenIgnore.cs index 45334c3..9580faa 100644 --- a/src/Ramstack.Parsing/Parser.ThenIgnore.cs +++ b/src/Ramstack.Parsing/Parser.ThenIgnore.cs @@ -9,15 +9,15 @@ partial class Parser /// The type of the value produced by the first parser. /// The type of the value produced by the second parser, which is ignored. /// The initial parser whose result is returned. - /// The subsequent parser. + /// The subsequent parser, applied after the initial parser. /// /// A parser that sequentially applies the current parser and a specified second parser, /// returning the result of the first parser with ignoring the result of the second. /// - public static Parser ThenIgnore(this Parser parser, Parser before) => - new ThenIgnoreParser(parser, before.Void()); + public static Parser ThenIgnore(this Parser parser, Parser ignore) => + new ThenIgnoreParser(parser, ignore.Void()); - #region Inner type: BeforeParser + #region Inner type: ThenIgnoreParser /// /// Represents a parser that sequentially applies an initial parser and a specified second parser, @@ -25,8 +25,8 @@ public static Parser ThenIgnore(this Parser parser /// /// The type of the value produced by the first parser. /// The initial parser whose result is returned. - /// The subsequent parser, applied after the initial parser. - private sealed class ThenIgnoreParser(Parser parser, Parser before) : Parser + /// The subsequent parser, applied after the initial parser. + private sealed class ThenIgnoreParser(Parser parser, Parser ignore) : Parser { /// public override bool TryParse(ref ParseContext context, [NotNullWhen(true)] out T? value) @@ -37,7 +37,7 @@ public override bool TryParse(ref ParseContext context, [NotNullWhen(true)] out { var (index, length) = context.MatchedSegment; - if (before.TryParse(ref context, out _)) + if (ignore.TryParse(ref context, out _)) { context.SetMatched(index, length); return true; @@ -50,7 +50,7 @@ public override bool TryParse(ref ParseContext context, [NotNullWhen(true)] out /// protected internal override Parser ToVoidParser() => - new ThenIgnoreParser(parser.Void(), before); + new ThenIgnoreParser(parser.Void(), ignore); } #endregion From 7794448099bd8cd18df3117dacaf6cb7e1c0abbc Mon Sep 17 00:00:00 2001 From: rameel Date: Sun, 16 Feb 2025 02:36:41 +0500 Subject: [PATCH 2/2] Add Literal.QuotedCharacter --- src/Ramstack.Parsing/Literal.Char.cs | 24 ++++++++++++++ .../LiteralTests.Char.cs | 31 +++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 src/Ramstack.Parsing/Literal.Char.cs create mode 100644 tests/Ramstack.Parsing.Tests/LiteralTests.Char.cs diff --git a/src/Ramstack.Parsing/Literal.Char.cs b/src/Ramstack.Parsing/Literal.Char.cs new file mode 100644 index 0000000..29e8f6f --- /dev/null +++ b/src/Ramstack.Parsing/Literal.Char.cs @@ -0,0 +1,24 @@ +using static Ramstack.Parsing.Parser; + +namespace Ramstack.Parsing; + +partial class Literal +{ + private static Parser? _quotedCharacter; + + /// + /// Gets a parser that matches a character enclosed in single quotes. + /// + public static Parser QuotedCharacter => _quotedCharacter ??= + Choice( + EscapeSequence, + UnicodeEscapeSequence, + Not( + Choice( + L('\''), + L('\n'), + L('\r')) + ).Then(Any)) + .Between(L('\''), L('\'')) + .As("quoted-character"); +} diff --git a/tests/Ramstack.Parsing.Tests/LiteralTests.Char.cs b/tests/Ramstack.Parsing.Tests/LiteralTests.Char.cs new file mode 100644 index 0000000..732d62a --- /dev/null +++ b/tests/Ramstack.Parsing.Tests/LiteralTests.Char.cs @@ -0,0 +1,31 @@ +namespace Ramstack.Parsing; + +partial class LiteralTests +{ + [TestCase("'1'", '1')] + [TestCase("'\\u0045'", '\u0045')] + [TestCase("'\\r'", '\r')] + [TestCase("'\\n'", '\n')] + [TestCase("'\\t'", '\t')] + public void QuotedCharacterTest(string input, char expected) + { + Assert.That( + Literal.QuotedCharacter.Parse(input).Value, + Is.EqualTo(expected)); + } + + [TestCase("'1")] + [TestCase("'\\uabcw'")] + [TestCase("'\\u123q'")] + [TestCase("'\\z'")] + [TestCase("'\r'")] + [TestCase("'\n'")] + [TestCase("'\''")] + [TestCase("'a")] + [TestCase("'ab'")] + public void QuotedCharacter_Error(string input) + { + var parser = Literal.QuotedCharacter; + Assert.That(parser.Parse(input).Success, Is.False); + } +}