Skip to content

Commit 2905411

Browse files
authored
Merge pull request #93 from datalust/dev
2.3.0 Release
2 parents 181727a + 1d82a81 commit 2905411

27 files changed

+392
-207
lines changed

Superpower.sln.DotSettings

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,12 @@
11
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
2-
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=TypeParameters/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb"&gt;&lt;ExtraRule Prefix="" Suffix="" Style="AA_BB" /&gt;&lt;/Policy&gt;</s:String></wpf:ResourceDictionary>
2+
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=TypeParameters/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb"&gt;&lt;ExtraRule Prefix="" Suffix="" Style="AA_BB" /&gt;&lt;/Policy&gt;</s:String>
3+
<s:Boolean x:Key="/Default/UserDictionary/Words/=allocs/@EntryIndexedValue">True</s:Boolean>
4+
<s:Boolean x:Key="/Default/UserDictionary/Words/=errloc/@EntryIndexedValue">True</s:Boolean>
5+
<s:Boolean x:Key="/Default/UserDictionary/Words/=frac/@EntryIndexedValue">True</s:Boolean>
6+
<s:Boolean x:Key="/Default/UserDictionary/Words/=lparen/@EntryIndexedValue">True</s:Boolean>
7+
<s:Boolean x:Key="/Default/UserDictionary/Words/=Numerics/@EntryIndexedValue">True</s:Boolean>
8+
<s:Boolean x:Key="/Default/UserDictionary/Words/=opvalue/@EntryIndexedValue">True</s:Boolean>
9+
<s:Boolean x:Key="/Default/UserDictionary/Words/=rparen/@EntryIndexedValue">True</s:Boolean>
10+
<s:Boolean x:Key="/Default/UserDictionary/Words/=Sprache/@EntryIndexedValue">True</s:Boolean>
11+
<s:Boolean x:Key="/Default/UserDictionary/Words/=tokenized/@EntryIndexedValue">True</s:Boolean>
12+
<s:Boolean x:Key="/Default/UserDictionary/Words/=tokenizers/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

sample/JsonParser/Program.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ enum JsonToken
6262
// concept that groups `true`, `false`, and `null`, it's useful
6363
// for the tokenizer to be very permissive - it's more informative
6464
// to generate an error later at the parsing stage, e.g.
65-
// "unexpected identifier `flase`", instead of failing at the
65+
// "unexpected identifier `false`", instead of failing at the
6666
// tokenization stage where all we'd have is "unexpected `l`".
6767
Identifier,
6868
}
@@ -100,7 +100,6 @@ static class JsonTokenizer
100100
static TextParser<Unit> JsonStringToken { get; } =
101101
from open in Character.EqualTo('"')
102102
from content in Span.EqualTo("\\\"").Value(Unit.Value).Try()
103-
.Or(Span.EqualTo("\\\\").Value(Unit.Value).Try())
104103
.Or(Character.Except('"').Value(Unit.Value))
105104
.IgnoreMany()
106105
from close in Character.EqualTo('"')

src/Superpower/Combinators.cs

