Skip to content

Commit

Permalink
rust: start pratt parser impl
Browse files Browse the repository at this point in the history
  • Loading branch information
styvane committed Jul 25, 2023
1 parent 01a5db9 commit 6f70da6
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 11 deletions.
10 changes: 3 additions & 7 deletions toolchain/rust/src/expr.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
//! This module defines the data structures for an expressions.
/// Expr represents an expression.
#[derive(Debug, PartialEq, Eq)]
pub struct Expr;

/// `ExprData` represents an expression data.
#[derive(Debug, PartialEq, Eq)]
pub enum ExprData {
VariableDecl(Expr, String),
Return(Expr, String),
ExprStatement(Expr, String),
VariableDecl(String),
Return(String),
ExprStatement(String),
}
68 changes: 64 additions & 4 deletions toolchain/rust/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@
//!
//! This module implement the parser for the language.
mod ops;

use crate::ast::syntax::*;
use crate::ast::{Program, Statement};
use crate::error::Error;
use crate::expr::{Expr, ExprData};
use crate::expr::ExprData;
use crate::lexer::Lexer;
use crate::token::{Token, TokenKind};

use self::ops::Precedence;

/// Parser type.
#[derive(Debug)]
pub struct Parser<I: Iterator<Item = (usize, char)>> {
Expand Down Expand Up @@ -100,7 +104,7 @@ where
match token.kind {
TokenKind::Let => self.parse_var_decl(),
TokenKind::Return => self.parse_return_statement(),
_ => None,
_ => self.parse_expr_statement(),
}
}

Expand All @@ -115,20 +119,32 @@ where
let stmt = Statement::Var(LocalVarDecl {
token,
name,
expr: ExprData::VariableDecl(Expr, "".into()),
expr: ExprData::VariableDecl(String::new()),
});

Some(stmt)
}

fn parse_expr_statement(&self) -> Option<Statement> {
let stmt = ExprStatement {
token: self.current_token.clone().take()?,
expr: self.parse_expr(Precedence::Lower),
};
Some(Statement::Expr(stmt))
}

fn parse_expr(&self, precedence: Precedence) -> ExprData {
todo!()
}

fn parse_return_statement(&mut self) -> Option<Statement> {
let token = self.current_token.take()?;
if !self.is_valid_current_token(TokenKind::Semi) {
self.advance();
}
let stmt = Statement::Return(ReturnStatement {
token,
expr: ExprData::Return(Expr, "".into()),
expr: ExprData::Return(String::new()),
});
Some(stmt)
}
Expand All @@ -143,11 +159,24 @@ pub trait PrattParser {
fn infix_parse(ast: ExprData) -> ExprData;
}

impl PrattParser for TokenKind {
fn prefix_parse() -> ExprData {
todo!()
}

fn infix_parse(ast: ExprData) -> ExprData {
todo!()
}
}

#[cfg(test)]
mod tests {
use crate::ast::syntax::ExprStatement;
use crate::ast::Statement;
use crate::error::Error;
use crate::expr::ExprData;
use crate::lexer::Lexer;
use crate::token::{TokenKind, TokenValue};

use super::Parser;

Expand Down Expand Up @@ -209,4 +238,35 @@ return 999999;
assert!(matches!(stmt, Statement::Return(_)))
}
}

#[test]
fn parse_identifier_expr() {
let input = "foobar;";
let lexer = Lexer::from_text(input);
let mut parser = Parser::new(lexer);
let program = parser.parse();
check_parser_errors(&parser.errors);

assert_eq!(
1,
program.statements.len(),
"program has not enough statements",
);

let (token, expr) = match &program.statements[0] {
Statement::Expr(ExprStatement {
token,
expr: ExprData::ExprStatement(expr),
..
}) => (token, expr),
_ => panic!(
"expected expression statement found {:?}",
&program.statements[0]
),
};

assert_eq!(TokenKind::Ident, token.kind);
assert_eq!(expr, "foobar");
assert_eq!(token.value, TokenValue::Word("foobar".into()));
}
}
7 changes: 7 additions & 0 deletions toolchain/rust/src/parser/ops.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/// Operator precedences.
#[derive(Debug, Clone)]
/// Defines operators precedences.
pub enum Precedence {
Lower,
}

0 comments on commit 6f70da6

Please sign in to comment.