1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 // ============================================================
11 // Implements the StringLexer class
13 // ============================================================
15 #define DISABLE_BINDER_DEBUG_LOGGING
17 #include "stringlexer.hpp"
22 namespace BINDER_SPACE
24 StringLexer::LEXEME_TYPE
25 StringLexer::GetNextLexeme(SString ¤tString, BOOL fPermitUnescapedQuotes)
27 BOOL fIsEscaped = FALSE;
28 WCHAR wcCurrentChar = INVALID_CHARACTER;
29 BINDER_LOG_ENTER(L"StringLexer::GetNextLexeme");
31 // Remove any white spaces
34 wcCurrentChar = PopCharacter(&fIsEscaped);
36 while (IsWhitespace(wcCurrentChar));
38 // Determine lexeme type
39 LEXEME_TYPE kLexemeType = LEXEME_TYPE_INVALID;
42 kLexemeType = GetLexemeType(wcCurrentChar);
44 if (kLexemeType != LEXEME_TYPE_STRING)
50 // First character of string lexeme; push it back
51 PushCharacter(wcCurrentChar, fIsEscaped);
52 kLexemeType = ParseString(currentString, fPermitUnescapedQuotes);
53 if (kLexemeType == LEXEME_TYPE_STRING)
55 BINDER_LOG_LEAVE_HR(L"StringLexer::GetNextLexeme(LEXEME_TYPE_STRING)", S_OK);
59 BINDER_LOG_LEAVE_HR(L"StringLexer::GetNextLexeme(LEXEME_TYPE_INVALID)",
66 StringLexer::LEXEME_TYPE
67 StringLexer::ParseString(SString ¤tString, BOOL fPermitUnescapedQuotes)
69 BOOL fIsFirstCharacter = TRUE;
70 WCHAR wcCurrentChar = INVALID_CHARACTER;
71 WCHAR wcOpeningQuote = INVALID_CHARACTER;
73 currentString.Clear();
75 // Read until we find another lexeme that's not a string character
78 BOOL fIsEscaped = FALSE;
79 wcCurrentChar = PopCharacter(&fIsEscaped);
81 if (wcCurrentChar == INVALID_CHARACTER)
83 // Found invalid character encoding
84 BINDER_LOG(L"StringLexer::ParseString: Invalid character encoding");
85 return LEXEME_TYPE_INVALID;
88 if (IsEOS(wcCurrentChar))
90 if (IsQuoteCharacter(wcOpeningQuote))
92 // EOS and unclosed quotes is an error
93 BINDER_LOG(L"StringLexer::ParseString: EOS and unclosed quotes");
94 return LEXEME_TYPE_INVALID;
98 // Reached end of input and therefore of string
103 if (fIsFirstCharacter)
105 fIsFirstCharacter = FALSE;
107 // If first character is quote, then record its quoteness
108 if (IsQuoteCharacter(wcCurrentChar))
110 wcOpeningQuote = wcCurrentChar;
115 if (wcCurrentChar == wcOpeningQuote)
117 // We've found the closing quote for a quoted string
121 if (!fPermitUnescapedQuotes && !fIsEscaped && IsQuoteCharacter(wcCurrentChar) && !IsQuoteCharacter(wcOpeningQuote))
123 // Unescaped quotes in the middle of the string are an error
124 BINDER_LOG(L"StringLexer::ParseString: Quote in the middle of a string");
125 return LEXEME_TYPE_INVALID;
128 if (IsSeparatorChar(wcCurrentChar) && !IsQuoteCharacter(wcOpeningQuote) && !fIsEscaped)
130 // Unescaped separator char terminates the string
131 PushCharacter(wcCurrentChar, fIsEscaped);
135 // Add character to current string
136 currentString.Append(wcCurrentChar);
139 if (!IsQuoteCharacter(wcOpeningQuote))
141 // Remove trailing white spaces from unquoted string
142 BINDER_LOG(L"StringLexer::ParseString: Trimming string");
143 TrimTrailingWhiteSpaces(currentString);
146 BINDER_LOG_STRING(L"string", currentString);
148 return LEXEME_TYPE_STRING;
151 void StringLexer::TrimTrailingWhiteSpaces(SString ¤tString)
153 SString::Iterator begin = currentString.Begin();
154 SString::Iterator cursor = currentString.End() - 1;
155 BOOL fFoundWhiteSpace = FALSE;
159 if ((cursor >= begin) && IsWhitespace(cursor[0]))
161 fFoundWhiteSpace = TRUE;
168 if (fFoundWhiteSpace)
170 currentString.Truncate(cursor + 1);