Skip to content

Commit b1b61d5

Browse files
authored
Merge pull request #9 from rameel/enhancement
Enhancements
2 parents 45b5b6b + 7794448 commit b1b61d5

3 files changed

Lines changed: 63 additions & 8 deletions

File tree

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using static Ramstack.Parsing.Parser;
2+
3+
namespace Ramstack.Parsing;
4+
5+
partial class Literal
6+
{
7+
private static Parser<char>? _quotedCharacter;
8+
9+
/// <summary>
10+
/// Gets a parser that matches a character enclosed in single quotes.
11+
/// </summary>
12+
public static Parser<char> QuotedCharacter => _quotedCharacter ??=
13+
Choice(
14+
EscapeSequence,
15+
UnicodeEscapeSequence,
16+
Not(
17+
Choice(
18+
L('\''),
19+
L('\n'),
20+
L('\r'))
21+
).Then(Any))
22+
.Between(L('\''), L('\''))
23+
.As("quoted-character");
24+
}

src/Ramstack.Parsing/Parser.ThenIgnore.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,24 @@ partial class Parser
99
/// <typeparam name="TResult">The type of the value produced by the first parser.</typeparam>
1010
/// <typeparam name="T">The type of the value produced by the second parser, which is ignored.</typeparam>
1111
/// <param name="parser">The initial parser whose result is returned.</param>
12-
/// <param name="before">The subsequent parser.</param>
12+
/// <param name="ignore">The subsequent parser, applied after the initial parser.</param>
1313
/// <returns>
1414
/// A parser that sequentially applies the current parser and a specified second parser,
1515
/// returning the result of the first parser with ignoring the result of the second.
1616
/// </returns>
17-
public static Parser<TResult> ThenIgnore<TResult, T>(this Parser<TResult> parser, Parser<T> before) =>
18-
new ThenIgnoreParser<TResult>(parser, before.Void());
17+
public static Parser<TResult> ThenIgnore<TResult, T>(this Parser<TResult> parser, Parser<T> ignore) =>
18+
new ThenIgnoreParser<TResult>(parser, ignore.Void());
1919

20-
#region Inner type: BeforeParser
20+
#region Inner type: ThenIgnoreParser
2121

2222
/// <summary>
2323
/// Represents a parser that sequentially applies an initial parser and a specified second parser,
2424
/// returning the result of the first parser with ignoring the result of the second.
2525
/// </summary>
2626
/// <typeparam name="T">The type of the value produced by the first parser.</typeparam>
2727
/// <param name="parser">The initial parser whose result is returned.</param>
28-
/// <param name="before">The subsequent parser, applied after the initial parser.</param>
29-
private sealed class ThenIgnoreParser<T>(Parser<T> parser, Parser<Unit> before) : Parser<T>
28+
/// <param name="ignore">The subsequent parser, applied after the initial parser.</param>
29+
private sealed class ThenIgnoreParser<T>(Parser<T> parser, Parser<Unit> ignore) : Parser<T>
3030
{
3131
/// <inheritdoc />
3232
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
3737
{
3838
var (index, length) = context.MatchedSegment;
3939

40-
if (before.TryParse(ref context, out _))
40+
if (ignore.TryParse(ref context, out _))
4141
{
4242
context.SetMatched(index, length);
4343
return true;
@@ -50,7 +50,7 @@ public override bool TryParse(ref ParseContext context, [NotNullWhen(true)] out
5050

5151
/// <inheritdoc />
5252
protected internal override Parser<Unit> ToVoidParser() =>
53-
new ThenIgnoreParser<Unit>(parser.Void(), before);
53+
new ThenIgnoreParser<Unit>(parser.Void(), ignore);
5454
}
5555

5656
#endregion
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
namespace Ramstack.Parsing;
2+
3+
partial class LiteralTests
4+
{
5+
[TestCase("'1'", '1')]
6+
[TestCase("'\\u0045'", '\u0045')]
7+
[TestCase("'\\r'", '\r')]
8+
[TestCase("'\\n'", '\n')]
9+
[TestCase("'\\t'", '\t')]
10+
public void QuotedCharacterTest(string input, char expected)
11+
{
12+
Assert.That(
13+
Literal.QuotedCharacter.Parse(input).Value,
14+
Is.EqualTo(expected));
15+
}
16+
17+
[TestCase("'1")]
18+
[TestCase("'\\uabcw'")]
19+
[TestCase("'\\u123q'")]
20+
[TestCase("'\\z'")]
21+
[TestCase("'\r'")]
22+
[TestCase("'\n'")]
23+
[TestCase("'\''")]
24+
[TestCase("'a")]
25+
[TestCase("'ab'")]
26+
public void QuotedCharacter_Error(string input)
27+
{
28+
var parser = Literal.QuotedCharacter;
29+
Assert.That(parser.Parse(input).Success, Is.False);
30+
}
31+
}

0 commit comments

Comments
 (0)