diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index 8c7b43e72..63446247d 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -477,10 +477,28 @@ struct IDLOptions { // This encapsulates where the parser is in the current source file. struct ParserState { - ParserState() : cursor_(nullptr), line_(1), token_(-1) {} + ParserState() + : cursor_(nullptr), line_start_(nullptr), line_(0), token_(-1) {} protected: + void ResetState(const char *source) { + cursor_ = source; + line_ = 0; + MarkNewLine(); + } + + void MarkNewLine() { + line_start_ = cursor_; + line_ += 1; + } + + int64_t CursorPosition() const { + FLATBUFFERS_ASSERT(cursor_ && line_start_ && cursor_ >= line_start_); + return static_cast(cursor_ - line_start_); + } + const char *cursor_; + const char *line_start_; int line_; // the current line being parsed int token_; diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index d10a2e7e9..518ef7b82 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -94,11 +94,12 @@ std::string MakeCamel(const std::string &in, bool first) { void Parser::Message(const std::string &msg) { error_ = file_being_parsed_.length() ? AbsolutePath(file_being_parsed_) : ""; // clang-format off - #ifdef _WIN32 - error_ += "(" + NumToString(line_) + ")"; // MSVC alike - #else + #ifdef _WIN32 // MSVC alike + error_ += + "(" + NumToString(line_) + ", " + NumToString(CursorPosition()) + ")"; + #else // gcc alike if (file_being_parsed_.length()) error_ += ":"; - error_ += NumToString(line_) + ":0"; // gcc alike + error_ += NumToString(line_) + ": " + NumToString(CursorPosition()); #endif // clang-format on error_ += ": " + msg; @@ -280,7 +281,7 @@ CheckedError Parser::Next() { case '\r': case '\t': break; case '\n': - line_++; + MarkNewLine(); seen_newline = true; break; case '{': @@ -420,7 +421,7 @@ CheckedError Parser::Next() { cursor_++; // TODO: make nested. while (*cursor_ != '*' || cursor_[1] != '/') { - if (*cursor_ == '\n') line_++; + if (*cursor_ == '\n') MarkNewLine(); if (!*cursor_) return Error("end of file in comment"); cursor_++; } @@ -2259,8 +2260,8 @@ bool Parser::Parse(const char *source, const char **include_paths, CheckedError Parser::StartParseFile(const char *source, const char *source_filename) { file_being_parsed_ = source_filename ? source_filename : ""; - source_ = cursor_ = source; - line_ = 1; + source_ = source; + ResetState(source_); error_.clear(); ECHECK(SkipByteOrderMark()); NEXT();