Reland "Use SkSL "offset" to actually mean "line""
This reverts commit a909dd6b8d8d6540f382e848c959792379f19365.
Turns out those reportPendingErrors() calls I removed were in fact
necessary, just not on any of the CQ bots.
Change-Id: I8be0898ac0b41dbb703a35f705cac06ca716c0b7
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/453077
Reviewed-by: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
diff --git a/include/sksl/DSLVar.h b/include/sksl/DSLVar.h
index 059bbab..16343ec 100644
--- a/include/sksl/DSLVar.h
+++ b/include/sksl/DSLVar.h
@@ -60,57 +60,57 @@
virtual VariableStorage storage() const = 0;
DSLExpression x() {
- return DSLExpression(*this).x();
+ return DSLExpression(*this, PositionInfo()).x();
}
DSLExpression y() {
- return DSLExpression(*this).y();
+ return DSLExpression(*this, PositionInfo()).y();
}
DSLExpression z() {
- return DSLExpression(*this).z();
+ return DSLExpression(*this, PositionInfo()).z();
}
DSLExpression w() {
- return DSLExpression(*this).w();
+ return DSLExpression(*this, PositionInfo()).w();
}
DSLExpression r() {
- return DSLExpression(*this).r();
+ return DSLExpression(*this, PositionInfo()).r();
}
DSLExpression g() {
- return DSLExpression(*this).g();
+ return DSLExpression(*this, PositionInfo()).g();
}
DSLExpression b() {
- return DSLExpression(*this).b();
+ return DSLExpression(*this, PositionInfo()).b();
}
DSLExpression a() {
- return DSLExpression(*this).a();
+ return DSLExpression(*this, PositionInfo()).a();
}
DSLExpression field(skstd::string_view name) {
- return DSLExpression(*this).field(name);
+ return DSLExpression(*this, PositionInfo()).field(name);
}
DSLPossibleExpression operator[](DSLExpression&& index);
DSLPossibleExpression operator++() {
- return ++DSLExpression(*this);
+ return ++DSLExpression(*this, PositionInfo());
}
DSLPossibleExpression operator++(int) {
- return DSLExpression(*this)++;
+ return DSLExpression(*this, PositionInfo())++;
}
DSLPossibleExpression operator--() {
- return --DSLExpression(*this);
+ return --DSLExpression(*this, PositionInfo());
}
DSLPossibleExpression operator--(int) {
- return DSLExpression(*this)--;
+ return DSLExpression(*this, PositionInfo())--;
}
protected:
diff --git a/include/sksl/SkSLErrorReporter.h b/include/sksl/SkSLErrorReporter.h
index 2c90ad8..af949c3 100644
--- a/include/sksl/SkSLErrorReporter.h
+++ b/include/sksl/SkSLErrorReporter.h
@@ -35,40 +35,21 @@
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 fOffset;
+ return fLine;
}
private:
const char* fFile = nullptr;
- const char* fText = nullptr;
- int32_t fOffset = -1;
int32_t fLine = -1;
};
diff --git a/src/sksl/SkSLDSLParser.cpp b/src/sksl/SkSLDSLParser.cpp
index 439aa08..8b283e9 100644
--- a/src/sksl/SkSLDSLParser.cpp
+++ b/src/sksl/SkSLDSLParser.cpp
@@ -103,7 +103,7 @@
, fSettings(settings)
, fKind(kind)
, fText(std::make_unique<String>(std::move(text)))
- , fPushback(Token::Kind::TK_NONE, -1, -1) {
+ , fPushback(Token::Kind::TK_NONE, /*offset=*/-1, /*length=*/-1, /*line=*/-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;
@@ -193,15 +193,15 @@
}
PositionInfo DSLParser::position(Token t) {
- return this->position(t.fOffset);
+ return this->position(t.fLine);
}
PositionInfo DSLParser::position(int offset) {
- return PositionInfo::Offset("<unknown>", fText->c_str(), offset);
+ return PositionInfo("<unknown>", offset);
}
void DSLParser::error(Token token, String msg) {
- this->error(token.fOffset, msg);
+ this->error(token.fLine, msg);
}
void DSLParser::error(int offset, String msg) {
@@ -303,7 +303,7 @@
switch (lookahead.fKind) {
case Token::Kind::TK_SEMICOLON:
this->nextToken();
- this->error(lookahead.fOffset, "expected a declaration, but found ';'");
+ this->error(lookahead, "expected a declaration, but found ';'");
return false;
default:
break;
@@ -443,13 +443,13 @@
void DSLParser::globalVarDeclarationEnd(PositionInfo pos, const dsl::DSLModifiers& mods,
dsl::DSLType baseType, skstd::string_view name) {
using namespace dsl;
- int offset = this->peek().fOffset;
+ int line = this->peek().fLine;
DSLType type = baseType;
DSLExpression initializer;
- if (!this->parseArrayDimensions(offset, &type)) {
+ if (!this->parseArrayDimensions(line, &type)) {
return;
}
- if (!this->parseInitializer(offset, &initializer)) {
+ if (!this->parseInitializer(line, &initializer)) {
return;
}
DSLGlobalVar first(mods, type, name, std::move(initializer), pos);
@@ -462,15 +462,15 @@
if (!this->expectIdentifier(&identifierName)) {
return;
}
- if (!this->parseArrayDimensions(offset, &type)) {
+ if (!this->parseArrayDimensions(line, &type)) {
return;
}
DSLExpression anotherInitializer;
- if (!this->parseInitializer(offset, &anotherInitializer)) {
+ if (!this->parseInitializer(line, &anotherInitializer)) {
return;
}
DSLGlobalVar next(mods, type, this->text(identifierName), std::move(anotherInitializer),
- this->position(offset));
+ this->position(line));
Declare(next);
AddToSymbolTable(next, this->position(identifierName));
}
@@ -482,13 +482,13 @@
DSLStatement DSLParser::localVarDeclarationEnd(PositionInfo pos, const dsl::DSLModifiers& mods,
dsl::DSLType baseType, skstd::string_view name) {
using namespace dsl;
- int offset = this->peek().fOffset;
+ int line = this->peek().fLine;
DSLType type = baseType;
DSLExpression initializer;
- if (!this->parseArrayDimensions(offset, &type)) {
+ if (!this->parseArrayDimensions(line, &type)) {
return {};
}
- if (!this->parseInitializer(offset, &initializer)) {
+ if (!this->parseInitializer(line, &initializer)) {
return {};
}
DSLVar first(mods, type, name, std::move(initializer), pos);
@@ -501,15 +501,15 @@
if (!this->expectIdentifier(&identifierName)) {
return result;
}
- if (!this->parseArrayDimensions(offset, &type)) {
+ if (!this->parseArrayDimensions(line, &type)) {
return result;
}
DSLExpression anotherInitializer;
- if (!this->parseInitializer(offset, &anotherInitializer)) {
+ if (!this->parseInitializer(line, &anotherInitializer)) {
return result;
}
DSLVar next(mods, type, this->text(identifierName), std::move(anotherInitializer),
- this->position(offset));
+ this->position(line));
DSLWriter::AddVarDeclaration(result, next);
AddToSymbolTable(next, this->position(identifierName));
}
@@ -617,8 +617,7 @@
}
}
if (fields.empty()) {
- this->error(name.fOffset,
- "struct '" + this->text(name) + "' must contain at least one field");
+ this->error(name, "struct '" + this->text(name) + "' must contain at least one field");
}
return dsl::Struct(this->text(name), SkMakeSpan(fields), this->position(name));
}
@@ -1662,10 +1661,10 @@
return std::move(result);
}
case Token::Kind::TK_DOT: {
- int offset = this->peek().fOffset;
+ int line = this->peek().fLine;
skstd::string_view text;
if (this->identifier(&text)) {
- return this->swizzle(offset, std::move(base), text);
+ return this->swizzle(line, std::move(base), text);
}
[[fallthrough]];
}
@@ -1679,13 +1678,13 @@
// identifiers that directly follow the float
Token id = this->nextRawToken();
if (id.fKind == Token::Kind::TK_IDENTIFIER) {
- return this->swizzle(next.fOffset, std::move(base), field + this->text(id));
+ return this->swizzle(next.fLine, 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.fOffset, std::move(base), field);
+ return this->swizzle(next.fLine, std::move(base), field);
}
case Token::Kind::TK_LPAREN: {
ExpressionArray args;
@@ -1702,7 +1701,7 @@
}
}
this->expect(Token::Kind::TK_RPAREN, "')' to complete function arguments");
- return this->call(next.fOffset, std::move(base), std::move(args));
+ return this->call(next.fLine, std::move(base), std::move(args));
}
case Token::Kind::TK_PLUSPLUS:
return std::move(base)++;
@@ -1761,8 +1760,9 @@
}
default:
this->nextToken();
- this->error(t.fOffset, "expected expression, but found '" + this->text(t) + "'");
+ this->error(t, "expected expression, but found '" + this->text(t) + "'");
fEncounteredFatalError = true;
+ break;
}
return {};
}
diff --git a/src/sksl/SkSLDSLParser.h b/src/sksl/SkSLDSLParser.h
index d496c8b..aed2a19 100644
--- a/src/sksl/SkSLDSLParser.h
+++ b/src/sksl/SkSLDSLParser.h
@@ -330,7 +330,7 @@
DSLParser* fParser;
Token fPushbackCheckpoint;
- int32_t fLexerCheckpoint;
+ SkSL::Lexer::Checkpoint fLexerCheckpoint;
ForwardingErrorReporter fErrorReporter;
ErrorReporter* fOldErrorReporter;
bool fOldEncounteredFatalError;
diff --git a/src/sksl/SkSLErrorReporter.cpp b/src/sksl/SkSLErrorReporter.cpp
index 797b5e9..6be9dd0 100644
--- a/src/sksl/SkSLErrorReporter.cpp
+++ b/src/sksl/SkSLErrorReporter.cpp
@@ -21,30 +21,16 @@
this->handleError(msg, position);
}
-void ErrorReporter::error(int offset, skstd::string_view msg) {
+void ErrorReporter::error(int line, skstd::string_view msg) {
if (msg.contains(Compiler::POISON_TAG)) {
// don't report errors on poison values
return;
}
- if (offset == -1) {
+ if (line == -1) {
++fErrorCount;
fPendingErrors.push_back(String(msg));
} else {
- 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();
+ this->error(msg, PositionInfo(/*file=*/nullptr, line));
}
}
diff --git a/src/sksl/SkSLLexer.cpp b/src/sksl/SkSLLexer.cpp
index ac59ca6..d6a6245 100644
--- a/src/sksl/SkSLLexer.cpp
+++ b/src/sksl/SkSLLexer.cpp
@@ -844,13 +844,13 @@
// a bit.
int32_t startOffset = fOffset;
if (startOffset == (int32_t)fText.length()) {
- return Token(Token::Kind::TK_END_OF_FILE, startOffset, 0);
+ return Token(Token::Kind::TK_END_OF_FILE, startOffset, 0, fLine);
}
State state = 1;
for (;;) {
if (fOffset >= (int32_t)fText.length()) {
if (kAccepts[state] == -1) {
- return Token(Token::Kind::TK_END_OF_FILE, startOffset, 0);
+ return Token(Token::Kind::TK_END_OF_FILE, startOffset, 0, fLine);
}
break;
}
@@ -864,9 +864,12 @@
}
state = newState;
++fOffset;
+ if (c == '\n') {
+ ++fLine;
+ }
}
Token::Kind kind = (Token::Kind)kAccepts[state];
- return Token(kind, startOffset, fOffset - startOffset);
+ return Token(kind, startOffset, fOffset - startOffset, fLine);
}
} // namespace SkSL
diff --git a/src/sksl/SkSLLexer.h b/src/sksl/SkSLLexer.h
index 19e3390..2c150bf 100644
--- a/src/sksl/SkSLLexer.h
+++ b/src/sksl/SkSLLexer.h
@@ -106,14 +106,14 @@
TK_NONE,
};
- Token() : fKind(Kind::TK_NONE), fOffset(-1), fLength(-1) {}
+ Token() {}
+ Token(Kind kind, int32_t offset, int32_t length, int32_t line)
+ : fKind(kind), fOffset(offset), fLength(length), fLine(line) {}
- Token(Kind kind, int32_t offset, int32_t length)
- : fKind(kind), fOffset(offset), fLength(length) {}
-
- Kind fKind;
- int fOffset;
- int fLength;
+ Kind fKind = Kind::TK_NONE;
+ int32_t fOffset = -1;
+ int32_t fLength = -1;
+ int32_t fLine = -1;
};
class Lexer {
@@ -121,17 +121,27 @@
void start(skstd::string_view text) {
fText = text;
fOffset = 0;
+ fLine = 1;
}
Token next();
- int32_t getCheckpoint() const { return fOffset; }
+ struct Checkpoint {
+ int32_t fOffset;
+ int32_t fLine;
+ };
- void rewindToCheckpoint(int32_t checkpoint) { fOffset = checkpoint; }
+ Checkpoint getCheckpoint() const { return {fOffset, fLine}; }
+
+ void rewindToCheckpoint(Checkpoint checkpoint) {
+ fOffset = checkpoint.fOffset;
+ fLine = checkpoint.fLine;
+ }
private:
skstd::string_view fText;
int32_t fOffset;
+ int32_t fLine;
};
} // namespace SkSL
diff --git a/src/sksl/SkSLParser.cpp b/src/sksl/SkSLParser.cpp
index 95ad7ac..09d65ae 100644
--- a/src/sksl/SkSLParser.cpp
+++ b/src/sksl/SkSLParser.cpp
@@ -89,7 +89,7 @@
Parser::Parser(skstd::string_view text, SymbolTable& symbols, ErrorReporter& errors)
: fText(text)
-, fPushback(Token::Kind::TK_NONE, -1, -1)
+, fPushback(Token::Kind::TK_NONE, /*offset=*/-1, /*length=*/-1, /*line=*/-1)
, fSymbols(symbols)
, fErrors(&errors) {
fLexer.start(text);
@@ -119,7 +119,7 @@
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=*/0, ASTNode::Kind::kFile);
+ ASTNode::ID result = this->createNode(/*offset=*/1, ASTNode::Kind::kFile);
fFile->fRoot = result;
for (;;) {
switch (this->peek().fKind) {
diff --git a/src/sksl/SkSLParser.h b/src/sksl/SkSLParser.h
index d83e34f..699984b 100644
--- a/src/sksl/SkSLParser.h
+++ b/src/sksl/SkSLParser.h
@@ -301,7 +301,7 @@
Parser* fParser;
Token fPushbackCheckpoint;
- int32_t fLexerCheckpoint;
+ Lexer::Checkpoint fLexerCheckpoint;
ForwardingErrorReporter fErrorReporter;
ErrorReporter* fOldErrorReporter;
bool fDone = false;
diff --git a/src/sksl/codegen/SkSLSPIRVCodeGenerator.cpp b/src/sksl/codegen/SkSLSPIRVCodeGenerator.cpp
index d42b6e2..47e80a0 100644
--- a/src/sksl/codegen/SkSLSPIRVCodeGenerator.cpp
+++ b/src/sksl/codegen/SkSLSPIRVCodeGenerator.cpp
@@ -3554,7 +3554,7 @@
}
// Make sure we have a main() function.
if (!main) {
- fContext.fErrors->error(/*offset=*/0, "program does not contain a main() function");
+ fContext.fErrors->error(/*offset=*/-1, "program does not contain a main() function");
return;
}
// Emit interface blocks.
diff --git a/src/sksl/dsl/DSLCore.cpp b/src/sksl/dsl/DSLCore.cpp
index 272fc8c..6885a7b 100644
--- a/src/sksl/dsl/DSLCore.cpp
+++ b/src/sksl/dsl/DSLCore.cpp
@@ -149,7 +149,7 @@
for (DSLVar& v : vars) {
statements.push_back(Declare(v, pos).release());
}
- return SkSL::Block::MakeUnscoped(/*offset=*/-1, std::move(statements));
+ return SkSL::Block::MakeUnscoped(pos.line(), std::move(statements));
}
static void Declare(DSLGlobalVar& var, PositionInfo pos) {
@@ -191,7 +191,7 @@
static DSLPossibleStatement For(DSLStatement initializer, DSLExpression test,
DSLExpression next, DSLStatement stmt, PositionInfo pos) {
- return ForStatement::Convert(DSLWriter::Context(), /*offset=*/-1,
+ return ForStatement::Convert(DSLWriter::Context(), pos.line(),
initializer.releaseIfPossible(), test.releaseIfPossible(),
next.releaseIfPossible(), stmt.release(),
DSLWriter::SymbolTable());
@@ -216,14 +216,14 @@
if (baseType->isArray()) {
baseType = &baseType->componentType();
}
- DSLWriter::IRGenerator().checkVarDeclaration(/*offset=*/-1, field.fModifiers.fModifiers,
+ DSLWriter::IRGenerator().checkVarDeclaration(pos.line(), 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(/*offset=*/-1, typeName, std::move(skslFields)));
+ SkSL::Type::MakeStructType(pos.line(), 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.
@@ -233,14 +233,14 @@
}
const SkSL::Variable* skslVar = DSLWriter::Var(var);
if (skslVar) {
- auto intf = std::make_unique<SkSL::InterfaceBlock>(/*offset=*/-1,
+ auto intf = std::make_unique<SkSL::InterfaceBlock>(pos.line(),
*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>(/*offset=*/-1,
+ DSLWriter::SymbolTable()->add(std::make_unique<SkSL::Field>(pos.line(),
skslVar,
i));
}
@@ -252,7 +252,7 @@
return var;
}
- static DSLPossibleStatement Return(DSLExpression value, PositionInfo pos) {
+ static DSLStatement 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
diff --git a/src/sksl/dsl/DSLStatement.cpp b/src/sksl/dsl/DSLStatement.cpp
index af2d9aa..080491f 100644
--- a/src/sksl/dsl/DSLStatement.cpp
+++ b/src/sksl/dsl/DSLStatement.cpp
@@ -83,11 +83,12 @@
}
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(/*offset=*/-1, std::move(stmts)));
+ return DSLStatement(SkSL::Block::MakeUnscoped(line, std::move(stmts)));
}
} // namespace dsl
diff --git a/src/sksl/dsl/DSLType.cpp b/src/sksl/dsl/DSLType.cpp
index c2d13ca..03258f9 100644
--- a/src/sksl/dsl/DSLType.cpp
+++ b/src/sksl/dsl/DSLType.cpp
@@ -221,7 +221,8 @@
}
DSLType Array(const DSLType& base, int count, PositionInfo pos) {
- count = base.skslType().convertArraySize(DSLWriter::Context(), DSLExpression(count).release());
+ count = base.skslType().convertArraySize(DSLWriter::Context(),
+ DSLExpression(count, pos).release());
DSLWriter::ReportErrors(pos);
if (!count) {
return DSLType(kPoison_Type);
diff --git a/src/sksl/dsl/DSLVar.cpp b/src/sksl/dsl/DSLVar.cpp
index 70d0115..37de479 100644
--- a/src/sksl/dsl/DSLVar.cpp
+++ b/src/sksl/dsl/DSLVar.cpp
@@ -158,12 +158,12 @@
DSLPossibleExpression DSLVarBase::operator[](DSLExpression&& index) {
- return DSLExpression(*this)[std::move(index)];
+ return DSLExpression(*this, PositionInfo())[std::move(index)];
}
DSLPossibleExpression DSLVarBase::assign(DSLExpression expr) {
- return DSLWriter::ConvertBinary(DSLExpression(*this).release(), SkSL::Token::Kind::TK_EQ,
- expr.release());
+ return DSLWriter::ConvertBinary(DSLExpression(*this, PositionInfo()).release(),
+ SkSL::Token::Kind::TK_EQ, expr.release());
}
DSLPossibleExpression DSLVar::operator=(DSLExpression expr) {
@@ -184,7 +184,7 @@
DSLWriter::ReportError("type does not support method calls", pos);
return nullptr;
}
- return DSLWriter::ConvertField(DSLExpression(*this).release(), methodName);
+ return DSLWriter::ConvertField(DSLExpression(*this, PositionInfo()).release(), methodName);
}
DSLPossibleExpression DSLGlobalVar::eval(DSLExpression x, PositionInfo pos) {
diff --git a/src/sksl/ir/SkSLConstructorScalarCast.cpp b/src/sksl/ir/SkSLConstructorScalarCast.cpp
index c249075..7473608 100644
--- a/src/sksl/ir/SkSLConstructorScalarCast.cpp
+++ b/src/sksl/ir/SkSLConstructorScalarCast.cpp
@@ -65,7 +65,7 @@
}
// We can cast scalar literals at compile-time.
if (arg->is<Literal>()) {
- return Literal::Make(arg->fOffset, arg->as<Literal>().value(), &type);
+ return Literal::Make(offset, arg->as<Literal>().value(), &type);
}
return std::make_unique<ConstructorScalarCast>(offset, type, std::move(arg));
}
diff --git a/src/sksl/lex/Main.cpp b/src/sksl/lex/Main.cpp
index 143d53a..37cc312 100644
--- a/src/sksl/lex/Main.cpp
+++ b/src/sksl/lex/Main.cpp
@@ -51,19 +51,18 @@
out << R"(
};
- )" << token << R"(()
- : fKind(Kind::TK_NONE)
- , fOffset(-1)
- , fLength(-1) {}
+ )" << token << "() {}";
- )" << token << R"((Kind kind, int32_t offset, int32_t length)
+ out << token << R"((Kind kind, int32_t offset, int32_t length, int32_t line)
: fKind(kind)
, fOffset(offset)
- , fLength(length) {}
+ , fLength(length)
+ , fLine(line) {}
- Kind fKind;
- int fOffset;
- int fLength;
+ Kind fKind = Kind::TK_NONE;
+ int32_t fOffset = -1;
+ int32_t fLength = -1;
+ int32_t fLine = -1;
};
class )" << lexer << R"( {
@@ -71,21 +70,29 @@
void start(skstd::string_view text) {
fText = text;
fOffset = 0;
+ fLine = 1;
}
)" << token << R"( next();
- int32_t getCheckpoint() const {
- return fOffset;
+ struct Checkpoint {
+ int32_t fOffset;
+ int32_t fLine;
+ };
+
+ Checkpoint getCheckpoint() const {
+ return {fOffset, fLine};
}
- void rewindToCheckpoint(int32_t checkpoint) {
- fOffset = checkpoint;
+ void rewindToCheckpoint(Checkpoint checkpoint) {
+ fOffset = checkpoint.fOffset;
+ fLine = checkpoint.fLine;
}
private:
skstd::string_view fText;
int32_t fOffset;
+ int32_t fLine;
};
} // namespace
@@ -154,13 +161,13 @@
// a bit.
int32_t startOffset = fOffset;
if (startOffset == (int32_t)fText.length()) {
- return )" << token << "(" << token << R"(::Kind::TK_END_OF_FILE, startOffset, 0);
+ return )" << token << "(" << token << R"(::Kind::TK_END_OF_FILE, startOffset, 0, fLine);
}
State state = 1;
for (;;) {
if (fOffset >= (int32_t)fText.length()) {
if (kAccepts[state] == -1) {
- return Token(Token::Kind::TK_END_OF_FILE, startOffset, 0);
+ return Token(Token::Kind::TK_END_OF_FILE, startOffset, 0, fLine);
}
break;
}
@@ -174,9 +181,12 @@
}
state = newState;
++fOffset;
+ if (c == '\n') {
+ ++fLine;
+ }
}
Token::Kind kind = ()" << token << R"(::Kind) kAccepts[state];
- return )" << token << R"((kind, startOffset, fOffset - startOffset);
+ return )" << token << R"((kind, startOffset, fOffset - startOffset, fLine);
}
} // namespace
diff --git a/tests/sksl/shared/StructMaxDepth.asm.frag b/tests/sksl/shared/StructMaxDepth.asm.frag
index 2df0733..06d568d 100644
--- a/tests/sksl/shared/StructMaxDepth.asm.frag
+++ b/tests/sksl/shared/StructMaxDepth.asm.frag
@@ -1,4 +1,4 @@
### Compilation failed:
-error: 1: program does not contain a main() function
+error: program does not contain a main() function
1 error