crftng-intrprtrs/src/ast/parser.rs

166 lines
3.9 KiB
Rust
Raw Normal View History

2022-03-24 16:33:10 +01:00
use super::astnode;
use super::astnode::{ASTNode, BinaryExpr};
use crate::lexer::{token, token::TokenType};
use std::iter;
use std::result::Result as StdResult;
type Result<T> = StdResult<T, ASTParsingError>;
#[derive(Debug)]
pub enum ASTParsingError {
UnmatchedBrace,
}
2022-04-02 21:23:47 +02:00
2022-03-24 16:33:10 +01:00
impl std::fmt::Display for ASTParsingError {
2022-04-02 21:23:47 +02:00
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2022-03-24 16:33:10 +01:00
todo!()
}
}
impl std::error::Error for ASTParsingError {}
2022-04-02 21:23:47 +02:00
pub struct Parser<'a, T: Iterator<Item = token::Token<'a>>> {
2022-03-24 16:33:10 +01:00
token_iter: iter::Peekable<T>,
}
2022-04-02 21:23:47 +02:00
impl<'a, T: Iterator<Item = token::Token<'a>>> Parser<'a, T> {
pub fn new(iter: T) -> Parser<'a, T> {
2022-03-24 16:33:10 +01:00
Parser {
token_iter: iter.peekable(),
}
}
pub fn scan_expressions(&mut self) -> StdResult<Vec<ASTNode>, Vec<ASTParsingError>> {
let mut tokens = Vec::new();
let mut errors = Vec::new();
while self.token_iter.peek().is_some() {
match self.expression() {
Ok(token) => {
if errors.is_empty() {
tokens.push(token)
}
}
Err(e) => errors.push(e),
}
}
if errors.is_empty() {
Ok(tokens)
} else {
Err(errors)
}
}
fn expression(&mut self) -> Result<ASTNode> {
self.equality()
}
fn equality(&mut self) -> Result<ASTNode> {
let mut node = self.comparison()?;
while let Some(o) = self
.token_iter
.next_if(|t| matches!(t.token_type, TokenType::EqualEqual | TokenType::BangEqual))
{
node = BinaryExpr::new(
Box::new(node),
o.token_type.try_into().unwrap(),
Box::new(self.comparison()?),
)
.into();
}
Ok(node)
}
fn comparison(&mut self) -> Result<ASTNode> {
let mut node = self.term()?;
while let Some(o) = self.token_iter.next_if(|t| {
matches!(
t.token_type,
TokenType::Greater
| TokenType::GreaterEqual
| TokenType::Less | TokenType::LessEqual
)
}) {
node = BinaryExpr::new(
Box::new(node),
o.token_type.try_into().unwrap(),
Box::new(self.comparison()?),
)
.into();
}
Ok(node)
}
fn term(&mut self) -> Result<ASTNode> {
let mut node = self.factor()?;
while let Some(o) = self
.token_iter
.next_if(|t| matches!(t.token_type, TokenType::Minus | TokenType::Plus))
{
node = BinaryExpr::new(
Box::new(node),
o.token_type.try_into().unwrap(),
Box::new(self.comparison()?),
)
.into()
}
Ok(node)
}
fn factor(&mut self) -> Result<ASTNode> {
let mut node = self.unary()?;
while let Some(o) = self
.token_iter
.next_if(|t| matches!(t.token_type, TokenType::Star | TokenType::Slash))
{
node = BinaryExpr::new(
Box::new(node),
o.token_type.try_into().unwrap(),
Box::new(self.comparison()?),
)
.into();
}
Ok(node)
}
fn unary(&mut self) -> Result<ASTNode> {
if let Some(op) = self
.token_iter
.next_if(|t| matches!(t.token_type, TokenType::Bang | TokenType::Minus))
{
let right = Box::new(self.unary()?);
Ok(ASTNode::UnaryExpr(astnode::UnaryExpr::new(
op.token_type.try_into().unwrap(),
right,
)))
} else {
self.primary()
}
}
fn primary(&mut self) -> Result<ASTNode> {
let node = match self.token_iter.next().map(|it| it.token_type) {
Some(TokenType::False) => ASTNode::Literal(astnode::Literal::Bool(false)),
Some(TokenType::True) => ASTNode::Literal(astnode::Literal::Bool(false)),
Some(TokenType::Int(i)) => ASTNode::Literal(astnode::Literal::Int(i)),
Some(TokenType::String(i)) => ASTNode::Literal(astnode::Literal::String(i)),
Some(TokenType::Float(f)) => ASTNode::Literal(astnode::Literal::Float(f)),
Some(TokenType::LeftParen) => {
let expr = self.expression()?;
let group = astnode::GroupingExpr::new(Box::new(expr));
match self
.token_iter
.next_if(|v| matches!(v.token_type, TokenType::RightParen))
{
Some(_) => return Ok(group.into()),
2022-04-02 21:23:47 +02:00
None => return Err(ASTParsingError::UnmatchedBrace),
2022-03-24 16:33:10 +01:00
}
}
Some(a) => panic!("{:#?}", a),
None => todo!(),
};
Ok(node)
}
}