Revert "Use SkSL "offset" to actually mean "line""

This reverts commit 47f76853c6.

Reason for revert: Test failures

Original change's description:
> Use SkSL "offset" to actually mean "line"
>
> SkSL internally tracks token offsets, but only ever reports errors using
> line numbers. With the introduction of the DSL, which (being embedded in
> C++ source) only has access to line numbers in the first place, tracking
> offsets went from merely providing little benefit to actively making
> life more difficult.
>
> We are changing SkSL's position tracking from handling offsets to
> handling line numbers, but to simplify the review process the change is
> split up into two main steps. The first step (this CL) starts using
> line numbers everywhere, but avoids the thousand-line churn of actually
> renaming "offset", so most "offset" fields, variables, and parameters
> will be briefly misnamed and will actually contain a line number.
>
> The followup CL will complete the process by renaming all of the
> now-misnamed fields, variables, and parameters, but will not make any
> behavioral changes.
>
> Bug: skia:12459
> Change-Id: I30dc87cf4b816c5ddd7b8ae1be32586388962085
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/451419
> Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
> Reviewed-by: John Stiles <johnstiles@google.com>

Bug: skia:12459
Change-Id: I562d9980cd43a2fc5108e562155fe731a1761dca
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/452720
Auto-Submit: Brian Osman <brianosman@google.com>
Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
This commit is contained in:
Brian Osman 2021-09-24 19:00:35 +00:00 committed by SkCQ
parent cc91452f0a
commit a909dd6b8d
17 changed files with 127 additions and 118 deletions

View File

@ -60,57 +60,57 @@ public:
virtual VariableStorage storage() const = 0;
DSLExpression x() {
return DSLExpression(*this, PositionInfo()).x();
return DSLExpression(*this).x();
}
DSLExpression y() {
return DSLExpression(*this, PositionInfo()).y();
return DSLExpression(*this).y();
}
DSLExpression z() {
return DSLExpression(*this, PositionInfo()).z();
return DSLExpression(*this).z();
}
DSLExpression w() {
return DSLExpression(*this, PositionInfo()).w();
return DSLExpression(*this).w();
}
DSLExpression r() {
return DSLExpression(*this, PositionInfo()).r();
return DSLExpression(*this).r();
}
DSLExpression g() {
return DSLExpression(*this, PositionInfo()).g();
return DSLExpression(*this).g();
}
DSLExpression b() {
return DSLExpression(*this, PositionInfo()).b();
return DSLExpression(*this).b();
}
DSLExpression a() {
return DSLExpression(*this, PositionInfo()).a();
return DSLExpression(*this).a();
}
DSLExpression field(skstd::string_view name) {
return DSLExpression(*this, PositionInfo()).field(name);
return DSLExpression(*this).field(name);
}
DSLPossibleExpression operator[](DSLExpression&& index);
DSLPossibleExpression operator++() {
return ++DSLExpression(*this, PositionInfo());
return ++DSLExpression(*this);
}
DSLPossibleExpression operator++(int) {
return DSLExpression(*this, PositionInfo())++;
return DSLExpression(*this)++;
}
DSLPossibleExpression operator--() {
return --DSLExpression(*this, PositionInfo());
return --DSLExpression(*this);
}
DSLPossibleExpression operator--(int) {
return DSLExpression(*this, PositionInfo())--;
return DSLExpression(*this)--;
}
protected:

View File

@ -35,21 +35,40 @@ public:
static PositionInfo Capture() { return PositionInfo(); }
#endif // __has_builtin(__builtin_FILE) && __has_builtin(__builtin_LINE)
static PositionInfo Offset(const char* file, const char* text, int offset) {
PositionInfo result(file, -1);
result.fText = text;
result.fOffset = offset;
return result;
}
const char* file_name() const {
return fFile;
}
int line() {
if (fLine == -1) {
if (fOffset == -1 || !fText) {
return -1;
}
fLine = 1;
for (int i = 0; i < fOffset; i++) {
if (fText[i] == '\n') {
++fLine;
}
}
}
return fLine;
}
// Temporary method until we finish replacing offset with line
int offset() {
return fLine;
return fOffset;
}
private:
const char* fFile = nullptr;
const char* fText = nullptr;
int32_t fOffset = -1;
int32_t fLine = -1;
};

View File

