| 198 | } |
| 199 | |
| 200 | std::optional<std::pair<std::string_view, SourceLocation>> Parser::parseSrcComment( |
| 201 | std::string_view const _arguments, |
| 202 | langutil::SourceLocation const& _commentLocation |
| 203 | ) |
| 204 | { |
| 205 | CharStream argumentStream(std::string(_arguments), ""); |
| 206 | Scanner scanner(argumentStream, ScannerKind::SpecialComment); |
| 207 | |
| 208 | std::string_view tail{_arguments.substr(_arguments.size())}; |
| 209 | auto const parseLocationComponent = [](Scanner& _scanner, bool expectTrailingColon) -> std::optional<std::string> |
| 210 | { |
| 211 | bool negative = false; |
| 212 | if (_scanner.currentToken() == Token::Sub) |
| 213 | { |
| 214 | negative = true; |
| 215 | _scanner.next(); |
| 216 | } |
| 217 | if (_scanner.currentToken() != Token::Number) |
| 218 | return std::nullopt; |
| 219 | if (expectTrailingColon && _scanner.peekNextToken() != Token::Colon) |
| 220 | return std::nullopt; |
| 221 | if (!isValidDecimal(_scanner.currentLiteral())) |
| 222 | return std::nullopt; |
| 223 | std::string decimal = (negative ? "-" : "") + _scanner.currentLiteral(); |
| 224 | _scanner.next(); |
| 225 | if (expectTrailingColon) |
| 226 | _scanner.next(); |
| 227 | return decimal; |
| 228 | }; |
| 229 | std::optional<std::string> rawSourceIndex = parseLocationComponent(scanner, true); |
| 230 | std::optional<std::string> rawStart = parseLocationComponent(scanner, true); |
| 231 | std::optional<std::string> rawEnd = parseLocationComponent(scanner, false); |
| 232 | |
| 233 | size_t const snippetStart = static_cast<size_t>(scanner.currentLocation().start); |
| 234 | bool const locationScannedSuccessfully = rawSourceIndex && rawStart && rawEnd; |
| 235 | bool const locationIsWhitespaceSeparated = |
| 236 | scanner.peekNextToken() == Token::EOS || |
| 237 | (snippetStart > 0 && langutil::isWhiteSpace(_arguments[snippetStart - 1])); |
| 238 | |
| 239 | if (!locationScannedSuccessfully || !locationIsWhitespaceSeparated) |
| 240 | { |
| 241 | m_errorReporter.syntaxError( |
| 242 | 8387_error, |
| 243 | _commentLocation, |
| 244 | "Invalid values in source location mapping. Could not parse location specification." |
| 245 | ); |
| 246 | return std::nullopt; |
| 247 | } |
| 248 | |
| 249 | // captures error cases `"test` (illegal end quote) and `"test\` (illegal escape sequence / dangling backslash) |
| 250 | bool const illegalLiteral = scanner.currentToken() == Token::Illegal && (scanner.currentError() == ScannerError::IllegalStringEndQuote || scanner.currentError() == ScannerError::IllegalEscapeSequence); |
| 251 | if (scanner.currentToken() == Token::StringLiteral || illegalLiteral) |
| 252 | tail = _arguments.substr(static_cast<size_t>(scanner.currentLocation().end)); |
| 253 | else |
| 254 | tail = _arguments.substr(static_cast<size_t>(scanner.currentLocation().start)); |
| 255 | |
| 256 | // Other scanner errors may occur if there is no string literal which follows |
| 257 | // (f.ex. IllegalHexDigit, IllegalCommentTerminator), but these are ignored |
nothing calls this directly
no test coverage detected