Lines changed: 140 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -395,19 +395,19 @@ public static TokenListParser<TKind, T[]> Many<TKind, T>(this TokenListParser<TK
395395
return input =>
396396
{
397397
var result = new List<T>();
398-
var @from = input;
398+
var from = input;
399399
var r = parser(input);
400400
while (r.HasValue)
401401
{
402-
if (@from == r.Remainder) // Broken parser, not a failed parsing.
403-
throw new ParseException($"Many() cannot be applied to zero-width parsers; value {r.Value} at position {r.Location.Position}.");
402+
if (from == r.Remainder) // Broken parser, not a failed parsing.
403+
throw new ParseException($"Many() cannot be applied to zero-width parsers; value {r.Value} at position {r.Location.Position}.", r.ErrorPosition);
404404

405405
result.Add(r.Value);
406-
@from = r.Remainder;
406+
from = r.Remainder;
407407
r = parser(r.Remainder);
408408
}
409409

410-
if (!r.Backtrack && r.IsPartial(@from))
410+
if (!r.Backtrack && r.IsPartial(from))
411411
return TokenListParserResult.CastEmpty<TKind, T, T[]>(r);
412412

413413
return TokenListParserResult.Value(result.ToArray(), input, from);
@@ -433,7 +433,7 @@ public static TextParser<T[]> Many<T>(this TextParser<T> parser)
433433
while (r.HasValue)
434434
{
435435
if (from == r.Remainder) // Broken parser, not a failed parsing.
436-
throw new ParseException($"Many() cannot be applied to zero-width parsers; value {r.Value} at position {r.Location.Position}.");
436+
throw new ParseException($"Many() cannot be applied to zero-width parsers; value {r.Value} at position {r.Location.Position}.", r.Location.Position);
437437

438438
result.Add(r.Value);
439439

@@ -467,7 +467,7 @@ public static TextParser<Unit> IgnoreMany<T>(this TextParser<T> parser)
467467
while (r.HasValue)
468468
{
469469
if (from == r.Remainder) // Broken parser, not a failed parsing.
470-
throw new ParseException($"IgnoreMany() cannot be applied to zero-width parsers; value {r.Value} at position {r.Location.Position}.");
470+
throw new ParseException($"IgnoreMany() cannot be applied to zero-width parsers; value {r.Value} at position {r.Location.Position}.", r.Location.Position);
471471

472472
from = r.Remainder;
473473
r = parser(r.Remainder);
@@ -499,6 +499,8 @@ public static TokenListParser<TKind, T[]> ManyDelimitedBy<TKind, T, U>(
499499
if (parser == null) throw new ArgumentNullException(nameof(parser));
500500
if (delimiter == null) throw new ArgumentNullException(nameof(delimiter));
501501

502+
// ReSharper disable once ConvertClosureToMethodGroup
503+
502504
if (end != null)
503505
return parser
504506
.AtLeastOnceDelimitedBy(delimiter)
@@ -655,7 +657,7 @@ public static TextParser<T> Named<T>(this TextParser<T> parser, string name)
655657
/// <param name="parser">The parser.</param>
656658
/// <param name="defaultValue">The default value</param>
657659
/// <returns>The resulting parser.</returns>
658-
public static TokenListParser<TKind, T> OptionalOrDefault<TKind, T>(this TokenListParser<TKind, T> parser, T defaultValue = default(T))
660+
public static TokenListParser<TKind, T> OptionalOrDefault<TKind, T>(this TokenListParser<TKind, T> parser, T defaultValue = default)
659661
{
660662
if (parser == null) throw new ArgumentNullException(nameof(parser));
661663

@@ -670,7 +672,7 @@ public static TextParser<T> Named<T>(this TextParser<T> parser, string name)
670672
/// <param name="parser">The parser.</param>
671673
/// <param name="defaultValue">The default value.</param>
672674
/// <returns>The resulting parser.</returns>
673-
public static TextParser<T> OptionalOrDefault<T>(this TextParser<T> parser, T defaultValue = default(T))
675+
public static TextParser<T> OptionalOrDefault<T>(this TextParser<T> parser, T defaultValue = default)
674676
{
675677
if (parser == null) throw new ArgumentNullException(nameof(parser));
676678

@@ -746,7 +748,16 @@ public static TokenListParser<TKind, U> Select<TKind, T, U>(this TokenListParser
746748
if (parser == null) throw new ArgumentNullException(nameof(parser));
747749
if (selector == null) throw new ArgumentNullException(nameof(selector));
748750

749-
return parser.Then(rt => Parse.Return<TKind, U>(selector(rt)));
751+
return input =>
752+
{
753+
var rt = parser(input);
754+
if (!rt.HasValue)
755+
return TokenListParserResult.CastEmpty<TKind, T, U>(rt);
756+
757+
var u = selector(rt.Value);
758+
759+
return TokenListParserResult.Value(u, input, rt.Remainder);
760+
};
750761
}
751762

752763
/// <summary>
@@ -762,7 +773,16 @@ public static TextParser<U> Select<T, U>(this TextParser<T> parser, Func<T, U> s
762773
if (parser == null) throw new ArgumentNullException(nameof(parser));
763774
if (selector == null) throw new ArgumentNullException(nameof(selector));
764775

765-
return parser.Then(rt => Parse.Return(selector(rt)));
776+
return input =>
777+
{
778+
var rt = parser(input);
779+
if (!rt.HasValue)
780+
return Result.CastEmpty<T, U>(rt);
781+
782+
var u = selector(rt.Value);
783+
784+
return Result.Value(u, input, rt.Remainder);
785+
};
766786
}
767787

768788
/// <summary>
@@ -778,7 +798,7 @@ public static TokenListParser<TKind, U> Cast<TKind, T, U>(this TokenListParser<T
778798
{
779799
if (parser == null) throw new ArgumentNullException(nameof(parser));
780800

781-
return parser.Then(rt => Parse.Return<TKind, U>((U)rt));
801+
return parser.Select(rt => (U)rt);
782802
}
783803

784804
/// <summary>
@@ -793,7 +813,7 @@ public static TextParser<U> Cast<T, U>(this TextParser<T> parser)
793813
{
794814
if (parser == null) throw new ArgumentNullException(nameof(parser));
795815

796-
return parser.Then(rt => Parse.Return((U)rt));
816+
return parser.Select(rt => (U)rt);
797817
}
798818

799819
/// <summary>
@@ -1023,6 +1043,113 @@ public static TextParser<T> Where<T>(this TextParser<T> parser, Func<T, bool> pr
10231043

10241044
return Result.Empty<T>(input, "unsatisfied condition");
10251045
};
1046+
}
1047+
1048+
/// <summary>
1049+
/// Parse a sequence of operands connected by left-associative operators.
1050+
/// </summary>
1051+
/// <typeparam name="TResult">The type of the leftmost operand and of the ultimate result.</typeparam>
1052+
/// <typeparam name="TOperator">The type of the operator.</typeparam>
1053+
/// <typeparam name="TOperand">The type of subsequent operands.</typeparam>
1054+
/// <param name="parser">The parser for the leftmost operand.</param>
1055+
/// <param name="operator">A parser matching operators.</param>
1056+
/// <param name="operand">A parser matching operands.</param>
1057+
/// <param name="apply">A function combining the operator, left operand, and right operand, into the result.</param>
1058+
/// <returns>The result of calling <paramref name="apply"/> successively on pairs of operands.</returns>
1059+
public static TextParser<TResult> Chain<TResult, TOperator, TOperand>(
1060+
this TextParser<TResult> parser,
1061+
TextParser<TOperator> @operator,
1062+
TextParser<TOperand> operand,
1063+
Func<TOperator, TResult, TOperand, TResult> apply)
1064+
{
1065+
if (parser == null) throw new ArgumentNullException(nameof(parser));
1066+
if (@operator == null) throw new ArgumentNullException(nameof(@operator));
1067+
if (operand == null) throw new ArgumentNullException(nameof(operand));
1068+
if (apply == null) throw new ArgumentNullException(nameof(apply));
1069+
1070+
return input =>
1071+
{
1072+
var parseResult = parser(input);
1073+
if (!parseResult.HasValue)
1074+
return parseResult;
1075+
1076+
var result = parseResult.Value;
1077+
var operandRemainder = parseResult.Remainder;
1078+
1079+
var operatorResult = @operator(operandRemainder);
1080+
while (operatorResult.HasValue || operatorResult.IsPartial(operandRemainder))
1081+
{
1082+
// If operator read any input, but failed to read complete input, we return error
1083+
if (!operatorResult.HasValue)
1084+
return Result.CastEmpty<TOperator, TResult>(operatorResult);
1085+
1086+
var operandResult = operand(operatorResult.Remainder);
1087+
operandRemainder = operandResult.Remainder;
1088+
1089+
if (!operandResult.HasValue)
1090+
return Result.CastEmpty<TOperand, TResult>(operandResult);
1091+
1092+
result = apply(operatorResult.Value, result, operandResult.Value);
1093+
1094+
operatorResult = @operator(operandRemainder);
1095+
}
1096+
1097+
return Result.Value(result, input, operandRemainder);
1098+
};
1099+
}
1100+
1101+
/// <summary>
1102+
/// Parse a sequence of operands connected by left-associative operators.
1103+
/// </summary>
1104+
/// <typeparam name="TKind">The kind of the tokens being parsed.</typeparam>
1105+
/// <typeparam name="TResult">The type of the leftmost operand and of the ultimate result.</typeparam>
1106+
/// <typeparam name="TOperator">The type of the operator.</typeparam>
1107+
/// <typeparam name="TOperand">The type of subsequent operands.</typeparam>
1108+
/// <param name="parser">The parser for the leftmost operand.</param>
1109+
/// <param name="operator">A parser matching operators.</param>
1110+
/// <param name="operand">A parser matching operands.</param>
1111+
/// <param name="apply">A function combining the operator, left operand, and right operand, into the result.</param>
1112+
/// <returns>The result of calling <paramref name="apply"/> successively on pairs of operands.</returns>
1113+
public static TokenListParser<TKind, TResult> Chain<TKind, TResult, TOperator, TOperand>(
1114+
this TokenListParser<TKind, TResult> parser,
1115+
TokenListParser<TKind, TOperator> @operator,
1116+
TokenListParser<TKind, TOperand> operand,
1117+
Func<TOperator, TResult, TOperand, TResult> apply)
1118+
{
1119+
if (parser == null) throw new ArgumentNullException(nameof(parser));
1120+
if (@operator == null) throw new ArgumentNullException(nameof(@operator));
1121+
if (operand == null) throw new ArgumentNullException(nameof(operand));
1122+
if (apply == null) throw new ArgumentNullException(nameof(apply));
1123+
1124+
return input =>
1125+
{
1126+
var parseResult = parser(input);
1127+
if (!parseResult.HasValue )
1128+
return parseResult;
1129+
1130+
var result = parseResult.Value;
1131+
var operandRemainder = parseResult.Remainder;
1132+
1133+
var operatorResult = @operator(operandRemainder);
1134+
while (operatorResult.HasValue || operatorResult.IsPartial(operandRemainder))
1135+
{
1136+
// If operator read any input, but failed to read complete input, we return error
1137+
if (!operatorResult.HasValue)
1138+
return TokenListParserResult.CastEmpty<TKind, TOperator, TResult>(operatorResult);
1139+
1140+
var operandResult = operand(operatorResult.Remainder);
1141+
operandRemainder = operandResult.Remainder;
1142+
1143+
if (!operandResult.HasValue)
1144+
return TokenListParserResult.CastEmpty<TKind, TOperand, TResult>(operandResult);
1145+
1146+
result = apply(operatorResult.Value, result, operandResult.Value);
1147+
1148+
operatorResult = @operator(operandRemainder);
1149+
}
1150+
1151+
return TokenListParserResult.Value(result, input, operandRemainder);
1152+
};
10261153
}
10271154
}
10281155
}

src/Superpower/Model/Position.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public Position(int absolute, int line, int column)
6262
/// <summary>
6363
/// A position with no value.
6464
/// </summary>
65-
public static Position Empty { get; } = default(Position);
65+
public static Position Empty { get; } = default;
6666

6767
/// <summary>
6868
/// True if the position has a value.

src/Superpower/Model/Result`1.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ internal Result(TextSpan location, TextSpan remainder, string errorMessage, stri
8888
{
8989
Location = location;
9090
Remainder = remainder;
91-
_value = default(T);
91+
_value = default;
9292
HasValue = false;
9393
Expectations = expectations;
9494
ErrorMessage = errorMessage;
@@ -98,7 +98,7 @@ internal Result(TextSpan location, TextSpan remainder, string errorMessage, stri
9898
internal Result(TextSpan remainder, string errorMessage, string[] expectations, bool backtrack)
9999
{
100100
Location = Remainder = remainder;
101-
_value = default(T);
101+
_value = default;
102102
HasValue = false;
103103
Expectations = expectations;
104104
ErrorMessage = errorMessage;

src/Superpower/Model/TextSpan.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public TextSpan(string source, Position position, int length)
6969
/// <summary>
7070
/// A span with no value.
7171
/// </summary>
72-
public static TextSpan None { get; } = default(TextSpan);
72+
public static TextSpan None { get; } = default;
7373

7474
/// <summary>
7575
/// A span corresponding to the empty string.

src/Superpower/Model/TokenListParserResult`2.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ internal TokenListParserResult(TokenList<TKind> location, TokenList<TKind> remai
111111
{
112112
Location = location;
113113
Remainder = remainder;
114-
_value = default(T);
114+
_value = default;
115115
HasValue = false;
116116
SubTokenErrorPosition = errorPosition;
117117
ErrorMessage = errorMessage;
@@ -122,7 +122,7 @@ internal TokenListParserResult(TokenList<TKind> location, TokenList<TKind> remai
122122
internal TokenListParserResult(TokenList<TKind> remainder, Position errorPosition, string errorMessage, string[] expectations, bool backtrack)
123123
{
124124
Location = Remainder = remainder;
125-
_value = default(T);
125+
_value = default;
126126
HasValue = false;
127127
SubTokenErrorPosition = errorPosition;
128128
ErrorMessage = errorMessage;

src/Superpower/Model/TokenList`1.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public TokenList(Token<TKind>[] tokens)
5555
/// <summary>
5656
/// A token list with no value.
5757
/// </summary>
58-
public static TokenList<TKind> Empty { get; } = default(TokenList<TKind>);
58+
public static TokenList<TKind> Empty { get; } = default;
5959

6060
/// <summary>
6161
/// True if the token list contains no tokens.

src/Superpower/Model/Token`1.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public Token(TKind kind, TextSpan span)
6060
/// <summary>
6161
/// A token with no value.
6262
/// </summary>
63-
public static Token<TKind> Empty { get; } = default(Token<TKind>);
63+
public static Token<TKind> Empty { get; } = default;
6464

6565
/// <inheritdoc/>
6666
public override string ToString()

src/Superpower/Model/Unit.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@ public struct Unit
2222
/// <summary>
2323
/// The singleton value of the struct, with no value.
2424
/// </summary>
25-
public static Unit Value { get; } = default(Unit);
25+
public static Unit Value { get; } = default;
2626
}
2727
}

0 commit comments

Comments
 (0)