public static Result <ImmutableArray <ColumnSort> > ParseSortLevel(string annotationValue) { var sortLevel = ImmutableArray.CreateBuilder <ColumnSort>(); var context = new LexingContext(new Lexer(annotationValue)); var usedFieldNames = new HashSet <string>(StringComparer.OrdinalIgnoreCase); if (!context.TryLex(SyntaxKind.Identifier, SyntaxKind.EndOfInput)) { return(Result.Error(context.ErrorMessage !)); } while (context.CurrentToken.Kind != SyntaxKind.EndOfInput) { var fieldName = context.CurrentToken.Value !; var directionKeyword = (SyntaxKind?)null; if (!context.TryLex(SyntaxKind.AscKeyword, SyntaxKind.DescKeyword, SyntaxKind.CommaToken, SyntaxKind.EndOfInput)) { return(Result.Error(context.ErrorMessage !)); } switch (context.CurrentToken.Kind) { case SyntaxKind.AscKeyword: case SyntaxKind.DescKeyword: directionKeyword = context.CurrentToken.Kind; if (!context.TryLex(SyntaxKind.CommaToken, SyntaxKind.EndOfInput)) { return(Result.Error(context.ErrorMessage !)); } break; } if (!usedFieldNames.Add(fieldName)) { return(Result.Error($"The field name ‘{fieldName}’ appears more than once.")); } sortLevel.Add(new ColumnSort( fieldName, ascendingOrder: (directionKeyword ?? SyntaxKind.AscKeyword) == SyntaxKind.AscKeyword)); if (context.CurrentToken.Kind == SyntaxKind.CommaToken) { if (!context.TryLex(SyntaxKind.Identifier)) { return(Result.Error(context.ErrorMessage !)); } } } return(Result.Success(sortLevel.ToImmutable())); }
public ILexicalToken Produce(LexingContext context) { var start = context.Position; var input = context.Input.Span; var length = input.Length; var c = input[start]; if (!c.IsInlineWhiteSpaceOrCaretControl()) { return(null); } var pos = start; while (true) { if (pos == length) { context.Position += pos - start; return(null); // todo: wrong? in a case of string of spaces, what the result would be? } c = input[pos]; switch (c) { case '\t': case ' ': case '\v': case '\f': case '\r': case '\n': pos++; break; default: var delta = pos - start; context.Position += delta; return(EmptyToken.Instance); } } }
public ILexicalToken Produce(LexingContext context) { var start = context.Position; var input = context.Input.Span[start..];
public ILexicalToken Produce(LexingContext context) { // todo checks. consider LexicalTokenProducerBase + ProduceImpl var start = context.Position; var input = context.Input.Span[start..];
public ILexicalToken Produce(LexingContext context) { var text = context.Input.Span; var length = text.Length; var c = text[context.Position]; if (c == '"') { var start = context.Position; var pos = start + 1; // skip '"' var sb = new StringBuilder(); while (true) { if (pos == length) { throw Helper.CreateException(ParsingErrorTag.UnclosedString, pos); } c = text[pos]; if (c.IsCaretControl()) { throw Helper.CreateException(ParsingErrorTag.NewLineInString, pos); } if (c == '\\') { if (pos + 1 == length) { throw Helper.CreateException(ParsingErrorTag.UnclosedString, length); } var nextChar = text[pos + 1]; if (nextChar == 'u') { var remaining = length - (pos + 1); if (remaining < 5) { throw Helper.CreateException(ParsingErrorTag.BadEscape, pos); } var hexNumString = text.Slice(pos + 2, 4); var codeParsed = int.TryParse( hexNumString, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var code); if (!codeParsed) { throw Helper.CreateException(ParsingErrorTag.BadEscape, pos); } var unescapedChar = (char)code; sb.Append(unescapedChar); pos += 6; continue; } else { var replacement = GetReplacement(nextChar); if (replacement.HasValue) { sb.Append(replacement); pos += 2; continue; } else { throw Helper.CreateException(ParsingErrorTag.BadEscape, pos); } } } pos++; if (c == '"') { break; } sb.Append(c); } var delta = pos - start; var str = sb.ToString(); var token = new StringToken( start, delta, str, "C"); context.Position += delta; return(token); } return(null); }