| //! Rust parser based on the Reference grammar. | |
| use std::ops::Range; | |
| use std::str::FromStr; | |
| pub mod coverage; | |
| pub mod lexer; | |
| mod parser; | |
| pub mod tree; | |
| #[derive(Clone, Debug)] | |
| pub struct ParseError { | |
| pub byte_offset: usize, | |
| pub message: String, | |
| } | |
| impl ParseError { | |
| pub fn display(&self, src: &str) -> String { | |
| let s = &src[self.byte_offset..]; | |
| match s.char_indices().nth(100) { | |
| Some((i, _)) => format!("{} at `{}…`", self.message, &s[..i]), | |
| None => format!("{} at `{s}`", self.message), | |
| } | |
| } | |
| } | |
| #[derive(Clone, Copy, PartialEq, PartialOrd, Debug, Eq)] | |
| pub enum Edition { | |
| Edition2015, | |
| Edition2018, | |
| Edition2021, | |
| Edition2024, | |
| } | |
| impl FromStr for Edition { | |
| type Err = (); | |
| fn from_str(s: &str) -> Result<Self, ()> { | |
| match s { | |
| "2015" => Ok(Edition::Edition2015), | |
| "2018" => Ok(Edition::Edition2018), | |
| "2021" => Ok(Edition::Edition2021), | |
| "2024" => Ok(Edition::Edition2024), | |
| _ => Err(()), | |
| } | |
| } | |
| } | |
| /// A parsed section of source corresponding to some grammar expression. | |
| #[derive(Clone, Debug, Default)] | |
| pub struct Node { | |
| pub name: String, | |
| /// Range in bytes of the original source that this node covers. | |
| pub range: Range<usize>, | |
| pub children: Nodes, | |
| } | |
| impl Node { | |
| pub fn new(name: String, range: Range<usize>) -> Node { | |
| Node { | |
| name, | |
| range, | |
| children: Nodes::default(), | |
| } | |
| } | |
| /// Returns a new `Node` with the given children. | |
| fn with_children(name: String, start: usize, children: Nodes) -> Node { | |
| let range = if children.0.is_empty() { | |
| Range { start, end: start } | |
| } else { | |
| Range { | |
| start: children.0.first().unwrap().range.start, | |
| end: children.0.last().unwrap().range.end, | |
| } | |
| }; | |
| Node { | |
| name, | |
| range, | |
| children, | |
| } | |
| } | |
| /// Length in bytes of this node. | |
| fn byte_len(&self) -> usize { | |
| self.range.end - self.range.start | |
| } | |
| } | |
| /// Abstraction over a sequence of nodes. | |
| #[derive(Clone, Debug, Default)] | |
| pub struct Nodes(pub Vec<Node>); | |
| impl Nodes { | |
| fn new(name: String, range: Range<usize>) -> Nodes { | |
| let node = Node { | |
| name, | |
| range, | |
| children: Nodes::default(), | |
| }; | |
| Nodes(vec![node]) | |
| } | |
| /// Converts this `Nodes` to one with a single `Node`. | |
| fn wrap(self, name: String, start: usize) -> Nodes { | |
| Nodes(vec![Node::with_children(name.to_string(), start, self)]) | |
| } | |
| fn extend(&mut self, other: Nodes) { | |
| self.0.extend(other.0) | |
| } | |
| fn byte_len(&self) -> usize { | |
| if self.0.is_empty() { | |
| 0 | |
| } else { | |
| self.0.last().unwrap().range.end - self.0.first().unwrap().range.start | |
| } | |
| } | |
| } |