1use core::fmt;
8
9#[derive(Debug, Clone, PartialEq, Eq)]
11#[non_exhaustive]
12pub enum ParseErrorKind {
13 Empty,
15 UnexpectedChar(char),
17 UnexpectedEnd,
19 UnknownElement(String),
21 BadBracketAtom(&'static str),
23 UnbalancedParen,
25 EmptyBranch,
27 UnclosedRingBond(u32),
29 RingBondToSelf(u32),
31 DuplicateRingBond(u32),
33 ConflictingRingBondOrder(u32),
35 DanglingBond,
37 NumberOverflow,
39 StereoPermOutOfRange {
41 geometry: &'static str,
43 got: u32,
45 max: u32,
47 },
48}
49
50impl fmt::Display for ParseErrorKind {
51 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52 match self {
53 Self::Empty => write!(f, "空的 SMILES"),
54 Self::UnexpectedChar(c) => write!(f, "意外的字符 {c:?}"),
55 Self::UnexpectedEnd => write!(f, "输入意外结束"),
56 Self::UnknownElement(s) => write!(f, "无法识别的元素符号 {s:?}"),
57 Self::BadBracketAtom(why) => write!(f, "方括号原子语法错误:{why}"),
58 Self::UnbalancedParen => write!(f, "括号不匹配"),
59 Self::EmptyBranch => write!(f, "空的分支"),
60 Self::UnclosedRingBond(n) => write!(f, "环闭合标号 {n} 未配对"),
61 Self::RingBondToSelf(n) => write!(f, "环闭合标号 {n} 的两端是同一个原子"),
62 Self::DuplicateRingBond(n) => write!(f, "环闭合标号 {n} 在同一对原子间重复"),
63 Self::ConflictingRingBondOrder(n) => {
64 write!(f, "环闭合标号 {n} 的两端指定了冲突的键级")
65 }
66 Self::DanglingBond => write!(f, "键符号后面缺少原子"),
67 Self::NumberOverflow => write!(f, "数值超出范围"),
68 Self::StereoPermOutOfRange { geometry, got, max } => write!(
69 f,
70 "立体标记 @{geometry}{got} 的序号超出范围,@{geometry} 最大为 {max}"
71 ),
72 }
73 }
74}
75
76#[derive(Debug, Clone, PartialEq, Eq)]
78pub struct ParseError {
79 pub kind: ParseErrorKind,
81 pub pos: usize,
83 pub input: String,
85}
86
87impl ParseError {
88 pub(crate) fn new(kind: ParseErrorKind, pos: usize, input: &[u8]) -> Self {
89 Self {
90 kind,
91 pos,
92 input: String::from_utf8_lossy(input).into_owned(),
93 }
94 }
95
96 #[must_use]
103 pub fn render(&self) -> String {
104 let cols = self.input[..self.pos.min(self.input.len())].chars().count();
106 format!("{}\n{}^ {}", self.input, " ".repeat(cols), self.kind)
107 }
108}
109
110impl fmt::Display for ParseError {
111 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112 write!(f, "第 {} 字符处:{}", self.pos, self.kind)
113 }
114}
115
116impl std::error::Error for ParseError {}
117
118pub type Result<T> = core::result::Result<T, ParseError>;