diff options
Diffstat (limited to 'tools/bookmaker/textParser.cpp')
-rw-r--r-- | tools/bookmaker/textParser.cpp | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/tools/bookmaker/textParser.cpp b/tools/bookmaker/textParser.cpp new file mode 100644 index 0000000000..6ea4a2485e --- /dev/null +++ b/tools/bookmaker/textParser.cpp @@ -0,0 +1,190 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "definition.h" + +#ifdef SK_BUILD_FOR_WIN +#include <Windows.h> +#endif + +TextParser::TextParser(const Definition* definition) : + TextParser(definition->fFileName, definition->fContentStart, definition->fContentEnd, + definition->fLineCount) { +} + +string TextParser::ReportFilename(string file) { + string fullName; +#ifdef SK_BUILD_FOR_WIN + TCHAR pathChars[MAX_PATH]; + DWORD pathLen = GetCurrentDirectory(MAX_PATH, pathChars); + for (DWORD index = 0; index < pathLen; ++index) { + fullName += pathChars[index] == (char)pathChars[index] ? (char)pathChars[index] : '?'; + } + fullName += '\\'; +#endif + fullName += file; + return fullName; +} + +void TextParser::reportError(const char* errorStr) const { + this->reportWarning(errorStr); + SkDebugf(""); // convenient place to set a breakpoint +} + +void TextParser::reportWarning(const char* errorStr) const { + const char* lineStart = fLine; + if (lineStart >= fEnd) { + lineStart = fChar; + } + SkASSERT(lineStart < fEnd); + TextParser err(fFileName, lineStart, fEnd, fLineCount); + size_t lineLen = this->lineLength(); + ptrdiff_t spaces = fChar - lineStart; + while (spaces > 0 && (size_t) spaces > lineLen) { + ++err.fLineCount; + err.fLine += lineLen; + spaces -= lineLen; + lineLen = err.lineLength(); + } + string fullName = this->ReportFilename(fFileName); + SkDebugf("\n%s(%zd): error: %s\n", fullName.c_str(), err.fLineCount, errorStr); + if (0 == lineLen) { + SkDebugf("[blank line]\n"); + } else { + while (lineLen > 0 && '\n' == err.fLine[lineLen - 1]) { + --lineLen; + } + SkDebugf("%.*s\n", (int) lineLen, err.fLine); + SkDebugf("%*s^\n", (int) spaces, ""); + } +} + +void TextParser::setForErrorReporting(const Definition* definition, const char* str) { + fFileName = definition->fFileName; + fStart = definition->fContentStart; + fLine = str; + while (fLine > fStart && fLine[-1] != '\n') { + --fLine; + } + fChar = str; + fEnd = definition->fContentEnd; + fLineCount = definition->fLineCount; + const char* lineInc = fStart; + while (lineInc < str) { + fLineCount += '\n' == *lineInc++; + } +} + +string TextParser::typedefName() { + // look for typedef as one of three forms: + // typedef return-type (*NAME)(params); + // typedef alias NAME; + // typedef std::function<alias> NAME; + string builder; + const char* end = this->doubleLF(); + if (!end) { + end = fEnd; + } + const char* altEnd = this->strnstr("#Typedef ##", end); + if (altEnd) { + end = this->strnchr('\n', end); + } + if (!end) { + return this->reportError<string>("missing typedef std::function end bracket >"); + } + bool stdFunction = this->startsWith("std::function"); + if (stdFunction) { + if (!this->skipToEndBracket('>')) { + return this->reportError<string>("missing typedef std::function end bracket >"); + } + this->next(); + this->skipWhiteSpace(); + builder += string(fChar, end - fChar); + } else { + const char* paren = this->strnchr('(', end); + if (!paren) { + const char* lastWord = nullptr; + do { + this->skipToWhiteSpace(); + if (fChar < end && isspace(fChar[0])) { + const char* whiteStart = fChar; + this->skipWhiteSpace(); + // FIXME: test should be for fMC + if ('#' == fChar[0]) { + end = whiteStart; + break; + } + lastWord = fChar; + } else { + break; + } + } while (true); + if (!lastWord) { + return this->reportError<string>("missing typedef name"); + } + builder += string(lastWord, end - lastWord); + } else { + this->skipTo(paren); + this->next(); + if ('*' != this->next()) { + return this->reportError<string>("missing typedef function asterisk"); + } + const char* nameStart = fChar; + if (!this->skipToEndBracket(')')) { + return this->reportError<string>("missing typedef function )"); + } + builder += string(nameStart, fChar - nameStart); + if (!this->skipToEndBracket('(')) { + return this->reportError<string>("missing typedef params ("); + } + if (! this->skipToEndBracket(')')) { + return this->reportError<string>("missing typedef params )"); + } + this->skipTo(end); + } + } + return builder; +} + +void MethodParser::skipToMethodEnd(Resolvable resolvable) { + if (this->eof()) { + return; + } + string name = fLocalName.length() ? fLocalName : fClassName; + if ('~' == this->peek()) { + this->next(); + if (!this->startsWith(name.c_str())) { + --fChar; + return; + } + } + if (Resolvable::kSimple != resolvable + && Resolvable::kInclude != resolvable + && (this->startsWith(name.c_str()) || this->startsWith("operator"))) { + const char* ptr = this->anyOf("\n ("); + if (ptr && '(' == *ptr && strncmp(ptr, "(...", 4)) { + this->skipToEndBracket(')'); + SkAssertResult(')' == this->next()); + this->skipExact("_const") || (Resolvable::kCode == resolvable + && this->skipExact(" const")); + return; + } + } + if (this->startsWith("Sk") && this->wordEndsWith(".h")) { // allow include refs + this->skipToNonName(); + } else { + this->skipFullName(); + if (this->endsWith("operator")) { + const char* ptr = this->anyOf("\n ("); + if (ptr && '(' == *ptr) { + this->skipToEndBracket(')'); + SkAssertResult(')' == this->next()); + this->skipExact("_const"); + } + } + } +} |