errors.rs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. use crate::core::{FileRef, Loc, Span};
  2. use crate::lexer;
  3. #[derive(Debug)]
  4. pub struct MatzoError {
  5. pub message: String,
  6. pub loc: Loc,
  7. pub context: Vec<ContextLine>,
  8. }
  9. #[derive(Debug)]
  10. pub struct ContextLine {
  11. pub message: String,
  12. pub loc: Loc,
  13. }
  14. impl MatzoError {
  15. pub fn new(loc: Loc, message: String) -> MatzoError {
  16. MatzoError {
  17. message,
  18. loc,
  19. context: Vec::new(),
  20. }
  21. }
  22. pub fn reposition(mut self, loc: Loc) -> MatzoError {
  23. self.loc = loc;
  24. self
  25. }
  26. fn format_expected_list(expected: Vec<String>) -> String {
  27. if expected.len() == 1 {
  28. expected[0].to_string()
  29. } else {
  30. let mut expected_list = String::new();
  31. let num = expected.len();
  32. for (i, exp) in expected.iter().enumerate() {
  33. if i > 0 {
  34. expected_list.push_str(", ");
  35. }
  36. if i + 1 == num {
  37. expected_list.push_str("or ");
  38. }
  39. expected_list.push_str(exp);
  40. }
  41. expected_list
  42. }
  43. }
  44. pub fn from_parse_error(
  45. file: FileRef,
  46. err: lalrpop_util::ParseError<usize, lexer::Token, lexer::LexerError>,
  47. ) -> Self {
  48. match err {
  49. lalrpop_util::ParseError::User { error } => {
  50. MatzoError::new(Loc { span: error.range, file }, "Unrecognized token".to_string())
  51. }
  52. lalrpop_util::ParseError::UnrecognizedToken {
  53. token: (start, tok, end),
  54. expected,
  55. } => {
  56. let span = Span {
  57. start: start as u32,
  58. end: end as u32,
  59. };
  60. let expected = MatzoError::format_expected_list(expected);
  61. MatzoError::new(
  62. Loc { span, file },
  63. format!("Unexpected {}. Expected {}", tok.token_name(), expected),
  64. )
  65. }
  66. lalrpop_util::ParseError::UnrecognizedEOF { location, expected } => {
  67. let span = Span {
  68. start: location as u32 - 1,
  69. end: location as u32,
  70. };
  71. let expected = MatzoError::format_expected_list(expected);
  72. MatzoError::new(
  73. Loc { span, file },
  74. format!("Unexpected end-of-file; expected {}", expected),
  75. )
  76. }
  77. lalrpop_util::ParseError::InvalidToken { .. } => {
  78. panic!("Unexpected `InvalidToken`")
  79. }
  80. lalrpop_util::ParseError::ExtraToken {
  81. token: (start, tok, end),
  82. } => {
  83. let span = Span {
  84. start: start as u32,
  85. end: end as u32,
  86. };
  87. MatzoError::new(Loc { span, file }, format!("Extra token {}", tok.token_name()))
  88. }
  89. }
  90. }
  91. }
  92. impl std::fmt::Display for MatzoError {
  93. fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
  94. write!(f, "MatzoError {{ .. }}")
  95. }
  96. }
  97. impl std::error::Error for MatzoError {}