@ -102,7 +102,7 @@ DSLParser::DSLParser(Compiler* compiler, const ProgramSettings& settings, Progra
, fSettings(settings)
, fKind(kind)
, fText(std::make_unique<String>(std::move(text)))
, fPushback(Token::Kind::TK_NONE, /*offset=*/-1, /*length=*/-1, /*line=*/-1) {
, fPushback(Token::Kind::TK_NONE, -1, -1) {
// We don't want to have to worry about manually releasing all of the objects in the event that
// an error occurs
fSettings.fAssertDSLObjectsReleased = false;
@ -192,15 +192,15 @@ skstd::string_view DSLParser::text(Token token) {
}
PositionInfo DSLParser::position(Token t) {
return this->position(t.fLine);
return this->position(t.fOffset);
}
PositionInfo DSLParser::position(int offset) {
return PositionInfo("<unknown>", offset);
return PositionInfo::Offset("<unknown>", fText->c_str(), offset);
}
void DSLParser::error(Token token, String msg) {
this->error(token.fLine, msg);
this->error(token.fOffset, msg);
}
void DSLParser::error(int offset, String msg) {
@ -284,7 +284,7 @@ bool DSLParser::declaration() {
switch (lookahead.fKind) {
case Token::Kind::TK_SEMICOLON:
this->nextToken();
this->error(lookahead, "expected a declaration, but found ';'");
this->error(lookahead.fOffset, "expected a declaration, but found ';'");
return false;
default:
break;
@ -424,13 +424,13 @@ bool DSLParser::parseInitializer(int offset, DSLExpression* initializer) {
void DSLParser::globalVarDeclarationEnd(PositionInfo pos, const dsl::DSLModifiers& mods,
dsl::DSLType baseType, skstd::string_view name) {
using namespace dsl;
int line = this->peek().fLine;
int offset = this->peek().fOffset;
DSLType type = baseType;
DSLExpression initializer;
if (!this->parseArrayDimensions(line, &type)) {
if (!this->parseArrayDimensions(offset, &type)) {
return;
}
this->parseInitializer(line, &initializer);
this->parseInitializer(offset, &initializer);
DSLGlobalVar first(mods, type, name, std::move(initializer), pos);
Declare(first);
AddToSymbolTable(first);
@ -441,15 +441,14 @@ void DSLParser::globalVarDeclarationEnd(PositionInfo pos, const dsl::DSLModifier
if (!this->expectIdentifier(&identifierName)) {
return;
}
if (!this->parseArrayDimensions(line, &type)) {
if (!this->parseArrayDimensions(offset, &type)) {
return;
}
DSLExpression anotherInitializer;
if (!this->parseInitializer(line, &anotherInitializer)) {
if (!this->parseInitializer(offset, &anotherInitializer)) {
return;
}
DSLGlobalVar next(mods, type, this->text(identifierName), std::move(anotherInitializer),
this->position(line));
DSLGlobalVar next(mods, type, this->text(identifierName), std::move(anotherInitializer));
Declare(next);
AddToSymbolTable(next, this->position(identifierName));
}
@ -461,13 +460,13 @@ void DSLParser::globalVarDeclarationEnd(PositionInfo pos, const dsl::DSLModifier
DSLStatement DSLParser::localVarDeclarationEnd(PositionInfo pos, const dsl::DSLModifiers& mods,
dsl::DSLType baseType, skstd::string_view name) {
using namespace dsl;
int line = this->peek().fLine;
int offset = this->peek().fOffset;
DSLType type = baseType;
DSLExpression initializer;
if (!this->parseArrayDimensions(line, &type)) {
if (!this->parseArrayDimensions(offset, &type)) {
return {};
}
this->parseInitializer(line, &initializer);
this->parseInitializer(offset, &initializer);
DSLVar first(mods, type, name, std::move(initializer), pos);
DSLStatement result = Declare(first);
AddToSymbolTable(first);
@ -478,15 +477,14 @@ DSLStatement DSLParser::localVarDeclarationEnd(PositionInfo pos, const dsl::DSLM
if (!this->expectIdentifier(&identifierName)) {
return result;
}
if (!this->parseArrayDimensions(line, &type)) {
if (!this->parseArrayDimensions(offset, &type)) {
return result;
}
DSLExpression anotherInitializer;
if (!this->parseInitializer(line, &anotherInitializer)) {
if (!this->parseInitializer(offset, &anotherInitializer)) {
return result;
}
DSLVar next(mods, type, this->text(identifierName), std::move(anotherInitializer),
this->position(line));
DSLVar next(mods, type, this->text(identifierName), std::move(anotherInitializer));
DSLWriter::AddVarDeclaration(result, next);
AddToSymbolTable(next, this->position(identifierName));
}
@ -594,7 +592,8 @@ skstd::optional<DSLType> DSLParser::structDeclaration() {
}
}
if (fields.empty()) {
this->error(name, "struct '" + this->text(name) + "' must contain at least one field");
this->error(name.fOffset,
"struct '" + this->text(name) + "' must contain at least one field");
}
return dsl::Struct(this->text(name), SkMakeSpan(fields), this->position(name));
}
@ -1638,10 +1637,10 @@ DSLExpression DSLParser::suffix(DSLExpression base) {
return std::move(result);
}
case Token::Kind::TK_DOT: {
int line = this->peek().fLine;
int offset = this->peek().fOffset;
skstd::string_view text;
if (this->identifier(&text)) {
return this->swizzle(line, std::move(base), text);
return this->swizzle(offset, std::move(base), text);
}
[[fallthrough]];
}
@ -1655,13 +1654,13 @@ DSLExpression DSLParser::suffix(DSLExpression base) {
// identifiers that directly follow the float
Token id = this->nextRawToken();
if (id.fKind == Token::Kind::TK_IDENTIFIER) {
return this->swizzle(next.fLine, std::move(base), field + this->text(id));
return this->swizzle(next.fOffset, std::move(base), field + this->text(id));
} else if (field.empty()) {
this->error(next, "expected field name or swizzle mask after '.'");
return {{DSLExpression::Poison()}};
}
this->pushback(id);
return this->swizzle(next.fLine, std::move(base), field);
return this->swizzle(next.fOffset, std::move(base), field);
}
case Token::Kind::TK_LPAREN: {
ExpressionArray args;
@ -1678,7 +1677,7 @@ DSLExpression DSLParser::suffix(DSLExpression base) {
}
}
this->expect(Token::Kind::TK_RPAREN, "')' to complete function arguments");
return this->call(next.fLine, std::move(base), std::move(args));
return this->call(next.fOffset, std::move(base), std::move(args));
}
case Token::Kind::TK_PLUSPLUS:
return std::move(base)++;
@ -1737,9 +1736,8 @@ DSLExpression DSLParser::term() {
}
default:
this->nextToken();
this->error(t, "expected expression, but found '" + this->text(t) + "'");
this->error(t.fOffset, "expected expression, but found '" + this->text(t) + "'");
fEncounteredFatalError = true;
break;
}
return {};
}

View File

@ -325,7 +325,7 @@ private:
DSLParser* fParser;
Token fPushbackCheckpoint;
SkSL::Lexer::Checkpoint fLexerCheckpoint;
int32_t fLexerCheckpoint;
ForwardingErrorReporter fErrorReporter;
ErrorReporter* fOldErrorReporter;
bool fOldEncounteredFatalError;

View File

@ -21,16 +21,30 @@ void ErrorReporter::error(skstd::string_view msg, PositionInfo position) {
this->handleError(msg, position);
}
void ErrorReporter::error(int line, skstd::string_view msg) {
void ErrorReporter::error(int offset, skstd::string_view msg) {
if (msg.contains(Compiler::POISON_TAG)) {
// don't report errors on poison values
return;
}
if (line == -1) {
if (offset == -1) {
++fErrorCount;
fPendingErrors.push_back(String(msg));
} else {
this->error(msg, PositionInfo(/*file=*/nullptr, line));
this->error(msg, this->position(offset));
}
}
PositionInfo ErrorReporter::position(int offset) const {
if (fSource && offset >= 0) {
int line = 1;
for (int i = 0; i < offset; i++) {
if (fSource[i] == '\n') {
++line;
}
}
return PositionInfo(/*file=*/nullptr, line);
} else {
return PositionInfo();
}
}

View File

@ -844,13 +844,13 @@ Token Lexer::next() {
// a bit.
int32_t startOffset = fOffset;
if (startOffset == (int32_t)fText.length()) {
return Token(Token::Kind::TK_END_OF_FILE, startOffset, 0, fLine);
return Token(Token::Kind::TK_END_OF_FILE, startOffset, 0);
}
State state = 1;
for (;;) {
if (fOffset >= (int32_t)fText.length()) {
if (kAccepts[state] == -1) {
return Token(Token::Kind::TK_END_OF_FILE, startOffset, 0, fLine);
return Token(Token::Kind::TK_END_OF_FILE, startOffset, 0);
}
break;
}
@ -864,12 +864,9 @@ Token Lexer::next() {
}
state = newState;
++fOffset;
if (c == '\n') {
++fLine;
}
}
Token::Kind kind = (Token::Kind)kAccepts[state];
return Token(kind, startOffset, fOffset - startOffset, fLine);
return Token(kind, startOffset, fOffset - startOffset);
}
} // namespace SkSL

View File

@ -106,14 +106,14 @@ struct Token {
TK_NONE,
};
Token() {}
Token(Kind kind, int32_t offset, int32_t length, int32_t line)
: fKind(kind), fOffset(offset), fLength(length), fLine(line) {}
Token() : fKind(Kind::TK_NONE), fOffset(-1), fLength(-1) {}
Kind fKind = Kind::TK_NONE;
int32_t fOffset = -1;
int32_t fLength = -1;
int32_t fLine = -1;
Token(Kind kind, int32_t offset, int32_t length)
: fKind(kind), fOffset(offset), fLength(length) {}
Kind fKind;
int fOffset;
int fLength;
};
class Lexer {
@ -121,27 +121,17 @@ public:
void start(skstd::string_view text) {
fText = text;
fOffset = 0;
fLine = 1;
}
Token next();
struct Checkpoint {
int32_t fOffset;
int32_t fLine;
};
int32_t getCheckpoint() const { return fOffset; }
Checkpoint getCheckpoint() const { return {fOffset, fLine}; }
void rewindToCheckpoint(Checkpoint checkpoint) {
fOffset = checkpoint.fOffset;
fLine = checkpoint.fLine;
}
void rewindToCheckpoint(int32_t checkpoint) { fOffset = checkpoint; }
private:
skstd::string_view fText;
int32_t fOffset;
int32_t fLine;
};
} // namespace SkSL

View File

@ -89,7 +89,7 @@ void Parser::InitLayoutMap() {
Parser::Parser(skstd::string_view text, SymbolTable& symbols, ErrorReporter& errors)
: fText(text)
, fPushback(Token::Kind::TK_NONE, /*offset=*/-1, /*length=*/-1, /*line=*/-1)
, fPushback(Token::Kind::TK_NONE, -1, -1)
, fSymbols(symbols)
, fErrors(&errors) {
fLexer.start(text);
@ -119,7 +119,7 @@ void Parser::createEmptyChild(ASTNode::ID target) {
std::unique_ptr<ASTFile> Parser::compilationUnit() {
fFile = std::make_unique<ASTFile>();
fFile->fNodes.reserve(fText.size() / 10); // a typical program is approx 10:1 for chars:nodes
ASTNode::ID result = this->createNode(/*offset=*/1, ASTNode::Kind::kFile);
ASTNode::ID result = this->createNode(/*offset=*/0, ASTNode::Kind::kFile);
fFile->fRoot = result;
for (;;) {
switch (this->peek().fKind) {

View File

@ -301,7 +301,7 @@ private:
Parser* fParser;
Token fPushbackCheckpoint;
Lexer::Checkpoint fLexerCheckpoint;
int32_t fLexerCheckpoint;
ForwardingErrorReporter fErrorReporter;
ErrorReporter* fOldErrorReporter;
bool fDone = false;

View File

@ -3554,7 +3554,7 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream&
}
// Make sure we have a main() function.
if (!main) {
fContext.fErrors->error(/*offset=*/-1, "program does not contain a main() function");
fContext.fErrors->error(/*offset=*/0, "program does not contain a main() function");
return;
}
// Emit interface blocks.

View File

@ -149,7 +149,7 @@ public:
for (DSLVar& v : vars) {
statements.push_back(Declare(v, pos).release());
}
return SkSL::Block::MakeUnscoped(pos.line(), std::move(statements));
return SkSL::Block::MakeUnscoped(/*offset=*/-1, std::move(statements));
}
static void Declare(DSLGlobalVar& var, PositionInfo pos) {
@ -191,7 +191,7 @@ public:
static DSLPossibleStatement For(DSLStatement initializer, DSLExpression test,
DSLExpression next, DSLStatement stmt, PositionInfo pos) {
return ForStatement::Convert(DSLWriter::Context(), pos.line(),
return ForStatement::Convert(DSLWriter::Context(), /*offset=*/-1,
initializer.releaseIfPossible(), test.releaseIfPossible(),
next.releaseIfPossible(), stmt.release(),
DSLWriter::SymbolTable());
@ -216,13 +216,14 @@ public:
if (baseType->isArray()) {
baseType = &baseType->componentType();
}
DSLWriter::IRGenerator().checkVarDeclaration(pos.line(), field.fModifiers.fModifiers,
DSLWriter::IRGenerator().checkVarDeclaration(/*offset=*/-1, field.fModifiers.fModifiers,
baseType, Variable::Storage::kInterfaceBlock);
GetErrorReporter().reportPendingErrors(field.fPosition);
skslFields.push_back(SkSL::Type::Field(field.fModifiers.fModifiers, field.fName,
&field.fType.skslType()));
}
const SkSL::Type* structType = DSLWriter::SymbolTable()->takeOwnershipOfSymbol(
SkSL::Type::MakeStructType(pos.line(), typeName, std::move(skslFields)));
SkSL::Type::MakeStructType(/*offset=*/-1, typeName, std::move(skslFields)));
DSLType varType = arraySize > 0 ? Array(structType, arraySize) : DSLType(structType);
DSLGlobalVar var(modifiers, varType, !varName.empty() ? varName : typeName);
// Interface blocks can't be declared, so we always need to mark the var declared ourselves.
@ -232,14 +233,14 @@ public:
}
const SkSL::Variable* skslVar = DSLWriter::Var(var);
if (skslVar) {
auto intf = std::make_unique<SkSL::InterfaceBlock>(pos.line(),
auto intf = std::make_unique<SkSL::InterfaceBlock>(/*offset=*/-1,
*skslVar, typeName, varName, arraySize, DSLWriter::SymbolTable());
DSLWriter::IRGenerator().scanInterfaceBlock(*intf);
DSLWriter::ProgramElements().push_back(std::move(intf));
if (varName.empty()) {
const std::vector<SkSL::Type::Field>& structFields = structType->fields();
for (size_t i = 0; i < structFields.size(); ++i) {
DSLWriter::SymbolTable()->add(std::make_unique<SkSL::Field>(pos.line(),
DSLWriter::SymbolTable()->add(std::make_unique<SkSL::Field>(/*offset=*/-1,
skslVar,
i));
}
@ -247,10 +248,11 @@ public:
AddToSymbolTable(var);
}
}
GetErrorReporter().reportPendingErrors(pos);
return var;
}
static DSLStatement Return(DSLExpression value, PositionInfo pos) {
static DSLPossibleStatement Return(DSLExpression value, PositionInfo pos) {
// Note that because Return is called before the function in which it resides exists, at
// this point we do not know the function's return type. We therefore do not check for
// errors, or coerce the value to the correct type, until the return statement is actually

View File

@ -83,12 +83,11 @@ DSLPossibleStatement::~DSLPossibleStatement() {
}
DSLStatement operator,(DSLStatement left, DSLStatement right) {
int line = left.fStatement->fOffset;
StatementArray stmts;
stmts.reserve_back(2);
stmts.push_back(left.release());
stmts.push_back(right.release());
return DSLStatement(SkSL::Block::MakeUnscoped(line, std::move(stmts)));
return DSLStatement(SkSL::Block::MakeUnscoped(/*offset=*/-1, std::move(stmts)));
}
} // namespace dsl

View File

@ -221,8 +221,8 @@ DSLExpression DSLType::Construct(DSLType type, SkSpan<DSLExpression> argArray) {
}
DSLType Array(const DSLType& base, int count, PositionInfo pos) {
count = base.skslType().convertArraySize(DSLWriter::Context(),
DSLExpression(count, pos).release());
count = base.skslType().convertArraySize(DSLWriter::Context(), DSLExpression(count).release());
DSLWriter::ReportErrors(pos);
if (!count) {
return DSLType(kPoison_Type);
}

View File

@ -158,12 +158,12 @@ VariableStorage DSLParameter::storage() const {
DSLPossibleExpression DSLVarBase::operator[](DSLExpression&& index) {
return DSLExpression(*this, PositionInfo())[std::move(index)];
return DSLExpression(*this)[std::move(index)];
}
DSLPossibleExpression DSLVarBase::assign(DSLExpression expr) {
return DSLWriter::ConvertBinary(DSLExpression(*this, PositionInfo()).release(),
SkSL::Token::Kind::TK_EQ, expr.release());
return DSLWriter::ConvertBinary(DSLExpression(*this).release(), SkSL::Token::Kind::TK_EQ,
expr.release());
}
DSLPossibleExpression DSLVar::operator=(DSLExpression expr) {
@ -184,7 +184,7 @@ std::unique_ptr<SkSL::Expression> DSLGlobalVar::methodCall(skstd::string_view me
DSLWriter::ReportError("type does not support method calls", pos);
return nullptr;
}
return DSLWriter::ConvertField(DSLExpression(*this, PositionInfo()).release(), methodName);
return DSLWriter::ConvertField(DSLExpression(*this).release(), methodName);
}
DSLPossibleExpression DSLGlobalVar::eval(DSLExpression x, PositionInfo pos) {

View File

@ -65,7 +65,7 @@ std::unique_ptr<Expression> ConstructorScalarCast::Make(const Context& context,
}
// We can cast scalar literals at compile-time.
if (arg->is<Literal>()) {
return Literal::Make(offset, arg->as<Literal>().value(), &type);
return Literal::Make(arg->fOffset, arg->as<Literal>().value(), &type);
}
return std::make_unique<ConstructorScalarCast>(offset, type, std::move(arg));
}

View File

@ -51,18 +51,19 @@ void writeH(const DFA& dfa, const char* lexer, const char* token,
out << R"(
};
)" << token << "() {}";
)" << token << R"(()
: fKind(Kind::TK_NONE)
, fOffset(-1)
, fLength(-1) {}
out << token << R"((Kind kind, int32_t offset, int32_t length, int32_t line)
)" << token << R"((Kind kind, int32_t offset, int32_t length)
: fKind(kind)
, fOffset(offset)
, fLength(length)
, fLine(line) {}
, fLength(length) {}
Kind fKind = Kind::TK_NONE;
int32_t fOffset = -1;
int32_t fLength = -1;
int32_t fLine = -1;
Kind fKind;
int fOffset;
int fLength;
};
class )" << lexer << R"( {
@ -70,29 +71,21 @@ public:
void start(skstd::string_view text) {
fText = text;
fOffset = 0;
fLine = 1;
}
)" << token << R"( next();
struct Checkpoint {
int32_t fOffset;
int32_t fLine;
};
Checkpoint getCheckpoint() const {
return {fOffset, fLine};
int32_t getCheckpoint() const {
return fOffset;
}
void rewindToCheckpoint(Checkpoint checkpoint) {
fOffset = checkpoint.fOffset;
fLine = checkpoint.fLine;
void rewindToCheckpoint(int32_t checkpoint) {
fOffset = checkpoint;
}
private:
skstd::string_view fText;
int32_t fOffset;
int32_t fLine;
};
} // namespace
@ -161,13 +154,13 @@ void writeCPP(const DFA& dfa, const char* lexer, const char* token, const char*
// a bit.
int32_t startOffset = fOffset;
if (startOffset == (int32_t)fText.length()) {
return )" << token << "(" << token << R"(::Kind::TK_END_OF_FILE, startOffset, 0, fLine);
return )" << token << "(" << token << R"(::Kind::TK_END_OF_FILE, startOffset, 0);
}
State state = 1;
for (;;) {
if (fOffset >= (int32_t)fText.length()) {
if (kAccepts[state] == -1) {
return Token(Token::Kind::TK_END_OF_FILE, startOffset, 0, fLine);
return Token(Token::Kind::TK_END_OF_FILE, startOffset, 0);
}
break;
}
@ -181,12 +174,9 @@ void writeCPP(const DFA& dfa, const char* lexer, const char* token, const char*
}
state = newState;
++fOffset;
if (c == '\n') {
++fLine;
}
}
Token::Kind kind = ()" << token << R"(::Kind) kAccepts[state];
return )" << token << R"((kind, startOffset, fOffset - startOffset, fLine);
return )" << token << R"((kind, startOffset, fOffset - startOffset);
}
} // namespace

View File

@ -1,4 +1,4 @@
### Compilation failed:
error: program does not contain a main() function
error: 1: program does not contain a main() function
1 error