/// <summary> /// Attempts to consume a WhiteSpace token. /// </summary> private static Boolean ConsumeWhiteSpace(String input, IList<UvssLexerToken> output, ref Int32 line, ref Int32 ix) { if (IsPastEndOfStream(input, ix)) return false; if (!IsValidStartWhiteSpace(input[ix])) return false; var start = ix; var length = 0; var newline = false; do { if (input[ix] == '\n') { newline = true; } ix++; length++; } while (ix < input.Length && IsValidInWhiteSpace(input[ix])); var token = new UvssLexerToken(UvssLexerTokenType.WhiteSpace, start, length, line); output.Add(token); if (newline) { line++; } return true; }
/// <summary> /// Attempts to consume a IndexOperator token. /// </summary> private static Boolean ConsumeIndexOperator(String input, IList<UvssLexerToken> output, Int32 line, ref Int32 ix) { var position = ix; if (input[position] != '[') return false; var start = position; var length = 0; position++; while (true) { if (ix >= input.Length) return false; if (input[position] == ']') break; if (!Char.IsDigit(input[position])) return false; length++; position++; } position++; if (length == 0) return false; length += 2; var value = input.Substring(start, length); var token = new UvssLexerToken(UvssLexerTokenType.IndexOperator, start, length, line, value); output.Add(token); ix = position; return true; }
/// <summary> /// Attempts to consume a String token. /// </summary> private static Boolean ConsumeString(String input, IList<UvssLexerToken> output, Int32 line, ref Int32 ix) { if (IsPastEndOfStream(input, ix)) return false; if (input[ix] != '"') return false; var start = ix++; var length = 2; while (ix < input.Length) { if (ix + 1 == input.Length && input[ix] != '"') { throw new UvssException(PresentationStrings.StyleSheetSyntaxUnterminatedString.Format(line)); } var c = input[ix++]; if (c == '"') break; length++; } var value = input.Substring(start + 1, length - 2); var token = new UvssLexerToken(UvssLexerTokenType.String, start, length, line, value); output.Add(token); return true; }
/// <summary> /// Attempts to consume a punctuation token. /// </summary> private static Boolean ConsumePunctuation(UvssLexerTokenType type, Char punctuation, String input, IList<UvssLexerToken> output, Int32 line, ref Int32 ix) { if (IsPastEndOfStream(input, ix)) return false; if (input[ix] == punctuation) { var token = new UvssLexerToken(type, ix, 1, line); output.Add(token); ix++; return true; } return false; }
/// <summary> /// Attempts to consume a UniversalSelector token. /// </summary> private static Boolean ConsumeUniversalSelector(String input, IList<UvssLexerToken> output, Int32 line, ref Int32 ix) { if (IsPastEndOfStream(input, ix)) return false; if (input[ix] != '*') return false; var token = new UvssLexerToken(UvssLexerTokenType.UniversalSelector, ix++, 1, line); output.Add(token); return true; }
/// <summary> /// Attempts to consume a Number token. /// </summary> private static Boolean ConsumeNumber(String input, IList<UvssLexerToken> output, Int32 line, ref Int32 ix) { if (IsPastEndOfStream(input, ix)) return false; if (!Char.IsDigit(input[ix])) return false; var start = ix++; var length = 1; var dec = false; while (ix < input.Length && IsValidInNumber(input[ix], ref dec)) { ix++; length++; } var value = input.Substring(start, length); var token = new UvssLexerToken(UvssLexerTokenType.Number, start, length, line, value); output.Add(token); return true; }
/// <summary> /// Attempts to consume an Identifier token or a keyword token. /// </summary> private static Boolean ConsumeIdentifierOrKeyword(String input, IList<UvssLexerToken> output, Int32 line, ref Int32 ix, ref Boolean storyboard) { if (IsPastEndOfStream(input, ix)) return false; if (!IsValidStartIdentifier(input[ix])) return false; var start = ix++; var length = 1; while (ix < input.Length && IsValidInIdentifier(input[ix])) { ix++; length++; } var tokenType = UvssLexerTokenType.Identifier; var tokenValue = input.Substring(start, length); switch (tokenValue.ToLowerInvariant()) { case "as": tokenType = UvssLexerTokenType.AsOperator; break; } var token = new UvssLexerToken(tokenType, start, length, line, tokenValue); output.Add(token); if (tokenValue.StartsWith("@")) storyboard = true; return true; }
/// <summary> /// Attempts to consume a LogicalChildSelector token. /// </summary> private static Boolean ConsumeLogicalChildSelector(String input, IList<UvssLexerToken> output, Int32 line, ref Int32 ix) { if (IsPastEndOfStream(input, ix + 1)) return false; if (input[ix] != '>' || input[ix + 1] != '?') return false; var token = new UvssLexerToken(UvssLexerTokenType.LogicalChildSelector, ix, 2, line); output.Add(token); ix += 2; return true; }
/// <summary> /// Attempts to consume a ComparisonOperator token. /// </summary> private static Boolean ConsumeComparisonOperator(String input, IList<UvssLexerToken> output, Int32 line, ref Int32 ix) { if (IsPastEndOfStream(input, ix)) return false; var c1 = input[ix]; var c2 = ix + 1 < input.Length ? input[ix + 1] : default(Char); var op = ""; switch (c1) { case '=': op = "="; break; case '<': if (c2 == '>') { op = "<>"; break; } if (c2 == '=') { op = "<="; break; } op = "<"; break; case '>': if (c2 == '=') { op = ">="; break; } op = ">"; break; default: return false; } var token = new UvssLexerToken(UvssLexerTokenType.ComparisonOperator, ix, op.Length, line, op); output.Add(token); ix += op.Length; return true; }
/// <summary> /// Attempts to consume a StyleName token. /// </summary> private static Boolean ConsumeStyleName(String input, IList<UvssLexerToken> output, Int32 line, ref Int32 ix) { if (IsPastEndOfStream(input, ix)) return false; if (!IsValidStartStyleName(input[ix])) return false; var start = ix++; var length = 1; var qualified = false; while (ix < input.Length && IsValidInStyleName(input[ix], ref qualified)) { ix++; length++; } var value = input.Substring(start, length); var type = String.Equals(value, "trigger", StringComparison.InvariantCultureIgnoreCase) ? UvssLexerTokenType.TriggerKeyword : UvssLexerTokenType.StyleName; var token = new UvssLexerToken(type, start, length, line, value); output.Add(token); if (type == UvssLexerTokenType.TriggerKeyword) { ChangeContext(cachedLexerContext_Trigger); } return true; }
/// <summary> /// Attempts to consume a MultiLineComment token. /// </summary> private static Boolean ConsumeMultiLineComment(String input, IList<UvssLexerToken> output, ref Int32 line, ref Int32 ix) { if (IsPastEndOfStream(input, ix)) return false; if (!IsValidStartMultiLineComment(input, ix)) return false; var start = ix + 2; var length = 0; for (var position = start; position < input.Length; position++) { if (input[position] == '\n') line++; if (IsValidEndMultiLineComment(input, position)) break; length++; } var totalLength = length + "/**/".Length; var token = new UvssLexerToken(UvssLexerTokenType.MultiLineComment, ix, totalLength, line, input.Substring(start, length)); output.Add(token); ix += totalLength; return true; }
/// <summary> /// Throws an exception indicating that an expected token was not found. /// </summary> /// <param name="state">The parser state.</param> /// <param name="token">The invalid token.</param> /// <param name="expected">The expected token type.</param> private static void ThrowExpectedToken(UvssParserState state, UvssLexerToken token, UvssLexerTokenType expected) { var lineNumber = token.Line; throw new UvssException(PresentationStrings.StyleSheetSyntaxExpectedToken.Format(lineNumber, token.TokenType, expected)); }
/// <summary> /// Gets a value indicating whether the specified token is a match for the specified parameters. /// </summary> /// <param name="token">The token to evaluate.</param> /// <param name="type">The desired token type.</param> /// <param name="value">The desired token value.</param> /// <returns><c>true</c> if the specified token is a match; otherwise, <c>false</c>.</returns> private static Boolean MatchToken(UvssLexerToken? token, UvssLexerTokenType type, String value = null) { if (token == null) return false; if (token.Value.TokenType != type) return false; if (value != null && !String.Equals(token.Value.Value, value, StringComparison.OrdinalIgnoreCase)) return false; return true; }
/// <summary> /// Throws an exception if the specified token does not match the specified parameters. /// </summary> /// <param name="state">The parser state.</param> /// <param name="token">The token to evaluate.</param> /// <param name="type">The desired token type.</param> /// <param name="value">The desired token value.</param> private static void MatchTokenOrFail(UvssParserState state, UvssLexerToken? token, UvssLexerTokenType type, String value = null) { if (token == null) ThrowUnexpectedEOF(state); if (token.Value.TokenType != type) ThrowExpectedToken(state, token.Value, type); if (value != null && !String.Equals(token.Value.Value, value, StringComparison.OrdinalIgnoreCase)) ThrowExpectedValue(state, token.Value, value); }
/// <summary> /// Throws an exception indicating that an unexpected value was reached. /// </summary> /// <param name="state">The parser state.</param> /// <param name="token">The invalid token.</param> private static void ThrowUnexpectedValue(UvssParserState state, UvssLexerToken token) { var lineNumber = token.Line; throw new UvssException(PresentationStrings.StyleSheetSyntaxUnexpectedValue.Format(lineNumber, token.Value)); }