aboutsummaryrefslogtreecommitdiff
path: root/sloth/src/parser/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'sloth/src/parser/mod.rs')
-rw-r--r--sloth/src/parser/mod.rs66
1 files changed, 62 insertions, 4 deletions
diff --git a/sloth/src/parser/mod.rs b/sloth/src/parser/mod.rs
index 9d77acc..bc47ddd 100644
--- a/sloth/src/parser/mod.rs
+++ b/sloth/src/parser/mod.rs
@@ -1,23 +1,57 @@
pub mod ast;
pub mod expr;
+pub mod graph;
pub mod stmt;
+use self::ast::{Literal, Stmt};
use crate::lexer::{Token, TokenType};
+
+#[derive(thiserror::Error, Debug, PartialEq)]
+pub enum ParsingError {
+ #[error("Invalid operation")]
+ InvalidOp,
+ #[error("Unexpected token")]
+ UnexpectedToken,
+}
+
#[derive(Debug)]
pub struct AstParser<'a> {
tokens: Vec<Token<'a>>,
index: usize,
+ id: i32,
+}
+
+impl<'a> AstParser<'a> {
+ pub fn parse(tokens: Vec<Token<'a>>) -> Result<Vec<Stmt>, ParsingError> {
+ let mut parser = Self::new(tokens);
+
+ let mut statements = Vec::new();
+ while !parser.eof() {
+ statements.push(parser.statement()?);
+ }
+
+ Ok(statements)
+ }
}
/// Implementation containing utilities used by the parsers internal components
impl<'a> AstParser<'a> {
pub fn new(tokens: Vec<Token<'a>>) -> Self {
- Self { tokens, index: 0 }
+ Self {
+ tokens,
+ index: 0,
+ id: 0,
+ }
}
+
pub fn peek(&self) -> &Token {
&self.tokens[self.index]
}
+ pub fn peek2(&self) -> &Token {
+ &self.tokens[self.index + 1]
+ }
+
pub fn advance(&mut self) -> Option<&Token> {
if self.eof() {
return None;
@@ -44,11 +78,35 @@ impl<'a> AstParser<'a> {
self.advance_if(|it| it.tt == *next)
}
- pub fn consume(&mut self, next: TokenType, error: &str) {
+ pub fn consume(&mut self, next: TokenType, error: &str) -> Result<&Token, ParsingError> {
if std::mem::discriminant(&self.peek().tt) != std::mem::discriminant(&next) {
- panic!("{error} at index {:?}", self.index);
+ println!("{error} at index {:?}", self.index);
+ return Err(ParsingError::UnexpectedToken);
}
- self.advance();
+
+ Ok(self.advance().unwrap())
+ }
+
+ pub fn consume_literal(&mut self) -> Result<Literal, ParsingError> {
+ let Some(TokenType::Literal(literal)) = self.advance().map(|it| it.tt.clone()) else {
+ return Err(ParsingError::UnexpectedToken);
+ };
+
+ Ok(literal.into())
+ }
+
+ pub fn consume_identifier(&mut self) -> Result<String, ParsingError> {
+ let Some(TokenType::Identifier(identifier)) = self.advance().map(|it| it.tt.clone()) else {
+ return Err(ParsingError::UnexpectedToken);
+ };
+
+ Ok(identifier)
+ }
+
+ pub fn reserve_id(&mut self) -> i32 {
+ let id = self.id;
+ self.id += 1;
+ id
}
pub fn eof(&self) -> bool {