Skip to content

Commit

Permalink
Merge pull request #79 from datalust/dev
Browse files Browse the repository at this point in the history
2.2.0 Release
  • Loading branch information
nblumhardt committed Jan 15, 2019
2 parents 585dd6a + c8eeff8 commit 181727a
Show file tree
Hide file tree
Showing 24 changed files with 298 additions and 57 deletions.
47 changes: 47 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "IntCalc",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/sample/IntCalc/bin/Debug/netcoreapp2.0/IntCalc.dll",
"args": [ "IntCalc" ],
"cwd": "${workspaceFolder}/sample/IntCalc",
"console": "integratedTerminal",
"stopAtEntry": false,
"internalConsoleOptions": "openOnSessionStart"
},
{
"name": "JsonParser",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/sample/JsonParser/bin/Debug/netcoreapp2.0/JsonParser.dll",
"args": [ "IntCalc" ],
"cwd": "${workspaceFolder}/sample/JsonParser",
"console": "integratedTerminal",
"stopAtEntry": false,
"internalConsoleOptions": "openOnSessionStart"
},
{
"name": "DateTimeTextParser",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/sample/DateTimeTextParser/bin/Debug/netcoreapp2.0/DateTimeParser.dll",
"args": [ "IntCalc" ],
"cwd": "${workspaceFolder}/sample/DateTimeTextParser",
"console": "integratedTerminal",
"stopAtEntry": false,
"internalConsoleOptions": "openOnSessionStart"
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"processId": "${command:pickProcess}"
}
]
}
34 changes: 34 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"group": {
"kind": "build",
"isDefault": true
},
"args": [
"build",
"/p:GenerateFullPaths=true"
],
"problemMatcher": "$msCompile"
},
{
"label": "test",
"command": "dotnet",
"type": "process",
"group": {
"kind": "test",
"isDefault": true
},
"args": [
"test",
"${workspaceFolder}/test/Superpower.Tests/Superpower.Tests.csproj",
"/p:GenerateFullPaths=true"
],
"problemMatcher": "$msCompile"
}
]
}
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ Superpower is introduced, with a worked example, in [this blog post](https://nbl
* [_DateTimeTextParser_](https://github.com/datalust/superpower/tree/dev/sample/DateTimeTextParser) shows how Superpower's text parsers work, parsing ISO-8601 date-times
* [_IntCalc_](https://github.com/datalust/superpower/tree/dev/sample/IntCalc) is a simple arithmetic expresion parser (`1 + 2 * 3`) included in the repository, demonstrating how Superpower token parsing works
* [_Plotty_](https://github.com/SuperJMN/Plotty) implements an instruction set for a RISC virtual machine
* [_tcalc_](https://github.com/nblumhardt/tcalc) is an example expression language that computes durations (`1d / 12m`)
**Real-world** projects built with Superpower:

Expand Down
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ artifacts:
deploy:
- provider: NuGet
api_key:
secure: 2APsxl7cOn94Y5lvJ0LshnVGefMpKu/JUG6IiM6BK9UWq1bN0Zv4X4OBXzkMPFm0
secure: Xi+qouQ6+cOJ85PMOQKEGy+MC1EKyYJCoF2YfuE9Rcj6lvNtm08TIZllTJCqId+M
skip_symbols: true
on:
branch: /^(master|dev)$/
Expand Down
5 changes: 3 additions & 2 deletions sample/IntCalc/ArithmeticExpressionTokenizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@ protected override IEnumerable<Result<ArithmeticExpressionToken>> Tokenize(TextS
{
ArithmeticExpressionToken charToken;

if (char.IsDigit(next.Value))
var ch = next.Value;
if (ch >= '0' && ch <= '9')
{
var integer = Numerics.Integer(next.Location);
next = integer.Remainder.ConsumeChar();
yield return Result.Value(ArithmeticExpressionToken.Number, integer.Location, integer.Remainder);
}
else if (_operators.TryGetValue(next.Value, out charToken))
else if (_operators.TryGetValue(ch, out charToken))
{
yield return Result.Value(charToken, next.Location, next.Remainder);
next = next.Remainder.ConsumeChar();
Expand Down
7 changes: 6 additions & 1 deletion sample/IntCalc/IntCalc.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup Condition=" '$(OS)' != 'Windows_NT' ">
<TargetFramework>netcoreapp1.0</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition=" '$(OS)' == 'Windows_NT' ">
<TargetFrameworks>net46;netcoreapp2.0</TargetFrameworks>
</PropertyGroup>

<PropertyGroup>
<TargetFrameworks>net46;netcoreapp1.0</TargetFrameworks>
<AssemblyName>IntCalc</AssemblyName>
<OutputType>Exe</OutputType>
<PackageId>IntCalc</PackageId>
Expand Down
6 changes: 3 additions & 3 deletions src/Superpower/Combinators.cs
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ public static TextParser<T[]> Repeat<T>(this TextParser<T> parser, int count)
if (!r.Backtrack && r.IsPartial(@from))
return TokenListParserResult.CastEmpty<TKind, T, T[]>(r);
return TokenListParserResult.Value(result.ToArray(), input, r.Remainder);
return TokenListParserResult.Value(result.ToArray(), input, from);
};
}

Expand Down Expand Up @@ -444,7 +444,7 @@ public static TextParser<T[]> Many<T>(this TextParser<T> parser)
if (!r.Backtrack && r.IsPartial(from))
return Result.CastEmpty<T, T[]>(r);
return Result.Value(result.ToArray(), input, r.Remainder);
return Result.Value(result.ToArray(), input, from);
};
}

Expand Down Expand Up @@ -476,7 +476,7 @@ public static TextParser<Unit> IgnoreMany<T>(this TextParser<T> parser)
if (!r.Backtrack && r.IsPartial(from))
return Result.CastEmpty<T, Unit>(r);
return Result.Value(Unit.Value, input, r.Remainder);
return Result.Value(Unit.Value, input, from);
};
}

Expand Down
74 changes: 62 additions & 12 deletions src/Superpower/Display/Presentation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,26 +69,76 @@ public static string FormatAppearance<TKind>(TKind kind, string value)

return $"{FormatKind(kind)} {clipped}";
}

public static string FormatLiteral(char literal)
{
switch (literal)
{
case '\r':
return "carriage return";
case '\n':
return "line feed";
case '\t':
return "tab";
case '\0':
return "NUL";
default:
return "`" + literal + "`";
//Unicode Category: Space Separators
case '\x00A0': return "U+00A0 no-break space";
case '\x1680': return "U+1680 ogham space mark";
case '\x2000': return "U+2000 en quad";
case '\x2001': return "U+2001 em quad";
case '\x2002': return "U+2002 en space";
case '\x2003': return "U+2003 em space";
case '\x2004': return "U+2004 three-per-em space";
case '\x2005': return "U+2005 four-per-em space";
case '\x2006': return "U+2006 six-per-em space";
case '\x2007': return "U+2007 figure space";
case '\x2008': return "U+2008 punctuation space";
case '\x2009': return "U+2009 thin space";
case '\x200A': return "U+200A hair space";
case '\x202F': return "U+202F narrow no-break space";
case '\x205F': return "U+205F medium mathematical space";
case '\x3000': return "U+3000 ideographic space";

//Line Separator
case '\x2028': return "U+2028 line separator";

//Paragraph Separator
case '\x2029': return "U+2029 paragraph separator";

//Unicode C0 Control Codes (ASCII equivalent)
case '\x0000': return "NUL"; //\0
case '\x0001': return "U+0001 start of heading";
case '\x0002': return "U+0002 start of text";
case '\x0003': return "U+0003 end of text";
case '\x0004': return "U+0004 end of transmission";
case '\x0005': return "U+0005 enquiry";
case '\x0006': return "U+0006 acknowledge";
case '\x0007': return "U+0007 bell";
case '\x0008': return "U+0008 backspace";
case '\x0009': return "tab"; //\t
case '\x000A': return "line feed"; //\n
case '\x000B': return "U+000B vertical tab";
case '\x000C': return "U+000C form feed";
case '\x000D': return "carriage return"; //\r
case '\x000E': return "U+000E shift in";
case '\x000F': return "U+000F shift out";
case '\x0010': return "U+0010 data link escape";
case '\x0011': return "U+0011 device ctrl 1";
case '\x0012': return "U+0012 device ctrl 2";
case '\x0013': return "U+0013 device ctrl 3";
case '\x0014': return "U+0014 device ctrl 4";
case '\x0015': return "U+0015 not acknowledge";
case '\x0016': return "U+0016 synchronous idle";
case '\x0017': return "U+0017 end transmission block";
case '\x0018': return "U+0018 cancel";
case '\x0019': return "U+0019 end of medium";
case '\x0020': return "space";
case '\x001A': return "U+001A substitute";
case '\x001B': return "U+001B escape";
case '\x001C': return "U+001C file separator";
case '\x001D': return "U+001D group separator";
case '\x001E': return "U+001E record separator";
case '\x001F': return "U+001F unit separator";
case '\x007F': return "U+007F delete";

default: return "`" + literal + "`";
}
}

public static string FormatLiteral(string literal)
{
{
return "`" + literal + "`";
}
}
Expand Down
11 changes: 3 additions & 8 deletions src/Superpower/Model/Result.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.

using Superpower.Util;

namespace Superpower.Model
{
/// <summary>
Expand Down Expand Up @@ -95,14 +97,7 @@ public static Result<T> CombineEmpty<T>(Result<T> first, Result<T> second)
if (expectations == null)
expectations = second.Expectations;
else if (second.Expectations != null)
{
expectations = new string[first.Expectations.Length + second.Expectations.Length];
var i = 0;
for (; i < first.Expectations.Length; ++i)
expectations[i] = first.Expectations[i];
for (var j = 0; j < second.Expectations.Length; ++i, ++j)
expectations[i] = second.Expectations[j];
}
expectations = ArrayEnumerable.Concat(first.Expectations, second.Expectations);

return new Result<T>(second.Remainder, second.ErrorMessage, expectations, second.Backtrack);
}
Expand Down
4 changes: 2 additions & 2 deletions src/Superpower/Model/Result`1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public T Value
get
{
if (!HasValue)
throw new InvalidOperationException("Result has no value.");
throw new InvalidOperationException($"{nameof(Result)} has no value.");
return _value;
}
}
Expand Down Expand Up @@ -141,7 +141,7 @@ public string FormatErrorMessageFragment()
else
{
var next = Location.ConsumeChar().Value;
message = $"unexpected `{next}`";
message = $"unexpected {Display.Presentation.FormatLiteral(next)}";
}

if (Expectations != null)
Expand Down
9 changes: 6 additions & 3 deletions src/Superpower/Model/TextSpan.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,16 @@ public override int GetHashCode()
}

/// <summary>
/// Compare a string span with another using source identity semantics - same source, same position, same length.
/// Compare a string span with another using source identity
/// semantics - same source, same position, same length.
/// </summary>
/// <param name="other">The other span.</param>
/// <returns>True if the spans are the same.</returns>
public bool Equals(TextSpan other)
{
return string.Equals(Source, other.Source) && Position.Absolute == other.Position.Absolute;
return ReferenceEquals(Source, other.Source) &&
Position.Absolute == other.Position.Absolute &&
Length == other.Length;
}

/// <summary>
Expand Down Expand Up @@ -170,7 +173,7 @@ public TextSpan Until(TextSpan next)
next.EnsureHasValue();
if (next.Source != Source) throw new ArgumentException("The spans are on different source strings.", nameof(next));
#endif
var charCount = Length - next.Length;
var charCount = next.Position.Absolute - Position.Absolute;
return First(charCount);
}

Expand Down
2 changes: 1 addition & 1 deletion src/Superpower/Model/TokenListParserResult`2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public T Value
get
{
if (!HasValue)
throw new InvalidOperationException("TokenResult has no value.");
throw new InvalidOperationException($"{nameof(TokenListParserResult)} has no value.");
return _value;
}
}
Expand Down
Loading

0 comments on commit 181727a

Please sign in to comment.