1use crate::parser::ParserNode;
2use idris::Idris;
3
4#[derive(Debug, Clone)]
6pub enum ParserError {
7 UnexpectedToken {
8 found: FoundToken,
9 expecting: Vec<PossibleExpectedToken>,
10 },
11 FailedToApplyRule {
12 merge_error: &'static str,
13 for_rule: crate::parser::rules::ParserRuleDeclarationLocation,
14 },
15 InvalidEarleyTable, AmbiguousCandidates, }
18
19impl ParserError {
20 pub(super) fn from_earley_table(table: &super::EarleyTable, tokens: &[crate::lexer::tokens::Token]) -> Self {
21 let error_row = table.table.iter().enumerate().rev().find(|(_, row)| !row.is_empty());
22 let (stuck_index, last_non_empty_row) = match error_row {
23 Some(error) => error,
24 None => return Self::InvalidEarleyTable,
25 };
26
27 let stuck_on_token = match tokens.get(stuck_index) {
28 Some(token) => FoundToken {
29 name: ParserNode::name_from_id(ParserNode::from(token.clone()).id()),
30 #[cfg(feature = "spanned_tree")]
31 position: token.span().start,
32 #[cfg(feature = "spanned_tree")]
33 length: token.span().end - token.span().start,
34 },
35 None => FoundToken {
36 name: "EOF",
37 #[cfg(feature = "spanned_tree")]
38 position: match tokens.last() {
39 Some(last) => last.span().end,
40 None => 0,
41 },
42 #[cfg(feature = "spanned_tree")]
43 length: 0,
44 },
45 };
46
47 let mut expecting = std::collections::HashSet::new();
49 for (expecting_token, for_nodes) in last_non_empty_row.uncompleted_items.iter() {
50 use idris::Idris;
52 if *expecting_token < crate::lexer::tokens::Token::COUNT {
53 expecting.insert(PossibleExpectedToken {
54 expected: *expecting_token,
55 for_nodes: for_nodes
56 .iter()
57 .map(|item| (item.rule.merged, item.rule.creation_loc.clone()))
58 .collect(),
59 });
60 }
61 }
62
63 Self::UnexpectedToken {
64 found: stuck_on_token,
65 expecting: expecting.into_iter().collect(),
66 }
67 }
68}
69
70impl std::fmt::Display for ParserError {
71 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
72 match self {
73 Self::UnexpectedToken { found, expecting } => {
74 #[cfg(feature = "spanned_tree")]
75 write!(
76 f,
77 "Unexpected token at position {}, length {}: \"{}\"",
78 found.position, found.length, found.name,
79 )?;
80 #[cfg(not(feature = "spanned_tree"))]
81 write!(f, "Unexpected token: \"{}\"", found.name,)?;
82 if !expecting.is_empty() {
83 write!(f, "\nExpecting one of:")?;
84 for expecting in expecting.iter().take(10) {
85 let node_name = <ParserNode as idris::Idris>::name_from_id(expecting.expected);
86 write!(f, "\n - token \"{node_name}\" to create nodes")?;
87 for (i, (for_node, for_rule)) in expecting.for_nodes.iter().take(3).enumerate() {
88 let node_name = <ParserNode as idris::Idris>::name_from_id(*for_node);
89 if i == 0 {
90 write!(f, " \"{node_name}\" (at {for_rule})")?;
91 } else {
92 write!(f, ", \"{node_name}\" (at {for_rule})")?;
93 }
94 }
95 if expecting.for_nodes.len() > 3 {
96 write!(f, "And {} others", expecting.for_nodes.len() - 10)?;
97 }
98 }
99 if expecting.len() > 10 {
100 write!(f, "\nAnd {} others", expecting.len() - 10)?;
101 }
102 } else {
103 write!(f, "\nNo tokens were expected !")?;
104 }
105 }
106 Self::FailedToApplyRule { merge_error, for_rule } => {
107 write!(f, "Failed to use rule (declared at: {}): {}", for_rule, merge_error)?;
108 }
109 Self::InvalidEarleyTable => write!(f, "Empty Earley table !")?,
110 Self::AmbiguousCandidates => write!(f, "Multiple candidates for rule completion !")?,
111 }
112
113 Ok(())
114 }
115}
116
117impl std::error::Error for ParserError {}
118
119#[derive(Debug, Clone, PartialEq, Eq, Hash)]
120pub struct PossibleExpectedToken {
121 pub expected: usize,
122 pub for_nodes: Vec<(usize, crate::parser::rules::ParserRuleDeclarationLocation)>,
123}
124
125#[derive(Debug, Clone, PartialEq, Eq, Hash)]
126pub struct FoundToken {
127 pub name: &'static str,
128 #[cfg(feature = "spanned_tree")]
129 pub position: usize,
130 #[cfg(feature = "spanned_tree")]
131 pub length: usize,
132}