errors.rs 3.2 KB

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