diff --git a/Lexer.Tests/MLexerShould.cs b/Lexer.Tests/MLexerShould.cs index 0b1b518..cae3b18 100644 --- a/Lexer.Tests/MLexerShould.cs +++ b/Lexer.Tests/MLexerShould.cs @@ -234,5 +234,22 @@ namespace Lexer.Tests Assert.AreEqual(2, tokens.Count); Assert.AreEqual(TokenKind.NumberLiteral, tokens[0].Kind); } + + [TestCase("%{\nabc\n%}", true)] + [TestCase("%{ a\nabc\n%}", false)] + [TestCase("if %{\nabc\n%}", false)] + public void ParseMultilineComments(string text, bool isMultiline) + { + var sut = CreateLexer(text); + var tokens = sut.ParseAll(); + if (isMultiline) + { + Assert.AreEqual(1, tokens.Count); + } + else + { + Assert.Less(1, tokens.Count); + } + } } } \ No newline at end of file diff --git a/Lexer/MLexer.cs b/Lexer/MLexer.cs index 34e0217..904d684 100644 --- a/Lexer/MLexer.cs +++ b/Lexer/MLexer.cs @@ -27,6 +27,10 @@ namespace Lexer private Trivia LexComment() { + if (TokensSinceNewLine == 0 && Window.PeekChar(1) == '{') + { + return LexMultilineComment(); + } var n = 1; while (!IsEolOrEof(Window.PeekChar(n))) { @@ -36,6 +40,52 @@ namespace Lexer return new Trivia(TriviaType.Comment, Window.GetAndConsumeChars(n)); } + private Trivia LexMultilineComment() + { + var n = 2; + var metPercentSign = false; + var atFirstLine = true; + while (true) + { + var c = Window.PeekChar(n); + if (c == '\0') + { + throw new ParsingException($"Unexpected end of file while parsing multi-line comment."); + } + + if (c == '\n') + { + atFirstLine = false; + } + + if (atFirstLine && !IsWhitespace(c)) // this is a one-line comment + { + while (!IsEolOrEof(Window.PeekChar(n))) + { + n++; + } + + return new Trivia(TriviaType.Comment, Window.GetAndConsumeChars(n)); + } + + if (metPercentSign && c == '}') + { + return new Trivia(TriviaType.MultiLineComment, Window.GetAndConsumeChars(n+1)); + } + + if (c == '%') + { + metPercentSign = true; + } + else + { + metPercentSign = false; + } + + n++; + } + } + private List LexCommentAfterDotDotDot() { var n = 0; diff --git a/Lexer/TextWindow.cs b/Lexer/TextWindow.cs index e57f17e..679a172 100644 --- a/Lexer/TextWindow.cs +++ b/Lexer/TextWindow.cs @@ -52,8 +52,19 @@ public void ConsumeChars(int n) { + for (var i = 0; i < n; i++) + { + if (PeekChar(i) == '\n' || PeekChar(i) == '\r') + { + _position.Line++; + _position.Column = 0; + } + else + { + _position.Column++; + } + } Offset += n; - _position.Column += n; } public char GetAndConsumeChar() diff --git a/Lexer/TriviaType.cs b/Lexer/TriviaType.cs index d7cba4a..c7eb255 100644 --- a/Lexer/TriviaType.cs +++ b/Lexer/TriviaType.cs @@ -4,6 +4,7 @@ { Whitespace, NewLine, - Comment + Comment, + MultiLineComment } } \ No newline at end of file