Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Pass more information in user defined parse error
  • Loading branch information
palaviv committed Jul 5, 2019
commit ef1d5433df31a3c4ba7e58250b75de85ca76eaa1
5 changes: 4 additions & 1 deletion compiler/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@ impl fmt::Display for CompileError {
}?;

// Print line number:
write!(f, " at line {:?}", self.location.row())
match &self.error {
CompileErrorType::Parse(..) => Ok(()),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. This exception for the parse error is not ideal, but we can improve on this later.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please implement the todo at this line:

location: Default::default(), // TODO: extract location from parse error!

Then we have proper locations on all compiler errors (where possible).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

_ => write!(f, " at line {:?}", self.location.row()),
}
}
}

Expand Down
8 changes: 3 additions & 5 deletions parser/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub enum ParseError {
/// Parser encountered an unexpected token
UnrecognizedToken(TokSpan, Vec<String>),
/// Maps to `User` type from `lalrpop-util`
Other,
Other(LexicalError),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be good to rename this error variant into Lexical(LexicalError).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}

/// Convert `lalrpop_util::ParseError` to our internal type
Expand All @@ -34,8 +34,7 @@ impl From<InnerError<Location, Tok, LexicalError>> for ParseError {
// TODO: Are there cases where this isn't an EOF?
InnerError::InvalidToken { location } => ParseError::EOF(Some(location)),
InnerError::ExtraToken { token } => ParseError::ExtraToken(token),
// Inner field is a unit-like enum `LexicalError::StringError` with no useful info
InnerError::User { .. } => ParseError::Other,
InnerError::User { error } => ParseError::Other(error),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very good to propagate the lexer errors!

InnerError::UnrecognizedToken { token, expected } => {
match token {
Some(tok) => ParseError::UnrecognizedToken(tok, expected),
Expand Down Expand Up @@ -66,8 +65,7 @@ impl fmt::Display for ParseError {
ParseError::UnrecognizedToken(ref t_span, _) => {
write!(f, "Got unexpected token: {:?} at {:?}", t_span.1, t_span.0)
}
// This is user defined, it probably means a more useful error should have been given upstream.
ParseError::Other => write!(f, "Got unsupported token(s)"),
ParseError::Other(ref error) => write!(f, "{}", error),
}
}
}
Expand Down
25 changes: 23 additions & 2 deletions parser/src/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use num_traits::Num;
use serde::{Deserialize, Serialize};
use std::cmp::Ordering;
use std::collections::HashMap;
use std::fmt;
use std::str::FromStr;
use unic_emoji_char::is_emoji_presentation;
use unicode_xid::UnicodeXID;
Expand Down Expand Up @@ -59,13 +60,13 @@ pub struct Lexer<T: Iterator<Item = char>> {
keywords: HashMap<String, Tok>,
}

#[derive(Debug)]
#[derive(Debug, PartialEq)]
pub struct LexicalError {
pub error: LexicalErrorType,
pub location: Location,
}

#[derive(Debug)]
#[derive(Debug, PartialEq)]
pub enum LexicalErrorType {
StringError,
UnicodeError,
Expand All @@ -74,6 +75,26 @@ pub enum LexicalErrorType {
OtherError(String),
}

impl fmt::Display for LexicalError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.error {
LexicalErrorType::StringError => write!(f, "Got unexpected string"),
LexicalErrorType::UnicodeError => write!(f, "Got unexpected unicode"),
LexicalErrorType::NestingError => write!(f, "Got unexpected nesting"),
LexicalErrorType::UnrecognizedToken { tok } => {
write!(f, "Got unexpected token {}", tok)
}
LexicalErrorType::OtherError(ref msg) => write!(f, "{}", msg),
}?;
write!(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to add the line and column info later on, so in the Display method of the CompilerError struct.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

f,
" at line {} column {}",
self.location.row(),
self.location.column()
)
}
}

#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct Location {
row: usize,
Expand Down