Check for parentheses match during lexing

This commit is contained in:
Alexander Luzgarev 2018-04-05 19:52:03 +02:00
parent ae90b27b41
commit 38da3ecf0b

View File

@ -11,11 +11,13 @@ namespace Lexer
private Token LastToken { get; set; } private Token LastToken { get; set; }
private int TokensSinceNewLine { get; set; } private int TokensSinceNewLine { get; set; }
private PureTokenFactory PureTokenFactory { get; } private PureTokenFactory PureTokenFactory { get; }
private Stack<TokenKind> TokenStack { get; }
public MLexer(ITextWindow window, PureTokenFactory pureTokenFactory) public MLexer(ITextWindow window, PureTokenFactory pureTokenFactory)
{ {
Window = window; Window = window;
PureTokenFactory = pureTokenFactory; PureTokenFactory = pureTokenFactory;
TokenStack = new Stack<TokenKind>();
} }
private static bool IsEolOrEof(char c) private static bool IsEolOrEof(char c)
@ -400,6 +402,7 @@ namespace Lexer
} }
if (TokensSinceNewLine == 1 if (TokensSinceNewLine == 1
&& !TokenStack.Any()
&& LastToken.Kind == TokenKind.Identifier && LastToken.Kind == TokenKind.Identifier
&& LastToken.TrailingTrivia.Any() && LastToken.TrailingTrivia.Any()
&& character != '=' && character != '='
@ -408,8 +411,9 @@ namespace Lexer
{ {
return ContinueParsingUnquotedStringLiteral(); return ContinueParsingUnquotedStringLiteral();
} }
if (LastToken?.Kind == TokenKind.UnquotedStringLiteral && if (LastToken?.Kind == TokenKind.UnquotedStringLiteral
TokensSinceNewLine > 0) && !TokenStack.Any()
&& TokensSinceNewLine > 0)
{ {
return ContinueParsingUnquotedStringLiteral(); return ContinueParsingUnquotedStringLiteral();
} }
@ -642,6 +646,47 @@ namespace Lexer
} }
} }
private bool IsOpeningToken(TokenKind tokenKind)
{
switch (tokenKind)
{
case TokenKind.OpeningBrace:
case TokenKind.OpeningBracket:
case TokenKind.OpeningSquareBracket:
return true;
default:
return false;
}
}
private bool IsClosingToken(TokenKind tokenKind)
{
switch (tokenKind)
{
case TokenKind.ClosingBrace:
case TokenKind.ClosingBracket:
case TokenKind.ClosingSquareBracket:
return true;
default:
return false;
}
}
private TokenKind? OpeningFromClosing(TokenKind tokenKind)
{
switch (tokenKind)
{
case TokenKind.ClosingBrace:
return TokenKind.OpeningBrace;
case TokenKind.ClosingBracket:
return TokenKind.OpeningBracket;
case TokenKind.ClosingSquareBracket:
return TokenKind.OpeningSquareBracket;
default:
return null;
}
}
public Token NextToken() public Token NextToken()
{ {
var leadingTrivia = LexTrivia(false); var leadingTrivia = LexTrivia(false);
@ -656,6 +701,36 @@ namespace Lexer
TokensSinceNewLine++; TokensSinceNewLine++;
} }
if (IsOpeningToken(token.Kind))
{
TokenStack.Push(token.Kind);
}
if (IsClosingToken(token.Kind))
{
if (TokenStack.TryPeek(out var t))
{
if (t == OpeningFromClosing(token.Kind))
{
TokenStack.Pop();
}
else
{
throw new ParsingException($"Unmatched \"{token.LiteralText}\" at {token.Position}.");
}
}
else
{
throw new ParsingException($"Unmatched \"{token.LiteralText}\" at {token.Position}.");
}
}
if (token.Kind == TokenKind.EndOfFile
&& TokenStack.Any())
{
throw new ParsingException($"Unmatched \"{TokenStack.Pop()}\" by the end of file.");
}
var result = new Token(token, leadingTrivia, trailingTrivia); var result = new Token(token, leadingTrivia, trailingTrivia);
LastToken = result; LastToken = result;
return result; return result;