Skip to content

Commit

Permalink
Add support for capturing comments in JSON.
Browse files Browse the repository at this point in the history
  • Loading branch information
tacosontitan committed Nov 26, 2024
1 parent 33c545f commit 30a4181
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 0 deletions.
33 changes: 33 additions & 0 deletions src/Pasper.Json/Parsing/JsonLexer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ private bool TryGetNextToken([NotNullWhen(true)] out IToken? token)
if (TryGetStringToken(out token))
return true;

if (TryGetSingleLineCommentToken(out token))
return true;

throw new UnexpectedTokenException(_lineNumber, _columnNumber, currentCharacter.ToString());
}

Expand Down Expand Up @@ -129,4 +132,34 @@ private bool TryGetStringToken([NotNullWhen(true)] out IToken? token)
_currentIndex = endIndex + 1;
return true;
}

private bool TryGetSingleLineCommentToken([NotNullWhen(true)] out IToken? token)
{
if (json[_currentIndex] != '/')
{
token = null;
return false;
}

var nextToken = json[_currentIndex + 1];
if (nextToken is not '/')
{
token = null;
return false;
}

// Single line comments can technically be placed on the final line of the specified
// input. The lexer accounts for this by assuming that if no line breaks are detected
// after the start of a comment, that the comment goes to the end of the input.
var startIndex = _currentIndex + 2;
var endIndex = json.IndexOf('\n', startIndex);
if (endIndex == -1)
endIndex = json.Length;

var value = json.Substring(startIndex, endIndex - startIndex);
token = new CommentToken(value.Trim());
_currentIndex = endIndex + 1;
_columnNumber += value.Length + 2;
return true;
}
}
13 changes: 13 additions & 0 deletions test/Pasper.Json.Tests/Parsing/JsonLexer/TryGetNextToken.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,17 @@ public void TryGetNextToken_EndObjectDetected_ReturnsTrue()
Assert.NotNull(lexer.Current);
Assert.IsType<EndObjectToken>(lexer.Current);
}

[Fact]
public void TryGetNextToken_CommentDetected_ReturnsTrue()
{
const string comment = "this is a comment";
const string testJson = $"// {comment}";
var lexer = new JsonLexer(testJson);
var tokenAvailable = lexer.MoveNext();
Assert.True(tokenAvailable);
Assert.NotNull(lexer.Current);
Assert.IsType<CommentToken>(lexer.Current);
Assert.Equal(comment, lexer.Current.Value);
}
}

0 comments on commit 30a4181

Please sign in to comment.