Rewrote the parser

This commit is contained in:
Jesse Braham 2024-12-24 09:02:18 +01:00
parent 96d1311e09
commit 88912bfa39
4 changed files with 335 additions and 289 deletions

View File

@ -59,6 +59,12 @@ impl<'lexer> Lexer<'lexer> {
Span::new(self.byte..self.byte, self.source.clone()) Span::new(self.byte..self.byte, self.source.clone())
} }
/// Returns `true` when at the end of the input.
#[must_use]
pub(crate) fn eof(&self) -> bool {
self.peek(0).is_none()
}
/// Get the current character. /// Get the current character.
#[must_use] #[must_use]
fn current(&self) -> Option<char> { fn current(&self) -> Option<char> {

View File

@ -4,9 +4,123 @@ use crate::{
span::Span, span::Span,
}; };
/// Abstract Syntax Tree (AST).
#[derive(Debug, Default, Clone, PartialEq)]
pub(crate) struct Ast {
root: Vec<Node>,
}
impl Ast {
/// Construct a new instance of `Ast`.
#[must_use]
pub(crate) fn new(root: Vec<Node>) -> Self {
Self { root }
}
}
impl From<Vec<Node>> for Ast {
fn from(root: Vec<Node>) -> Self {
Self { root }
}
}
#[cfg(not(tarpaulin_include))]
impl std::fmt::Display for Ast {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for node in &self.root {
write!(f, "{node}\n")?;
}
Ok(())
}
}
/// A node in the Abstract Syntax Tree (AST).
///
/// `Nodes`s contain the kind of node which was found, as well as a [Span]
/// specifying the [Source] and [Location] of the node.
///
/// [Source]: crate::span::Source
/// [Location]: crate::span::Location
#[derive(Debug, Clone, PartialEq)]
pub(crate) struct Node {
/// The kind of node.
pub kind: Expr,
/// The span in which the node occurs.
pub span: Span,
}
impl Node {
/// Construct a new instance of `Node`.
#[must_use]
pub(crate) fn new(kind: Expr, span: Span) -> Self {
Self { kind, span }
}
/// Push a child node onto a list node.
pub(crate) fn push_node(&mut self, child: Self) -> Result<(), ParserError> {
match &mut self.kind {
Expr::List(vec) | Expr::Map(vec) | Expr::Set(vec) | Expr::Vector(vec) => {
vec.push(child);
}
_ => {
// FIXME
// return Err(ParserError::new(
// ParserErrorKind::UnexpectedState,
// child.span,
// ))
todo!()
}
}
Ok(())
}
#[cfg(not(tarpaulin_include))]
#[must_use]
fn display(&self, indent: usize) -> String {
let mut text = format!(
"{}{}@{}..{}\n",
" ".repeat(indent),
self.kind,
self.span.bytes().start,
self.span.bytes().end
);
match &self.kind {
Expr::Atom(_) => {}
Expr::List(vec) | Expr::Map(vec) | Expr::Set(vec) | Expr::Vector(vec) => {
for node in vec {
text.push_str(&format!("{}\n", node.display(indent + 1)));
}
}
}
text.trim_end().to_string()
}
}
impl TryFrom<Token> for Node {
type Error = ParserError;
fn try_from(token: Token) -> Result<Self, Self::Error> {
let span = token.span.clone();
let kind = Expr::try_from(token)?;
Ok(Self::new(kind, span))
}
}
#[cfg(not(tarpaulin_include))]
impl std::fmt::Display for Node {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.display(0))
}
}
/// An atomic value. /// An atomic value.
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum Atom { pub(crate) enum Atom {
/// Boolean, e.g. `true`, `false` /// Boolean, e.g. `true`, `false`
Bool(bool), Bool(bool),
/// Character, e.g. `'c'`, `'\n'` /// Character, e.g. `'c'`, `'\n'`
@ -45,7 +159,7 @@ impl std::fmt::Display for Atom {
/// An expression. /// An expression.
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum NodeKind { pub(crate) enum Expr {
/// An atomic value. /// An atomic value.
Atom(Atom), Atom(Atom),
/// A list of nodes. /// A list of nodes.
@ -58,13 +172,25 @@ pub enum NodeKind {
Vector(Vec<Node>), Vector(Vec<Node>),
} }
impl From<Atom> for NodeKind { impl Expr {
/// Which closing delimiter is associated with the expression kind?
pub(crate) fn closing_delimiter(&self) -> Option<TokenKind> {
match self {
Expr::List(_) => Some(TokenKind::CloseParen),
Expr::Map(_) | Expr::Set(_) => Some(TokenKind::CloseBrace),
Expr::Vector(_) => Some(TokenKind::CloseBracket),
_ => None,
}
}
}
impl From<Atom> for Expr {
fn from(atom: Atom) -> Self { fn from(atom: Atom) -> Self {
Self::Atom(atom) Self::Atom(atom)
} }
} }
impl TryFrom<Token> for NodeKind { impl TryFrom<Token> for Expr {
type Error = ParserError; type Error = ParserError;
fn try_from(token: Token) -> Result<Self, Self::Error> { fn try_from(token: Token) -> Result<Self, Self::Error> {
@ -78,10 +204,12 @@ impl TryFrom<Token> for NodeKind {
TokenKind::Symbol(s) => Atom::Symbol(s), TokenKind::Symbol(s) => Atom::Symbol(s),
TokenKind::Nil => Atom::Nil, TokenKind::Nil => Atom::Nil,
_ => { _ => {
return Err(ParserError::new( // FIXME
ParserErrorKind::UnexpectedState, // return Err(ParserError::new(
token.span, // ParserErrorKind::UnexpectedState,
)) // token.span,
// ))
todo!()
} }
}; };
@ -90,9 +218,9 @@ impl TryFrom<Token> for NodeKind {
} }
#[cfg(not(tarpaulin_include))] #[cfg(not(tarpaulin_include))]
impl std::fmt::Display for NodeKind { impl std::fmt::Display for Expr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use NodeKind::*; use Expr::*;
match self { match self {
Atom(atom) => write!(f, "{atom}"), Atom(atom) => write!(f, "{atom}"),
@ -103,89 +231,3 @@ impl std::fmt::Display for NodeKind {
} }
} }
} }
/// A node in the Abstract Syntax Tree (AST).
///
/// `Nodes`s contain the kind of node which was found, as well as a [Span]
/// specifying the [Source] and [Location] of the node.
///
/// [Source]: crate::span::Source
/// [Location]: crate::span::Location
#[derive(Debug, Clone, PartialEq)]
pub struct Node {
/// The kind of node.
pub kind: NodeKind,
/// The span in which the node occurs.
pub span: Span,
}
impl Node {
/// Construct a new instance of `Node`.
#[must_use]
pub const fn new(kind: NodeKind, span: Span) -> Self {
Self { kind, span }
}
/// Push a child node onto a list node.
pub fn push_node(&mut self, child: Self) -> Result<(), ParserError> {
match &mut self.kind {
NodeKind::List(vec)
| NodeKind::Map(vec)
| NodeKind::Set(vec)
| NodeKind::Vector(vec) => {
vec.push(child);
}
_ => {
return Err(ParserError::new(
ParserErrorKind::UnexpectedState,
child.span,
))
}
}
Ok(())
}
#[cfg(not(tarpaulin_include))]
fn display(&self, indent: usize) -> String {
let mut text = format!(
"{}{}@{}..{}\n",
" ".repeat(indent),
self.kind,
self.span.bytes().start,
self.span.bytes().end
);
match &self.kind {
NodeKind::Atom(_) => {}
NodeKind::List(vec)
| NodeKind::Map(vec)
| NodeKind::Set(vec)
| NodeKind::Vector(vec) => {
for node in vec {
text.push_str(&format!("{}\n", node.display(indent + 1)));
}
}
}
text.trim_end().to_string()
}
}
impl TryFrom<Token> for Node {
type Error = ParserError;
fn try_from(token: Token) -> Result<Self, Self::Error> {
let span = token.span.clone();
let kind = NodeKind::try_from(token)?;
Ok(Self::new(kind, span))
}
}
#[cfg(not(tarpaulin_include))]
impl std::fmt::Display for Node {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.display(0))
}
}

View File

@ -5,19 +5,16 @@ use crate::{lexer::LexerError, span::Span};
pub enum ParserErrorKind { pub enum ParserErrorKind {
/// An error which ocurred during lexical analysis. /// An error which ocurred during lexical analysis.
Lexer(LexerError), Lexer(LexerError),
/// Expected a value for key in map, but no value was found. /// Key in map is missing its corresponding value.
MissingValueInMap, MissingValueInMap,
/// An unexpecting closing parenthesis/brace/bracket was encountered. /// Opening delimiter does not have a matching closing delimiter.
UnexpectedCloseBracket, UnclosedSequence,
/// Unexpectedly reached the end of the input. /// An unexpected closing delimiter was found.
UnexpectedClosingDelimiter,
/// Unexpectedly reached end of input.
UnexpectedEof, UnexpectedEof,
/// Unexpected parser state reached. /// An unmatched closing delimiter was found.
UnexpectedState, UnmatchedClosingDelimiter,
/// Opening parenthesis/brace/bracket does not have a matching closing
/// parenthesis/brace/bracket.
UnclosedBracket,
/// An unmatched parenthesis/brace/bracket was encountered.
UnmatchedBracket,
} }
/// Parser error, with a start and end location. /// Parser error, with a start and end location.
@ -30,13 +27,20 @@ pub struct ParserError {
} }
impl ParserError { impl ParserError {
/// Construct a new instance of `ParserErorr`. /// Construct a new instance of `ParserError`.
#[must_use] #[must_use]
pub const fn new(kind: ParserErrorKind, span: Span) -> Self { pub const fn new(kind: ParserErrorKind, span: Span) -> Self {
Self { kind, span } Self { kind, span }
} }
} }
impl From<LexerError> for ParserError {
fn from(err: LexerError) -> Self {
let span = err.span.clone();
Self::new(ParserErrorKind::Lexer(err), span)
}
}
impl std::error::Error for ParserError {} impl std::error::Error for ParserError {}
#[cfg(not(tarpaulin_include))] #[cfg(not(tarpaulin_include))]
@ -46,19 +50,14 @@ impl std::fmt::Display for ParserError {
match &self.kind { match &self.kind {
Lexer(err) => write!(f, "{err}"), Lexer(err) => write!(f, "{err}"),
MissingValueInMap => write!(f, "Key in map is missing its value"), MissingValueInMap => write!(f, "Key in map is missing its corresponding value"),
UnexpectedCloseBracket => write!(f, "Unexpected closing bracket"), UnclosedSequence => write!(
UnexpectedEof => write!(f, "Unexpected reached end of input"), f,
UnexpectedState => write!(f, "Unexpected parsing state reached"), "Opening delimiter does not have a matching closing delimiter"
UnclosedBracket => write!(f, "Unclosed bracket"), ),
UnmatchedBracket => write!(f, "Unmatched bracket"), UnexpectedClosingDelimiter => write!(f, "An unexpected closing delimiter was found"),
UnexpectedEof => write!(f, "Unexpectedly reached end of input"),
UnmatchedClosingDelimiter => write!(f, "An unmatched closing delimiter was found"),
} }
} }
} }
impl From<LexerError> for ParserError {
fn from(err: LexerError) -> Self {
let span = err.span.clone();
Self::new(ParserErrorKind::Lexer(err), span)
}
}

