Rewrote the parser
This commit is contained in:
parent
96d1311e09
commit
88912bfa39
@ -59,6 +59,12 @@ impl<'lexer> Lexer<'lexer> {
|
||||
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.
|
||||
#[must_use]
|
||||
fn current(&self) -> Option<char> {
|
||||
|
@ -4,9 +4,123 @@ use crate::{
|
||||
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.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Atom {
|
||||
pub(crate) enum Atom {
|
||||
/// Boolean, e.g. `true`, `false`
|
||||
Bool(bool),
|
||||
/// Character, e.g. `'c'`, `'\n'`
|
||||
@ -45,7 +159,7 @@ impl std::fmt::Display for Atom {
|
||||
|
||||
/// An expression.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum NodeKind {
|
||||
pub(crate) enum Expr {
|
||||
/// An atomic value.
|
||||
Atom(Atom),
|
||||
/// A list of nodes.
|
||||
@ -58,13 +172,25 @@ pub enum NodeKind {
|
||||
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 {
|
||||
Self::Atom(atom)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Token> for NodeKind {
|
||||
impl TryFrom<Token> for Expr {
|
||||
type Error = ParserError;
|
||||
|
||||
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::Nil => Atom::Nil,
|
||||
_ => {
|
||||
return Err(ParserError::new(
|
||||
ParserErrorKind::UnexpectedState,
|
||||
token.span,
|
||||
))
|
||||
// FIXME
|
||||
// return Err(ParserError::new(
|
||||
// ParserErrorKind::UnexpectedState,
|
||||
// token.span,
|
||||
// ))
|
||||
todo!()
|
||||
}
|
||||
};
|
||||
|
||||
@ -90,9 +218,9 @@ impl TryFrom<Token> for NodeKind {
|
||||
}
|
||||
|
||||
#[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 {
|
||||
use NodeKind::*;
|
||||
use Expr::*;
|
||||
|
||||
match self {
|
||||
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))
|
||||
}
|
||||
}
|
@ -5,19 +5,16 @@ use crate::{lexer::LexerError, span::Span};
|
||||
pub enum ParserErrorKind {
|
||||
/// An error which ocurred during lexical analysis.
|
||||
Lexer(LexerError),
|
||||
/// Expected a value for key in map, but no value was found.
|
||||
/// Key in map is missing its corresponding value.
|
||||
MissingValueInMap,
|
||||
/// An unexpecting closing parenthesis/brace/bracket was encountered.
|
||||
UnexpectedCloseBracket,
|
||||
/// Unexpectedly reached the end of the input.
|
||||
/// Opening delimiter does not have a matching closing delimiter.
|
||||
UnclosedSequence,
|
||||
/// An unexpected closing delimiter was found.
|
||||
UnexpectedClosingDelimiter,
|
||||
/// Unexpectedly reached end of input.
|
||||
UnexpectedEof,
|
||||
/// Unexpected parser state reached.
|
||||
UnexpectedState,
|
||||
/// Opening parenthesis/brace/bracket does not have a matching closing
|
||||
/// parenthesis/brace/bracket.
|
||||
UnclosedBracket,
|
||||
/// An unmatched parenthesis/brace/bracket was encountered.
|
||||
UnmatchedBracket,
|
||||
/// An unmatched closing delimiter was found.
|
||||
UnmatchedClosingDelimiter,
|
||||
}
|
||||
|
||||
/// Parser error, with a start and end location.
|
||||
@ -30,13 +27,20 @@ pub struct ParserError {
|
||||
}
|
||||
|
||||
impl ParserError {
|
||||
/// Construct a new instance of `ParserErorr`.
|
||||
/// Construct a new instance of `ParserError`.
|
||||
#[must_use]
|
||||
pub const fn new(kind: ParserErrorKind, span: Span) -> Self {
|
||||
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 {}
|
||||
|
||||
#[cfg(not(tarpaulin_include))]
|
||||
@ -46,19 +50,14 @@ impl std::fmt::Display for ParserError {
|
||||
|
||||
match &self.kind {
|
||||
Lexer(err) => write!(f, "{err}"),
|
||||
MissingValueInMap => write!(f, "Key in map is missing its value"),
|
||||
UnexpectedCloseBracket => write!(f, "Unexpected closing bracket"),
|
||||
UnexpectedEof => write!(f, "Unexpected reached end of input"),
|
||||
UnexpectedState => write!(f, "Unexpected parsing state reached"),
|
||||
UnclosedBracket => write!(f, "Unclosed bracket"),
|
||||
UnmatchedBracket => write!(f, "Unmatched bracket"),
|
||||
MissingValueInMap => write!(f, "Key in map is missing its corresponding value"),
|
||||
UnclosedSequence => write!(
|
||||
f,
|
||||
"Opening delimiter does not have a matching closing delimiter"
|
||||
),
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -1,154 +1,154 @@
|
||||
pub use self::{
|
||||
use self::{
|
||||
ast::{Ast, Expr, Node},
|
||||
error::{ParserError, ParserErrorKind},
|
||||
node::{Node, NodeKind},
|
||||
};
|
||||
use crate::lexer::{Lexer, TokenKind};
|
||||
use crate::{
|
||||
lexer::{Lexer, TokenKind},
|
||||
span::Span,
|
||||
};
|
||||
|
||||
mod ast;
|
||||
mod error;
|
||||
mod node;
|
||||
|
||||
/// Parser for converting Onihime source code into an Abstract Syntax Tree
|
||||
/// (AST).
|
||||
#[derive(Debug)]
|
||||
pub struct Parser<'parser> {
|
||||
pub(crate) struct Parser<'parser> {
|
||||
lexer: Lexer<'parser>,
|
||||
parents: Vec<Node>,
|
||||
current: Node,
|
||||
}
|
||||
|
||||
impl<'parser> Parser<'parser> {
|
||||
/// Create a new parser instance from a string.
|
||||
#[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 {
|
||||
lexer: Lexer::new(input),
|
||||
lexer,
|
||||
parents: Vec::new(),
|
||||
current,
|
||||
}
|
||||
}
|
||||
|
||||
/// 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);
|
||||
}
|
||||
|
||||
/// Parse the input string into an AST.
|
||||
pub fn parse(&mut self) -> Result<Vec<Node>, ParserError> {
|
||||
let mut parents = Vec::new();
|
||||
let mut cur_node = Node::new(NodeKind::List(Vec::new()), self.lexer.span());
|
||||
|
||||
while let Some(token) = self.lexer.read()? {
|
||||
match token.kind {
|
||||
TokenKind::BlockComment(_) | TokenKind::LineComment(_) => {}
|
||||
|
||||
TokenKind::OpenParen => {
|
||||
let child = Node::new(NodeKind::List(Vec::new()), token.span);
|
||||
parents.push(cur_node);
|
||||
cur_node = child;
|
||||
}
|
||||
TokenKind::CloseParen => {
|
||||
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::List(_)) {
|
||||
return Err(ParserError::new(
|
||||
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;
|
||||
}
|
||||
|
||||
_ => {
|
||||
let node = Node::try_from(token)?;
|
||||
cur_node.push_node(node)?;
|
||||
}
|
||||
/// Produce an Abstract Syntax Tree (AST) from the source input.
|
||||
#[must_use]
|
||||
pub(crate) fn parse(mut self) -> Result<Ast, ParserError> {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
if !parents.is_empty() {
|
||||
// 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::UnclosedBracket,
|
||||
cur_node.span,
|
||||
ParserErrorKind::UnclosedSequence,
|
||||
self.current.span,
|
||||
));
|
||||
}
|
||||
|
||||
if let NodeKind::List(body) = cur_node.kind {
|
||||
Ok(body)
|
||||
// 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!() // In theory, at least...
|
||||
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 {
|
||||
// Comments are simply ignored by the parser:
|
||||
TokenKind::BlockComment(_) | TokenKind::LineComment(_) => Ok(None),
|
||||
|
||||
// Any valid opening delimiters begins a new sequence:
|
||||
TokenKind::OpenParen => self.begin_sequence(Expr::List, token.span),
|
||||
TokenKind::OpenHashBrace => self.begin_sequence(Expr::Map, token.span),
|
||||
TokenKind::OpenBrace => self.begin_sequence(Expr::Set, token.span),
|
||||
TokenKind::OpenBracket => self.begin_sequence(Expr::Vector, token.span),
|
||||
|
||||
// Any valid closing delimiters end the current sequence:
|
||||
kind
|
||||
@ (TokenKind::CloseParen | TokenKind::CloseBrace | TokenKind::CloseBracket) => {
|
||||
self.end_sequence(kind, token.span)
|
||||
}
|
||||
|
||||
// Atoms are pushed to the current sequence:
|
||||
_ => {
|
||||
let node = Node::try_from(token)?;
|
||||
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(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[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(
|
||||
ParserErrorKind::UnmatchedClosingDelimiter,
|
||||
span,
|
||||
));
|
||||
}
|
||||
|
||||
// For maps, ensure that each key has a corresponding value:
|
||||
match current.kind {
|
||||
Expr::Map(ref vec) if vec.len() % 2 != 0 => {
|
||||
return Err(ParserError::new(ParserErrorKind::MissingValueInMap, span));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// Finally, return the current node so it can be added to the AST:
|
||||
Ok(Some(current))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -156,8 +156,7 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::{
|
||||
lexer::{LexerError, LexerErrorKind, Symbol},
|
||||
parser::node::Atom,
|
||||
span::Span,
|
||||
parser::ast::Atom,
|
||||
};
|
||||
|
||||
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(
|
||||
ParserErrorKind::Lexer(LexerError::new(
|
||||
@ -181,35 +180,35 @@ mod tests {
|
||||
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(
|
||||
NodeKind::List(vec![
|
||||
Expr::List(vec![
|
||||
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(2).into(), Span::new(5..6, src.clone())),
|
||||
]),
|
||||
Span::new(0..7, src)
|
||||
)
|
||||
]));
|
||||
])));
|
||||
|
||||
test!(error_list_unmatched_bracket: "(]", src => Err(ParserError::new(
|
||||
ParserErrorKind::UnmatchedBracket,
|
||||
ParserErrorKind::UnmatchedClosingDelimiter,
|
||||
Span::new(1..2, src),
|
||||
)));
|
||||
|
||||
test!(error_list_missing_close_paren: "(true", src => Err(ParserError::new(
|
||||
ParserErrorKind::UnclosedBracket,
|
||||
Span::new(0..1, src),
|
||||
ParserErrorKind::UnclosedSequence,
|
||||
Span::new(0..5, src),
|
||||
)));
|
||||
|
||||
test!(error_list_unexpected_close_paren: ")", src => Err(ParserError::new(
|
||||
ParserErrorKind::UnexpectedCloseBracket,
|
||||
ParserErrorKind::UnexpectedClosingDelimiter,
|
||||
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(
|
||||
NodeKind::Map(vec![
|
||||
Expr::Map(vec![
|
||||
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::Keyword(Symbol::from("b")).into(), Span::new(9..11, src.clone())),
|
||||
@ -217,7 +216,7 @@ mod tests {
|
||||
]),
|
||||
Span::new(0..16, src)
|
||||
)
|
||||
]));
|
||||
])));
|
||||
|
||||
test!(error_map_missing_value: "#{:x}", src => Err(ParserError::new(
|
||||
ParserErrorKind::MissingValueInMap,
|
||||
@ -225,74 +224,74 @@ mod tests {
|
||||
)));
|
||||
|
||||
test!(error_map_unmatched_bracket: "#{)", src => Err(ParserError::new(
|
||||
ParserErrorKind::UnmatchedBracket,
|
||||
ParserErrorKind::UnmatchedClosingDelimiter,
|
||||
Span::new(2..3, src),
|
||||
)));
|
||||
|
||||
test!(error_map_missing_close_brace: "#{", src => Err(ParserError::new(
|
||||
ParserErrorKind::UnclosedBracket,
|
||||
ParserErrorKind::UnclosedSequence,
|
||||
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(
|
||||
NodeKind::Set(vec![
|
||||
Node::new(NodeKind::Set(vec![]), Span::new(1..3, src.clone())),
|
||||
Node::new(NodeKind::Atom(Atom::Nil), Span::new(4..7, src.clone())),
|
||||
Expr::Set(vec![
|
||||
Node::new(Expr::Set(vec![]), Span::new(1..3, src.clone())),
|
||||
Node::new(Expr::Atom(Atom::Nil), Span::new(4..7, src.clone())),
|
||||
]),
|
||||
Span::new(0..8, src),
|
||||
)
|
||||
]));
|
||||
])));
|
||||
|
||||
test!(error_set_unmatched_bracket: "{]", src => Err(ParserError::new(
|
||||
ParserErrorKind::UnmatchedBracket,
|
||||
ParserErrorKind::UnmatchedClosingDelimiter,
|
||||
Span::new(1..2, src),
|
||||
)));
|
||||
|
||||
test!(error_set_missing_close_brace: "{", src => Err(ParserError::new(
|
||||
ParserErrorKind::UnclosedBracket,
|
||||
ParserErrorKind::UnclosedSequence,
|
||||
Span::new(0..1, src),
|
||||
)));
|
||||
|
||||
test!(error_map_set_unexpected_close_brace: "}", src => Err(ParserError::new(
|
||||
ParserErrorKind::UnexpectedCloseBracket,
|
||||
Span::new(0..1, src)
|
||||
)));
|
||||
|
||||
test!(vector: "['a' 'b' 'c']", src => Ok(vec![
|
||||
test!(vector: "['a' 'b' 'c']", src => Ok(Ast::from(vec![
|
||||
Node::new(
|
||||
NodeKind::Vector(vec![
|
||||
Node::new(NodeKind::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(NodeKind::Atom(Atom::Char('c')), Span::new(9..12, src.clone())),
|
||||
Expr::Vector(vec![
|
||||
Node::new(Expr::Atom(Atom::Char('a')), Span::new(1..4, src.clone())),
|
||||
Node::new(Expr::Atom(Atom::Char('b')), Span::new(5..8, src.clone())),
|
||||
Node::new(Expr::Atom(Atom::Char('c')), Span::new(9..12, src.clone())),
|
||||
]),
|
||||
Span::new(0..13, src),
|
||||
)
|
||||
]));
|
||||
])));
|
||||
|
||||
test!(error_vector_unmatched_bracket: "[}", src => Err(ParserError::new(
|
||||
ParserErrorKind::UnmatchedBracket,
|
||||
ParserErrorKind::UnmatchedClosingDelimiter,
|
||||
Span::new(1..2, src),
|
||||
)));
|
||||
|
||||
test!(error_vector_missing_close_bracket: "{", src => Err(ParserError::new(
|
||||
ParserErrorKind::UnclosedBracket,
|
||||
test!(error_vector_missing_close_bracket: "[", src => Err(ParserError::new(
|
||||
ParserErrorKind::UnclosedSequence,
|
||||
Span::new(0..1, src),
|
||||
)));
|
||||
|
||||
test!(error_vector_unexpected_close_bracket: "]", src => Err(ParserError::new(
|
||||
ParserErrorKind::UnexpectedCloseBracket,
|
||||
ParserErrorKind::UnexpectedClosingDelimiter,
|
||||
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(
|
||||
NodeKind::List(vec![
|
||||
Expr::List(vec![
|
||||
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(3).into(), Span::new(5..6, src.clone())),
|
||||
Node::new(
|
||||
NodeKind::List(vec![
|
||||
Expr::List(vec![
|
||||
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(2).into(), Span::new(12..13, src.clone())),
|
||||
@ -303,7 +302,7 @@ mod tests {
|
||||
Span::new(0..15, src.clone())
|
||||
),
|
||||
Node::new(
|
||||
NodeKind::List(vec![
|
||||
Expr::List(vec![
|
||||
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(5).into(), Span::new(21..22, src.clone())),
|
||||
@ -311,21 +310,21 @@ mod tests {
|
||||
Span::new(16..23, src.clone())
|
||||
),
|
||||
Node::new(
|
||||
NodeKind::List(vec![
|
||||
Expr::List(vec![
|
||||
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(5).into(), Span::new(30..31, src.clone())),
|
||||
]),
|
||||
Span::new(24..32, src)
|
||||
),
|
||||
]));
|
||||
])));
|
||||
|
||||
test!(function_application: "(join \"foo\" \"bar\")", src => Ok(vec![Node::new(
|
||||
NodeKind::List(vec![
|
||||
test!(function_application: "(join \"foo\" \"bar\")", src => Ok(Ast::from(vec![Node::new(
|
||||
Expr::List(vec![
|
||||
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("bar".into()).into(), Span::new(12..17, src.clone())),
|
||||
]),
|
||||
Span::new(0..18, src)
|
||||
)]));
|
||||
)])));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user