/// <summary>Matches a string. Works with single or double quotes and escaping.</summary> /// <returns>Wether a string was matched.</returns> public bool MatchString() { LexScanner scanner = MakeScanner(); // single will be true for single quotes, false for double quotes. bool single = scanner.At('\''); // Not a string. if (!single && !scanner.At('\"')) { return(false); } char lookingFor = single ? '\'' : '\"'; bool escaped = false; // Look for end of string. do { scanner.Advance(); if (scanner.At('\\') && !escaped) { escaped = true; } else if (escaped) { escaped = false; } }while (!scanner.ReachedEnd && (escaped || !scanner.At(lookingFor))); scanner.Advance(); PushToken(scanner, TokenType.String); return(true); }
bool MatchBlockComment() { LexScanner scanner = MakeScanner(); if (!scanner.At('/') || !scanner.At('*', 1)) { return(false); } scanner.Advance(); scanner.Advance(); // Match every character to the end of the line. while (!scanner.ReachedEnd) { if (scanner.At('*') && scanner.At('/', 1)) { scanner.Advance(); scanner.Advance(); break; } scanner.Advance(); } // Done. Accept(scanner); return(true); }
/// <summary>Unknown token.</summary> public void Unknown() { LexScanner scanner = MakeScanner(); PushToken(new Token(Content[Index].ToString(), new DocRange(new DocPos(Line, Column), new DocPos(Line, Column + 1)), TokenType.Unknown)); scanner.Advance(); Accept(scanner); }
/// <summary>Matches a string. Works with single or double quotes and escaping.</summary> /// <returns>Whether a string was matched.</returns> public bool MatchString(bool continueInterpolatedString = false, bool single = false) { LexScanner scanner = MakeScanner(); // Interpolated string. bool interpolated = continueInterpolatedString || scanner.Match('$'); if (!continueInterpolatedString) { // single will be true for single quotes, false for double quotes. single = scanner.Match('\''); // Not a string. if (!single && !scanner.Match('\"')) { return(false); } } char lookingFor = single ? '\'' : '\"'; //escaped will be 0 whenever it's not escaped bool escaped = false; // Look for end of string. while (!scanner.ReachedEnd && (escaped || !scanner.Match(lookingFor))) { var progressCheck = scanner.Index; // If this is an interpolated string, look for a '{' that is not followed by another '{'. if (interpolated && scanner.Match('{') && !scanner.Match('{')) { Token resultingToken = scanner.AsToken(continueInterpolatedString ? TokenType.InterpolatedStringMiddle : TokenType.InterpolatedStringTail); if (single) { resultingToken.Flags |= TokenFlags.StringSingleQuotes; } PushToken(resultingToken); Accept(scanner); return(true); } escaped = escaped ? false : scanner.Match('\\'); // If the scanner did not progress, advance. if (progressCheck == scanner.Index) { scanner.Advance(); } } PushToken(scanner, interpolated ? TokenType.InterpolatedStringHead : TokenType.String); return(true); }
/// <summary>Skips whitespace.</summary> public void Skip() { do { LexScanner scanner = MakeScanner(); while (!scanner.ReachedEnd && scanner.AtWhitespace()) { scanner.Advance(); } Accept(scanner); } while(MatchLineComment() || MatchBlockComment()); }
/// <summary>Matches a symbol.</summary> /// <returns>Whether a symbol was matched.</returns> public bool MatchSymbol(char symbol, TokenType tokenType) { LexScanner scanner = MakeScanner(); if (scanner.Match(symbol)) { PushToken(scanner.AsToken(tokenType)); Accept(scanner); return(true); } return(false); }
// * Matchers * /// <summary>Matches a keyword.</summary> /// <param name="keyword">The name of the keyword that will be matched.</param> /// <param name="tokenType">The type of the created token.</param> /// <returns>Whether the keyword was matched.</returns> public bool MatchKeyword(string keyword, TokenType tokenType) { LexScanner scanner = MakeScanner(); if (scanner.Match(keyword) && !scanner.AtIdentifierChar()) { PushToken(scanner.AsToken(tokenType)); Accept(scanner); return(true); } return(false); }
/// <summary>Skips whitespace.</summary> public bool Skip() { bool preceedingWhitespace = false; LexScanner scanner = MakeScanner(); while (!scanner.ReachedEnd && scanner.AtWhitespace()) { if (scanner.At('\n')) { preceedingWhitespace = true; } scanner.Advance(); } Accept(scanner); return(preceedingWhitespace); }
/// <summary>Matches a number.</summary> /// <returns>Whether a number was matched.</returns> public bool MatchNumber() { LexScanner scanner = MakeScanner(); // Get the number. bool foundLeftNumber = false; while (scanner.AtNumeric()) { scanner.Advance(); foundLeftNumber = true; } Skip(); // At decimal if (scanner.At('.')) { scanner.Advance(); Skip(); // Get the decimal. bool decimalFound = false; while (scanner.AtNumeric()) { scanner.Advance(); decimalFound = true; } if (!decimalFound && !foundLeftNumber) { return(false); } } // No decimal and no left number. else if (!foundLeftNumber) { return(false); } // Done. PushToken(scanner, TokenType.Number); return(true); }
/// <summary>Matches an identifier.</summary> /// <returns>Whether an identifier was matched.</returns> public bool MatchIdentifier() { LexScanner scanner = MakeScanner(); // Advance while the current character is an identifier. while (!scanner.ReachedEnd && scanner.AtIdentifierChar()) { scanner.Advance(); } // Push the token if it is accepted. if (scanner.WasAdvanced) { PushToken(scanner.AsToken(TokenType.Identifier)); Accept(scanner); return(true); } return(false); }
bool MatchActionComment() { LexScanner scanner = MakeScanner(); // Action comment. if (!scanner.At('#')) { return(false); } // Match every character to the end of the line. scanner.Advance(); while (!scanner.ReachedEnd && !scanner.At('\n')) { scanner.Advance(); } // Done. PushToken(scanner, TokenType.ActionComment); return(true); }
/// <summary>Matches a string. Works with single or double quotes and escaping.</summary> /// <returns>Wether a string was matched.</returns> public bool MatchString() { LexScanner scanner = MakeScanner(); // single will be true for single quotes, false for double quotes. bool single = scanner.At('\''); // Not a string. if (!single && !scanner.At('\"')) { return(false); } char lookingFor = single ? '\'' : '\"'; //escaped will be 0 whenever it's not escaped int escaped = 0; // Look for end of string. do { scanner.Advance(); if (scanner.At('\\') && escaped == 0) { escaped = 2; } else if (escaped > 0) { escaped -= 1; } }while (!scanner.ReachedEnd && ((escaped > 0) || !scanner.At(lookingFor))); scanner.Advance(); PushToken(scanner, TokenType.String); return(true); }
private void PushToken(LexScanner scanner, TokenType tokenType) { _push.PushToken(scanner.AsToken(tokenType)); Accept(scanner); }
private void Accept(LexScanner scanner) { Index = scanner.Index; Line = scanner.Line; Column = scanner.Column; }