errors.rs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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 } => MatzoError::new(
  50. Loc {
  51. span: error.range,
  52. file,
  53. },
  54. "Unrecognized token".to_string(),
  55. ),
  56. lalrpop_util::ParseError::UnrecognizedToken {
  57. token: (start, tok, end),
  58. expected,
  59. } => {
  60. let span = Span {
  61. start: start as u32,
  62. end: end as u32,
  63. };
  64. let expected = MatzoError::format_expected_list(expected);
  65. MatzoError::new(
  66. Loc { span, file },
  67. format!("Unexpected {}. Expected {}", tok.token_name(), expected),
  68. )
  69. }
  70. lalrpop_util::ParseError::UnrecognizedEOF { location, expected } => {
  71. let span = Span {
  72. start: location as u32 - 1,
  73. end: location as u32,
  74. };
  75. let expected = MatzoError::format_expected_list(expected);
  76. MatzoError::new(
  77. Loc { span, file },
  78. format!("Unexpected end-of-file; expected {}", expected),
  79. )
  80. }
  81. lalrpop_util::ParseError::InvalidToken { .. } => {
  82. panic!("Unexpected `InvalidToken`")
  83. }
  84. lalrpop_util::ParseError::ExtraToken {
  85. token: (start, tok, end),
  86. } => {
  87. let span = Span {
  88. start: start as u32,
  89. end: end as u32,
  90. };
  91. MatzoError::new(
  92. Loc { span, file },
  93. format!("Extra token {}", tok.token_name()),
  94. )
  95. }
  96. }
  97. }
  98. }
  99. impl std::fmt::Display for MatzoError {
  100. fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
  101. write!(f, "MatzoError {{ .. }}")
  102. }
  103. }
  104. impl std::error::Error for MatzoError {}