View File

@ -1,153 +1,153 @@
pub use self::{ use self::{
ast::{Ast, Expr, Node},
error::{ParserError, ParserErrorKind}, error::{ParserError, ParserErrorKind},
node::{Node, NodeKind},
}; };
use crate::lexer::{Lexer, TokenKind}; use crate::{
lexer::{Lexer, TokenKind},
span::Span,
};
mod ast;
mod error; mod error;
mod node;
/// Parser for converting Onihime source code into an Abstract Syntax Tree pub(crate) struct Parser<'parser> {
/// (AST).
#[derive(Debug)]
pub struct Parser<'parser> {
lexer: Lexer<'parser>, lexer: Lexer<'parser>,
parents: Vec<Node>,
current: Node,
} }
impl<'parser> Parser<'parser> { impl<'parser> Parser<'parser> {
/// Create a new parser instance from a string. /// Create a new parser instance from a string.
#[must_use] #[must_use]
pub fn new(input: &'parser str) -> Self { pub(crate) fn new(input: &'parser str) -> Self {
let lexer = Lexer::new(input);
let current = Node::new(Expr::List(Vec::new()), lexer.span());
Self { Self {
lexer: Lexer::new(input), lexer,
parents: Vec::new(),
current,
} }
} }
/// Set the name of the lexer's source. /// Set the name of the lexer's source.
pub fn set_name(&mut self, name: String) { pub(crate) fn set_name(&mut self, name: String) {
self.lexer.set_name(name); self.lexer.set_name(name);
} }
/// Parse the input string into an AST. /// Produce an Abstract Syntax Tree (AST) from the source input.
pub fn parse(&mut self) -> Result<Vec<Node>, ParserError> { #[must_use]
let mut parents = Vec::new(); pub(crate) fn parse(mut self) -> Result<Ast, ParserError> {
let mut cur_node = Node::new(NodeKind::List(Vec::new()), self.lexer.span()); // This parser is actually quite simple!Recursively parse expressions until we
// run out of tokens, or an error occurs:
while !self.lexer.eof() {
if let Some(node) = self.expr()? {
self.current.push_node(node);
}
}
while let Some(token) = self.lexer.read()? { // When we reach the end of input, there should be no remaining parent nodes; if
// there are, that means that there is a missing closing delimiter somewhere:
if !self.parents.is_empty() {
return Err(ParserError::new(
ParserErrorKind::UnclosedSequence,
self.current.span,
));
}
// Since we created an initial `Expr::List` node to hold the parsed contents
// (i.e. so that we had something to push nodes to), we can now rip out its guts
// and return the newly constructed AST:
if let Expr::List(root) = self.current.kind {
Ok(Ast::new(root))
} else {
unreachable!() // TODO: Is this really true? It should be... right?
}
}
#[must_use]
fn expr(&mut self) -> Result<Option<Node>, ParserError> {
if let Some(token) = self.lexer.read()? {
match token.kind { match token.kind {
TokenKind::BlockComment(_) | TokenKind::LineComment(_) => {} // Comments are simply ignored by the parser:
TokenKind::BlockComment(_) | TokenKind::LineComment(_) => Ok(None),
TokenKind::OpenParen => { // Any valid opening delimiters begins a new sequence:
let child = Node::new(NodeKind::List(Vec::new()), token.span); TokenKind::OpenParen => self.begin_sequence(Expr::List, token.span),
parents.push(cur_node); TokenKind::OpenHashBrace => self.begin_sequence(Expr::Map, token.span),
cur_node = child; TokenKind::OpenBrace => self.begin_sequence(Expr::Set, token.span),
} TokenKind::OpenBracket => self.begin_sequence(Expr::Vector, token.span),
TokenKind::CloseParen => {
let mut parent = parents.pop().ok_or_else(|| {
ParserError::new(
ParserErrorKind::UnexpectedCloseBracket,
token.span.clone(),
)
})?;
cur_node.span.extend(&token.span); // Any valid closing delimiters end the current sequence:
kind
if !matches!(cur_node.kind, NodeKind::List(_)) { @ (TokenKind::CloseParen | TokenKind::CloseBrace | TokenKind::CloseBracket) => {
return Err(ParserError::new( self.end_sequence(kind, token.span)
ParserErrorKind::UnmatchedBracket,
token.span,
));
}
parent.push_node(cur_node)?;
cur_node = parent;
}
TokenKind::OpenBrace => {
let child = Node::new(NodeKind::Set(Vec::new()), token.span);
parents.push(cur_node);
cur_node = child;
}
TokenKind::OpenHashBrace => {
let child = Node::new(NodeKind::Map(Vec::new()), token.span);
parents.push(cur_node);
cur_node = child;
}
TokenKind::CloseBrace => {
let mut parent = parents.pop().ok_or_else(|| {
ParserError::new(
ParserErrorKind::UnexpectedCloseBracket,
token.span.clone(),
)
})?;
cur_node.span.extend(&token.span);
if !matches!(cur_node.kind, NodeKind::Map(_) | NodeKind::Set(_)) {
return Err(ParserError::new(
ParserErrorKind::UnmatchedBracket,
token.span,
));
}
if let NodeKind::Map(ref vec) = cur_node.kind {
if vec.len() % 2 != 0 {
return Err(ParserError::new(
ParserErrorKind::MissingValueInMap,
token.span,
));
}
}
parent.push_node(cur_node)?;
cur_node = parent;
}
TokenKind::OpenBracket => {
let child = Node::new(NodeKind::Vector(Vec::new()), token.span);
parents.push(cur_node);
cur_node = child;
}
TokenKind::CloseBracket => {
let mut parent = parents.pop().ok_or_else(|| {
ParserError::new(
ParserErrorKind::UnexpectedCloseBracket,
token.span.clone(),
)
})?;
cur_node.span.extend(&token.span);
if !matches!(cur_node.kind, NodeKind::Vector(_)) {
return Err(ParserError::new(
ParserErrorKind::UnmatchedBracket,
token.span,
));
}
parent.push_node(cur_node)?;
cur_node = parent;
} }
// Atoms are pushed to the current sequence:
_ => { _ => {
let node = Node::try_from(token)?; let node = Node::try_from(token)?;
cur_node.push_node(node)?; let span = node.span.clone();
self.current.push_node(node);
self.current.span.extend(&span);
Ok(None)
} }
} }
} else {
Err(ParserError::new(
ParserErrorKind::UnexpectedEof,
self.lexer.span(),
))
}
} }
if !parents.is_empty() { #[must_use]
fn begin_sequence(
&mut self,
init: impl FnOnce(Vec<Node>) -> Expr,
span: Span,
) -> Result<Option<Node>, ParserError> {
self.current.span.extend(&span);
self.parents.push(self.current.clone());
self.current = Node::new(init(Vec::new()), span.clone());
Ok(None)
}
#[must_use]
fn end_sequence(&mut self, kind: TokenKind, span: Span) -> Result<Option<Node>, ParserError> {
// We will ultimately return the current expression, so clone it and update its
// span first:
let mut current = self.current.clone();
current.span.extend(&span);
// Update the parser's current node to the previous parent, or return an error
// if no parents exist:
self.current = self.parents.pop().ok_or_else(|| {
ParserError::new(ParserErrorKind::UnexpectedClosingDelimiter, span.clone())
})?;
// Ensure that the appropriate closing delimiter was found for our current node:
if current.kind.closing_delimiter() != Some(kind) {
return Err(ParserError::new( return Err(ParserError::new(
ParserErrorKind::UnclosedBracket, ParserErrorKind::UnmatchedClosingDelimiter,
cur_node.span, span,
)); ));
} }
if let NodeKind::List(body) = cur_node.kind { // For maps, ensure that each key has a corresponding value:
Ok(body) match current.kind {
} else { Expr::Map(ref vec) if vec.len() % 2 != 0 => {
unreachable!() // In theory, at least... return Err(ParserError::new(ParserErrorKind::MissingValueInMap, span));
} }
_ => {}
}
// Finally, return the current node so it can be added to the AST:
Ok(Some(current))
} }
} }
@ -156,8 +156,7 @@ mod tests {
use super::*; use super::*;
use crate::{ use crate::{
lexer::{LexerError, LexerErrorKind, Symbol}, lexer::{LexerError, LexerErrorKind, Symbol},
parser::node::Atom, parser::ast::Atom,
span::Span,
}; };
macro_rules! test { macro_rules! test {
@ -171,7 +170,7 @@ mod tests {
}; };
} }
test!(empty: "", _src => Ok(vec![])); test!(empty: "", _src => Ok(Ast::default()));
test!(error_invalid_number: "(+ 1.2.3)", src => Err(ParserError::new( test!(error_invalid_number: "(+ 1.2.3)", src => Err(ParserError::new(
ParserErrorKind::Lexer(LexerError::new( ParserErrorKind::Lexer(LexerError::new(
@ -181,35 +180,35 @@ mod tests {
Span::new(3..8, src) Span::new(3..8, src)
))); )));
test!(list: "(+ 1 2) ; sneaky comment :)", src => Ok(vec![ test!(list: "(+ 1 2) ; sneaky comment :)", src => Ok(Ast::from(vec![
Node::new( Node::new(
NodeKind::List(vec![ Expr::List(vec![
Node::new(Atom::Symbol(Symbol::from("+")).into(), Span::new(1..2, src.clone())), Node::new(Atom::Symbol(Symbol::from("+")).into(), Span::new(1..2, src.clone())),
Node::new(Atom::Integer(1).into(), Span::new(3..4, src.clone())), Node::new(Atom::Integer(1).into(), Span::new(3..4, src.clone())),
Node::new(Atom::Integer(2).into(), Span::new(5..6, src.clone())), Node::new(Atom::Integer(2).into(), Span::new(5..6, src.clone())),
]), ]),
Span::new(0..7, src) Span::new(0..7, src)
) )
])); ])));
test!(error_list_unmatched_bracket: "(]", src => Err(ParserError::new( test!(error_list_unmatched_bracket: "(]", src => Err(ParserError::new(
ParserErrorKind::UnmatchedBracket, ParserErrorKind::UnmatchedClosingDelimiter,
Span::new(1..2, src), Span::new(1..2, src),
))); )));
test!(error_list_missing_close_paren: "(true", src => Err(ParserError::new( test!(error_list_missing_close_paren: "(true", src => Err(ParserError::new(
ParserErrorKind::UnclosedBracket, ParserErrorKind::UnclosedSequence,
Span::new(0..1, src), Span::new(0..5, src),
))); )));
test!(error_list_unexpected_close_paren: ")", src => Err(ParserError::new( test!(error_list_unexpected_close_paren: ")", src => Err(ParserError::new(
ParserErrorKind::UnexpectedCloseBracket, ParserErrorKind::UnexpectedClosingDelimiter,
Span::new(0..1, src) Span::new(0..1, src)
))); )));
test!(map: "#{:a 0.0 :b 1.0}", src => Ok(vec![ test!(map: "#{:a 0.0 :b 1.0}", src => Ok(Ast::from(vec![
Node::new( Node::new(
NodeKind::Map(vec![ Expr::Map(vec![
Node::new(Atom::Keyword(Symbol::from("a")).into(), Span::new(2..4, src.clone())), Node::new(Atom::Keyword(Symbol::from("a")).into(), Span::new(2..4, src.clone())),
Node::new(Atom::Float(0.0).into(), Span::new(5..8, src.clone())), Node::new(Atom::Float(0.0).into(), Span::new(5..8, src.clone())),
Node::new(Atom::Keyword(Symbol::from("b")).into(), Span::new(9..11, src.clone())), Node::new(Atom::Keyword(Symbol::from("b")).into(), Span::new(9..11, src.clone())),
@ -217,7 +216,7 @@ mod tests {
]), ]),
Span::new(0..16, src) Span::new(0..16, src)
) )
])); ])));
test!(error_map_missing_value: "#{:x}", src => Err(ParserError::new( test!(error_map_missing_value: "#{:x}", src => Err(ParserError::new(
ParserErrorKind::MissingValueInMap, ParserErrorKind::MissingValueInMap,
@ -225,74 +224,74 @@ mod tests {
))); )));
test!(error_map_unmatched_bracket: "#{)", src => Err(ParserError::new( test!(error_map_unmatched_bracket: "#{)", src => Err(ParserError::new(
ParserErrorKind::UnmatchedBracket, ParserErrorKind::UnmatchedClosingDelimiter,
Span::new(2..3, src), Span::new(2..3, src),
))); )));
test!(error_map_missing_close_brace: "#{", src => Err(ParserError::new( test!(error_map_missing_close_brace: "#{", src => Err(ParserError::new(
ParserErrorKind::UnclosedBracket, ParserErrorKind::UnclosedSequence,
Span::new(0..2, src), Span::new(0..2, src),
))); )));
test!(set: "{{} nil}", src => Ok(vec![ test!(error_map_set_unexpected_close_brace: "}", src => Err(ParserError::new(
ParserErrorKind::UnexpectedClosingDelimiter,
Span::new(0..1, src)
)));
test!(set: "{{} nil}", src => Ok(Ast::from(vec![
Node::new( Node::new(
NodeKind::Set(vec![ Expr::Set(vec![
Node::new(NodeKind::Set(vec![]), Span::new(1..3, src.clone())), Node::new(Expr::Set(vec![]), Span::new(1..3, src.clone())),
Node::new(NodeKind::Atom(Atom::Nil), Span::new(4..7, src.clone())), Node::new(Expr::Atom(Atom::Nil), Span::new(4..7, src.clone())),
]), ]),
Span::new(0..8, src), Span::new(0..8, src),
) )
])); ])));
test!(error_set_unmatched_bracket: "{]", src => Err(ParserError::new( test!(error_set_unmatched_bracket: "{]", src => Err(ParserError::new(
ParserErrorKind::UnmatchedBracket, ParserErrorKind::UnmatchedClosingDelimiter,
Span::new(1..2, src), Span::new(1..2, src),
))); )));
test!(error_set_missing_close_brace: "{", src => Err(ParserError::new( test!(error_set_missing_close_brace: "{", src => Err(ParserError::new(
ParserErrorKind::UnclosedBracket, ParserErrorKind::UnclosedSequence,
Span::new(0..1, src), Span::new(0..1, src),
))); )));
test!(error_map_set_unexpected_close_brace: "}", src => Err(ParserError::new( test!(vector: "['a' 'b' 'c']", src => Ok(Ast::from(vec![
ParserErrorKind::UnexpectedCloseBracket,
Span::new(0..1, src)
)));
test!(vector: "['a' 'b' 'c']", src => Ok(vec![
Node::new( Node::new(
NodeKind::Vector(vec![ Expr::Vector(vec![
Node::new(NodeKind::Atom(Atom::Char('a')), Span::new(1..4, src.clone())), Node::new(Expr::Atom(Atom::Char('a')), Span::new(1..4, src.clone())),
Node::new(NodeKind::Atom(Atom::Char('b')), Span::new(5..8, src.clone())), Node::new(Expr::Atom(Atom::Char('b')), Span::new(5..8, src.clone())),
Node::new(NodeKind::Atom(Atom::Char('c')), Span::new(9..12, src.clone())), Node::new(Expr::Atom(Atom::Char('c')), Span::new(9..12, src.clone())),
]), ]),
Span::new(0..13, src), Span::new(0..13, src),
) )
])); ])));
test!(error_vector_unmatched_bracket: "[}", src => Err(ParserError::new( test!(error_vector_unmatched_bracket: "[}", src => Err(ParserError::new(
ParserErrorKind::UnmatchedBracket, ParserErrorKind::UnmatchedClosingDelimiter,
Span::new(1..2, src), Span::new(1..2, src),
))); )));
test!(error_vector_missing_close_bracket: "{", src => Err(ParserError::new( test!(error_vector_missing_close_bracket: "[", src => Err(ParserError::new(
ParserErrorKind::UnclosedBracket, ParserErrorKind::UnclosedSequence,
Span::new(0..1, src), Span::new(0..1, src),
))); )));
test!(error_vector_unexpected_close_bracket: "]", src => Err(ParserError::new( test!(error_vector_unexpected_close_bracket: "]", src => Err(ParserError::new(
ParserErrorKind::UnexpectedCloseBracket, ParserErrorKind::UnexpectedClosingDelimiter,
Span::new(0..1, src) Span::new(0..1, src)
))); )));
test!(multiple_expressions: "(/ 6 3 (+ 1 2)) (* 2 5)\n(- 10 5)", src => Ok(vec![ test!(multiple_expressions: "(/ 6 3 (+ 1 2)) (* 2 5)\n(- 10 5)", src => Ok(Ast::from(vec![
Node::new( Node::new(
NodeKind::List(vec![ Expr::List(vec![
Node::new(Atom::Symbol(Symbol::from("/")).into(), Span::new(1..2, src.clone())), Node::new(Atom::Symbol(Symbol::from("/")).into(), Span::new(1..2, src.clone())),
Node::new(Atom::Integer(6).into(), Span::new(3..4, src.clone())), Node::new(Atom::Integer(6).into(), Span::new(3..4, src.clone())),
Node::new(Atom::Integer(3).into(), Span::new(5..6, src.clone())), Node::new(Atom::Integer(3).into(), Span::new(5..6, src.clone())),
Node::new( Node::new(
NodeKind::List(vec![ Expr::List(vec![
Node::new(Atom::Symbol(Symbol::from("+")).into(), Span::new(8..9, src.clone())), Node::new(Atom::Symbol(Symbol::from("+")).into(), Span::new(8..9, src.clone())),
Node::new(Atom::Integer(1).into(), Span::new(10..11, src.clone())), Node::new(Atom::Integer(1).into(), Span::new(10..11, src.clone())),
Node::new(Atom::Integer(2).into(), Span::new(12..13, src.clone())), Node::new(Atom::Integer(2).into(), Span::new(12..13, src.clone())),
@ -303,7 +302,7 @@ mod tests {
Span::new(0..15, src.clone()) Span::new(0..15, src.clone())
), ),
Node::new( Node::new(
NodeKind::List(vec![ Expr::List(vec![
Node::new(Atom::Symbol(Symbol::from("*")).into(), Span::new(17..18, src.clone())), Node::new(Atom::Symbol(Symbol::from("*")).into(), Span::new(17..18, src.clone())),
Node::new(Atom::Integer(2).into(), Span::new(19..20, src.clone())), Node::new(Atom::Integer(2).into(), Span::new(19..20, src.clone())),
Node::new(Atom::Integer(5).into(), Span::new(21..22, src.clone())), Node::new(Atom::Integer(5).into(), Span::new(21..22, src.clone())),
@ -311,21 +310,21 @@ mod tests {
Span::new(16..23, src.clone()) Span::new(16..23, src.clone())
), ),
Node::new( Node::new(
NodeKind::List(vec![ Expr::List(vec![
Node::new(Atom::Symbol(Symbol::from("-")).into(), Span::new(25..26, src.clone())), Node::new(Atom::Symbol(Symbol::from("-")).into(), Span::new(25..26, src.clone())),
Node::new(Atom::Integer(10).into(), Span::new(27..29, src.clone())), Node::new(Atom::Integer(10).into(), Span::new(27..29, src.clone())),
Node::new(Atom::Integer(5).into(), Span::new(30..31, src.clone())), Node::new(Atom::Integer(5).into(), Span::new(30..31, src.clone())),
]), ]),
Span::new(24..32, src) Span::new(24..32, src)
), ),
])); ])));
test!(function_application: "(join \"foo\" \"bar\")", src => Ok(vec![Node::new( test!(function_application: "(join \"foo\" \"bar\")", src => Ok(Ast::from(vec![Node::new(
NodeKind::List(vec![ Expr::List(vec![
Node::new(Atom::Symbol(Symbol::from("join")).into(), Span::new(1..5, src.clone())), Node::new(Atom::Symbol(Symbol::from("join")).into(), Span::new(1..5, src.clone())),
Node::new(Atom::String("foo".into()).into(), Span::new(6..11, src.clone())), Node::new(Atom::String("foo".into()).into(), Span::new(6..11, src.clone())),
Node::new(Atom::String("bar".into()).into(), Span::new(12..17, src.clone())), Node::new(Atom::String("bar".into()).into(), Span::new(12..17, src.clone())),
]), ]),
Span::new(0..18, src) Span::new(0..18, src)
)])); )])));
} }