Skip to content

Commit

Permalink
Use best strtegy for SkipwhiteSpace
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastienros committed Nov 23, 2024
1 parent da7db49 commit ccda146
Show file tree
Hide file tree
Showing 18 changed files with 556 additions and 108 deletions.
37 changes: 37 additions & 0 deletions src/Parlot/Character.Mask.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;
#if !NET8_0_OR_GREATER
using System.Runtime.CompilerServices;
#endif

namespace Parlot;

[Flags]
internal enum CharacterMask : byte
{
None = 0,
IdentifierStart = 1,
IdentifierPart = 2,
WhiteSpace = 4,
WhiteSpaceOrNewLine = 8
}

#if !NET8_0_OR_GREATER
public static partial class Character
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsDecimalDigit(char ch) => IsInRange(ch, '0', '9');

public static bool IsIdentifierStart(char ch)
{
return (_characterData[ch] & (byte)CharacterMask.IdentifierStart) != 0;
}

public static bool IsIdentifierPart(char ch)
{
return (_characterData[ch] & (byte)CharacterMask.IdentifierPart) != 0;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsHexDigit(char ch) => HexConverter.IsHexChar(ch);
}
#endif
35 changes: 35 additions & 0 deletions src/Parlot/Character.SearchValues.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#if NET8_0_OR_GREATER
using System.Buffers;
using System.Runtime.CompilerServices;

namespace Parlot;

public static partial class Character
{
internal const string DecimalDigits = "0123456789";
internal const string Alpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
internal const string AlphaNumeric = Alpha + DecimalDigits;
internal const string DefaultIdentifierStart = "$_" + Alpha;
internal const string DefaultIdentifierPart = "$_" + AlphaNumeric;
internal const string HexDigits = "0123456789abcdefABCDEF";
internal const string NewLines = "\n\r\v";

internal static readonly SearchValues<char> _decimalDigits = SearchValues.Create(DecimalDigits);
internal static readonly SearchValues<char> _hexDigits = SearchValues.Create(HexDigits);
internal static readonly SearchValues<char> _identifierStart = SearchValues.Create(DefaultIdentifierStart);
internal static readonly SearchValues<char> _identifierPart = SearchValues.Create(DefaultIdentifierPart);
internal static readonly SearchValues<char> _newLines = SearchValues.Create(NewLines);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsDecimalDigit(char ch) => _decimalDigits.Contains(ch);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsIdentifierStart(char ch) => _identifierStart.Contains(ch);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsIdentifierPart(char ch) => _identifierPart.Contains(ch);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsHexDigit(char ch) => _hexDigits.Contains(ch);
}
#endif
50 changes: 13 additions & 37 deletions src/Parlot/Character.cs
Original file line number Diff line number Diff line change
@@ -1,51 +1,15 @@
using System;
using System;
using System.Buffers;
using System.Runtime.CompilerServices;

namespace Parlot;

[Flags]
internal enum CharacterMask : byte
{
None = 0,
IdentifierStart = 1,
IdentifierPart = 2,
WhiteSpace = 4,
WhiteSpaceOrNewLine = 8
}

public static partial class Character
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsDecimalDigit(char ch) => IsInRange(ch, '0', '9');

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsInRange(char ch, char min, char max) => ch - (uint)min <= max - (uint)min;

public static bool IsHexDigit(char ch) => HexConverter.IsHexChar(ch);

public static bool IsIdentifierStart(char ch)
{
return (_characterData[ch] & (byte)CharacterMask.IdentifierStart) != 0;
}

public static bool IsIdentifierPart(char ch)
{
return (_characterData[ch] & (byte)CharacterMask.IdentifierPart) != 0;
}

public static bool IsWhiteSpace(char ch)
{
return (_characterData[ch] & (byte)CharacterMask.WhiteSpace) != 0;
}

public static bool IsWhiteSpaceOrNewLine(char ch)
{
return (_characterData[ch] & (byte)CharacterMask.WhiteSpaceOrNewLine) != 0;
}

public static bool IsNewLine(char ch) => ch is '\n' or '\r' or '\v';

public static char ScanHexEscape(string text, int index, out int length)
{
return ScanHexEscape(text.AsSpan(index), out length);
Expand Down Expand Up @@ -156,4 +120,16 @@ public static TextSpan DecodeString(TextSpan span)
}

private static int HexValue(char ch) => HexConverter.FromChar(ch);

public static bool IsWhiteSpace(char ch)
{
return (_characterData[ch] & (byte)CharacterMask.WhiteSpace) != 0;
}

public static bool IsWhiteSpaceOrNewLine(char ch)
{
return (_characterData[ch] & (byte)CharacterMask.WhiteSpaceOrNewLine) != 0;
}

public static bool IsNewLine(char ch) => ch is '\n' or '\r' or '\v';
}
6 changes: 3 additions & 3 deletions src/Parlot/Cursor.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Runtime.CompilerServices;

namespace Parlot;
Expand Down Expand Up @@ -67,7 +67,7 @@ public void Advance()
}

/// <summary>
/// Advances the cursor.
/// Advances the cursor and tracks its current location (line and column).
/// </summary>
public void Advance(int count)
{
Expand Down Expand Up @@ -115,7 +115,7 @@ public void Advance(int count)
}

/// <summary>
/// Advances the cursor with the knowledge there are no new lines.
/// Advances the cursor and tracks its current location (line and column) with the knowledge there are no new lines (\r or \n).
/// </summary>
public void AdvanceNoNewLines(int offset)
{
Expand Down
46 changes: 46 additions & 0 deletions src/Parlot/Fluent/IdentifierLiteral.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#if NET8_0_OR_GREATER
using System;
using System.Buffers;

namespace Parlot.Fluent;

internal sealed class IdentifierLiteral : Parser<TextSpan>
{
private readonly SearchValues<char> _startSearchValues;
private readonly SearchValues<char> _partSearchValues;

public IdentifierLiteral(SearchValues<char> startSearchValues, SearchValues<char> partSearchValues)
{
_startSearchValues = startSearchValues;
_partSearchValues = partSearchValues;

// Since we assume these can't container new lines, we can check this here.
if (partSearchValues.Contains('\n') || startSearchValues.Contains('\r'))
{
throw new InvalidOperationException("Identifiers cannot contain new lines.");
}
}

public override bool Parse(ParseContext context, ref ParseResult<TextSpan> result)
{
context.EnterParser(this);

var span = context.Scanner.Cursor.Span;

if (span.Length == 0 || !_startSearchValues.Contains(span[0]))
{
return false;
}

var index = span.Slice(1).IndexOfAnyExcept(_partSearchValues);

// If index == -1 the whole input is a match
var size = index == -1 ? span.Length : index + 1;

var start = context.Scanner.Cursor.Position.Offset;
context.Scanner.Cursor.AdvanceNoNewLines(size);
result.Set(start, start + size, new TextSpan(context.Scanner.Buffer, start, size));
return true;
}
}
#endif
2 changes: 0 additions & 2 deletions src/Parlot/Fluent/NumberLiteral.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,8 @@ public CompilationResult Compile(CompilationContext context)
{
var result = context.CreateCompilationResult<T>();

// var start = context.Scanner.Cursor.Offset;
// var reset = context.Scanner.Cursor.Position;

var start = context.DeclareOffsetVariable(result);
var reset = context.DeclarePositionVariable(result);

var numberStyles = result.DeclareVariable<NumberStyles>($"numberStyles{context.NextNumber}", Expression.Constant(_numberStyles));
Expand Down
Loading

0 comments on commit ccda146

Please sign in to comment.