private LexResult LexString(string typeName) { Debug.Assert(Buffer.Peek(0) == '"' || Buffer.Peek(0) == '\''); char quoteChar = Buffer.Peek(); Buffer.AdvanceColumn(); bool isComplete = false; CppTokenKind kind = quoteChar == '\'' ? CppTokenKind.CharLiteral : CppTokenKind.StringLiteral; int maxCount = (kind == CppTokenKind.CharLiteral) ? 1 : -1; int minCount = (kind == CppTokenKind.CharLiteral) ? 1 : 0; int count = 0; while (!Buffer.IsEOF) { char first = Buffer.Peek(); char second = Buffer.Peek(1); if (first == quoteChar) { isComplete = true; break; } else if (first == '\\') { switch (second) { case '\'': case '"': case '?': case '\\': case 'a': case 'b': case 'f': case 'n': case 'e': case 'r': case 't': case 'v': { Buffer.AdvanceColumns(2); ++count; continue; } case 'x': case 'X': case 'u': case 'U': { Buffer.AdvanceColumns(2); if (SyntaxUtils.IsHex(Buffer.Peek())) { int len = 0; while (!Buffer.IsEOF) { if (!SyntaxUtils.IsHex(Buffer.Peek())) { break; } else { ++len; Buffer.AdvanceColumn(); } } } else { AddError(Buffer.TextPosition, $"Unsupported hex escape character '{Buffer.Peek()}'!", typeName); break; } ++count; continue; } default: if (SyntaxUtils.IsOctal(second)) { Buffer.AdvanceColumn(); while (!Buffer.IsEOF) { if (!SyntaxUtils.IsOctal(Buffer.Peek())) { break; } else { Buffer.AdvanceColumn(); } } ++count; continue; } else { AddError(Buffer.TextPosition, $"Not supported escape character '{Buffer.Peek()}'!", typeName); break; } } } else if (SyntaxUtils.IsLineBreak(first)) { break; } else if (char.IsWhiteSpace(first)) { Buffer.AdvanceManual(first, second); } else { Buffer.AdvanceColumn(); } ++count; } // Skip over quote char if (isComplete) { Debug.Assert(Buffer.Peek() == quoteChar); Buffer.AdvanceColumn(); } if (!isComplete) { AddError(Buffer.LexemeStart, $"Unterminated {typeName} literal!", typeName); } else { if (minCount > 0 && count < minCount) { AddError(Buffer.LexemeStart, $"Not enough characters for {typeName} literal, expect {minCount} but got {count}!", typeName); } else if (maxCount > -1 && (count > maxCount)) { AddError(Buffer.LexemeStart, $"Too many characters for {typeName} literal, expect {maxCount} but got {count}!", typeName); } } return(new LexResult(kind, isComplete)); }