Skip to content

Commit

Permalink
Use same format for parser errors as for evaluation errors (bug #45967).
Browse files Browse the repository at this point in the history
* oct-parse.yy (get_file_line): Delete unused function.
* oct-parse.yy (bison_error): New variable "in_file" to track whether parser is
in a file or at the command line.  Change format of output message when in
a file to match that of an evaluation error.  When at the command line,
also print out the line of code that was incorrect and point to the error.
  • Loading branch information
Rik committed Jan 17, 2024
1 parent 3c9c7f5 commit eebbfe1
Showing 1 changed file with 30 additions and 63 deletions.
93 changes: 30 additions & 63 deletions libinterp/parse-tree/oct-parse.yy
Original file line number Diff line number Diff line change
Expand Up @@ -5498,34 +5498,6 @@ OCTAVE_BEGIN_NAMESPACE(octave)
m_lexer.m_allow_command_syntax = false;
}

// FIXME: this function partially duplicates do_dbtype in debug.cc.
static std::string
get_file_line (const std::string& name, int line)
{
// NAME should be an absolute file name and the file should exist.

std::ifstream fs = sys::ifstream (name.c_str (), std::ios::in);

std::string text;

if (fs)
{
int i = 1;

do
{
if (! std::getline (fs, text))
{
text = "";
break;
}
}
while (i++ < line);
}

return text;
}

void
base_parser::bison_error (const std::string& str)
{
Expand All @@ -5543,56 +5515,51 @@ OCTAVE_BEGIN_NAMESPACE(octave)
{
std::ostringstream output_buf;

if (m_lexer.m_reading_fcn_file || m_lexer.m_reading_script_file
|| m_lexer.m_reading_classdef_file)
output_buf << "parse error near line " << err_line
<< " of file " << m_lexer.m_fcn_file_full_name;
else
output_buf << "parse error:";

if (str != "parse error")
output_buf << "\n\n " << str;

output_buf << "\n\n";

std::string curr_line;

if (m_lexer.m_reading_fcn_file || m_lexer.m_reading_script_file
|| m_lexer.m_reading_classdef_file)
curr_line = get_file_line (m_lexer.m_fcn_file_full_name, err_line);
else
curr_line = m_lexer.m_current_input_line;
bool in_file = (m_lexer.m_reading_fcn_file || m_lexer.m_reading_script_file
|| m_lexer.m_reading_classdef_file);

// Adjust the error column for display because it is 1-based in the
// lexer for easier reporting.
err_col--;

if (! curr_line.empty ())
if (in_file)
{
// FIXME: we could do better if we just cached lines from the
// input file in a list. See also functions for managing input
// buffers in lex.ll.
output_buf << str
<< " near line " << err_line << ", column " << err_col << "\n"
<< "error: called from\n"
<< " " << m_lexer.m_fcn_file_name
<< " at line " << err_line << " column " << err_col << "\n";
}
else
{
// On command line, point directly to error
output_buf << str << "\n\n";
std::string curr_line = m_lexer.m_current_input_line;

std::size_t len = curr_line.length ();
if (! curr_line.empty ())
{
// FIXME: we could do better if we just cached lines from the
// input file in a list. See also functions for managing input
// buffers in lex.ll.
std::size_t len = curr_line.length ();

if (curr_line[len-1] == '\n')
curr_line.resize (len-1);
if (curr_line[len-1] == '\n')
curr_line.resize (len-1);

// Print the line, maybe with a pointer near the error token.
// Print the line, maybe with a pointer near the error token.
output_buf << ">>> " << curr_line << "\n";

output_buf << ">>> " << curr_line << "\n";
if (err_col == 0)
err_col = len;

if (err_col == 0)
err_col = len;
for (int i = 0; i < err_col + 3; i++)
output_buf << " ";

for (int i = 0; i < err_col + 3; i++)
output_buf << " ";
output_buf << "^" << "\n";
}

output_buf << "^";
}

output_buf << "\n";

m_parse_error_msg = output_buf.str ();
}

Expand Down

0 comments on commit eebbfe1

Please sign in to comment.