parser: init
does not support many expressions Signed-off-by: Amneesh Singh <natto@weirdnatto.in>
This commit is contained in:
		
							
								
								
									
										59
									
								
								src/ast.rs
									
									
									
									
									
								
							
							
						
						
									
										59
									
								
								src/ast.rs
									
									
									
									
									
								
							@@ -1,72 +1,93 @@
 | 
				
			|||||||
/// A very naive AST definition using recursive enums
 | 
					//! A very naive AST definition using recursive enums
 | 
				
			||||||
/// See the parser for implementation
 | 
					//!
 | 
				
			||||||
 | 
					//! See the parser for implementation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use std::rc::Rc;
 | 
					use std::rc::Rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub type Parent = Vec<Entity>;
 | 
					pub type Parent = Vec<Entity>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Entities are functions, classes, and modules
 | 
					/// Entities are functions, classes, and modules
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug, PartialEq)]
 | 
				
			||||||
pub enum Entity {
 | 
					pub enum Entity {
 | 
				
			||||||
    Fn(Fn),
 | 
					    Fn(Fn),
 | 
				
			||||||
    Class(Class),
 | 
					    Class(Class),
 | 
				
			||||||
    Module(Module),
 | 
					    Module(Module),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					/// A module just provides an additional scope
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// TODO: Add exporting and importing modules
 | 
				
			||||||
 | 
					#[derive(Debug, PartialEq)]
 | 
				
			||||||
pub struct Module {
 | 
					pub struct Module {
 | 
				
			||||||
 | 
					    /// Name of module
 | 
				
			||||||
    pub name: Rc<str>,
 | 
					    pub name: Rc<str>,
 | 
				
			||||||
 | 
					    /// Everything inside the module
 | 
				
			||||||
    pub children: Vec<ModuleChildren>,
 | 
					    pub children: Vec<ModuleChildren>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Modules contain functions, classes and statements
 | 
					/// Modules contain functions, classes and statements
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug, PartialEq)]
 | 
				
			||||||
pub enum ModuleChildren {
 | 
					pub enum ModuleChildren {
 | 
				
			||||||
    Fn(Fn),
 | 
					    Fn(Fn),
 | 
				
			||||||
    Class(Class),
 | 
					    Class(Class),
 | 
				
			||||||
    Module(Module),
 | 
					    Module(Module),
 | 
				
			||||||
    Const(Let),
 | 
					    Static(Let),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					/// Classes encapsulate functions and definitions.
 | 
				
			||||||
 | 
					#[derive(Debug, PartialEq)]
 | 
				
			||||||
pub struct Class {
 | 
					pub struct Class {
 | 
				
			||||||
 | 
					    /// Name of class
 | 
				
			||||||
    pub name: Rc<str>,
 | 
					    pub name: Rc<str>,
 | 
				
			||||||
 | 
					    /// Everything inside the class
 | 
				
			||||||
    pub children: Vec<ClassChildren>,
 | 
					    pub children: Vec<ClassChildren>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Classes contain functions and statements.
 | 
					#[derive(Debug, PartialEq)]
 | 
				
			||||||
///
 | 
					 | 
				
			||||||
/// TODO: Maybe change statements to something else
 | 
					 | 
				
			||||||
#[derive(Debug)]
 | 
					 | 
				
			||||||
pub enum ClassChildren {
 | 
					pub enum ClassChildren {
 | 
				
			||||||
    Fn(Fn),
 | 
					    Fn(Fn),
 | 
				
			||||||
    Statement(Statement),
 | 
					    Let(Let),
 | 
				
			||||||
 | 
					    Static(Let),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					/// A Function
 | 
				
			||||||
 | 
					#[derive(Debug, PartialEq)]
 | 
				
			||||||
pub struct Fn {
 | 
					pub struct Fn {
 | 
				
			||||||
 | 
					    /// Name of the function
 | 
				
			||||||
    pub name: Rc<str>,
 | 
					    pub name: Rc<str>,
 | 
				
			||||||
 | 
					    /// Optional return type
 | 
				
			||||||
    pub return_ty: Option<Ty>,
 | 
					    pub return_ty: Option<Ty>,
 | 
				
			||||||
 | 
					    /// Parameters
 | 
				
			||||||
    pub params: Vec<(Rc<str>, Ty)>,
 | 
					    pub params: Vec<(Rc<str>, Ty)>,
 | 
				
			||||||
 | 
					    /// The function block
 | 
				
			||||||
    pub children: Vec<Statement>,
 | 
					    pub children: Vec<Statement>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					/// Statements encapsulate expressions and definitions
 | 
				
			||||||
 | 
					#[derive(Debug, PartialEq)]
 | 
				
			||||||
pub enum Statement {
 | 
					pub enum Statement {
 | 
				
			||||||
    Const(Let),
 | 
					    Static(Let),
 | 
				
			||||||
    Let(Let),
 | 
					    Let(Let),
 | 
				
			||||||
    Expr(Expr),
 | 
					    Expr(Expr),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					/// A variable definition
 | 
				
			||||||
 | 
					#[derive(Debug, PartialEq)]
 | 
				
			||||||
pub struct Let {
 | 
					pub struct Let {
 | 
				
			||||||
 | 
					    /// Name of variabe
 | 
				
			||||||
    pub name: Rc<str>,
 | 
					    pub name: Rc<str>,
 | 
				
			||||||
 | 
					    /// Type of variable
 | 
				
			||||||
    pub ty: Ty,
 | 
					    pub ty: Ty,
 | 
				
			||||||
 | 
					    /// Value of variable
 | 
				
			||||||
    pub expr: Option<Expr>,
 | 
					    pub expr: Option<Expr>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Op = crate::lexer::TokenSymbol;
 | 
					type Op = crate::lexer::TokenSymbol;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					/// Lowest form of expression
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// TODO: refine
 | 
				
			||||||
 | 
					#[derive(Debug, PartialEq)]
 | 
				
			||||||
pub enum Expr {
 | 
					pub enum Expr {
 | 
				
			||||||
    Int(i32),
 | 
					    Int(i32),
 | 
				
			||||||
    Float(f32),
 | 
					    Float(f32),
 | 
				
			||||||
@@ -74,7 +95,7 @@ pub enum Expr {
 | 
				
			|||||||
    Op(Op, Box<Expr>, Option<Box<Expr>>),
 | 
					    Op(Op, Box<Expr>, Option<Box<Expr>>),
 | 
				
			||||||
    If(Box<Expr>, Box<Expr>, Option<Box<Expr>>),
 | 
					    If(Box<Expr>, Box<Expr>, Option<Box<Expr>>),
 | 
				
			||||||
    Block(Vec<Statement>),
 | 
					    Block(Vec<Statement>),
 | 
				
			||||||
    Loop,
 | 
					    Loop(Vec<Statement>),
 | 
				
			||||||
    Break,
 | 
					    Break,
 | 
				
			||||||
    Continue,
 | 
					    Continue,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -82,7 +103,7 @@ pub enum Expr {
 | 
				
			|||||||
/// Primitives
 | 
					/// Primitives
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// TODO: add arrays and pointers maybe
 | 
					/// TODO: add arrays and pointers maybe
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug, PartialEq)]
 | 
				
			||||||
pub enum Ty {
 | 
					pub enum Ty {
 | 
				
			||||||
    Int,
 | 
					    Int,
 | 
				
			||||||
    Float,
 | 
					    Float,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										10
									
								
								src/lexer.rs
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								src/lexer.rs
									
									
									
									
									
								
							@@ -75,6 +75,7 @@ pub enum TokenKeyword {
 | 
				
			|||||||
    Module,
 | 
					    Module,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // statements
 | 
					    // statements
 | 
				
			||||||
 | 
					    Static,
 | 
				
			||||||
    Let,
 | 
					    Let,
 | 
				
			||||||
    Ret,
 | 
					    Ret,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -137,8 +138,9 @@ pub struct Lexer<'a> {
 | 
				
			|||||||
    tokens: VecDeque<Token>,
 | 
					    tokens: VecDeque<Token>,
 | 
				
			||||||
    /// Current line number
 | 
					    /// Current line number
 | 
				
			||||||
    pub line: usize,
 | 
					    pub line: usize,
 | 
				
			||||||
 | 
					    pub col: usize,
 | 
				
			||||||
    /// Start character index for the current token
 | 
					    /// Start character index for the current token
 | 
				
			||||||
    pub start: usize,
 | 
					    start: usize,
 | 
				
			||||||
    /// End character index for the current token
 | 
					    /// End character index for the current token
 | 
				
			||||||
    end: usize,
 | 
					    end: usize,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -170,6 +172,7 @@ impl<'a> Lexer<'a> {
 | 
				
			|||||||
            chars: content.chars().peekable(),
 | 
					            chars: content.chars().peekable(),
 | 
				
			||||||
            tokens: VecDeque::new(),
 | 
					            tokens: VecDeque::new(),
 | 
				
			||||||
            line: 1,
 | 
					            line: 1,
 | 
				
			||||||
 | 
					            col: 1,
 | 
				
			||||||
            start: 0,
 | 
					            start: 0,
 | 
				
			||||||
            end: 0,
 | 
					            end: 0,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -196,6 +199,7 @@ impl<'a> Lexer<'a> {
 | 
				
			|||||||
    #[inline]
 | 
					    #[inline]
 | 
				
			||||||
    fn next(&mut self) -> Option<char> {
 | 
					    fn next(&mut self) -> Option<char> {
 | 
				
			||||||
        self.end += 1;
 | 
					        self.end += 1;
 | 
				
			||||||
 | 
					        self.col += 1;
 | 
				
			||||||
        self.chars.next()
 | 
					        self.chars.next()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -236,7 +240,7 @@ impl<'a> Lexer<'a> {
 | 
				
			|||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    is_float = true;
 | 
					                    is_float = true;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                'e' => {
 | 
					                'e' | 'E' => {
 | 
				
			||||||
                    self.next();
 | 
					                    self.next();
 | 
				
			||||||
                    is_float = true;
 | 
					                    is_float = true;
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
@@ -289,6 +293,7 @@ impl<'a> Lexer<'a> {
 | 
				
			|||||||
            "fn" => Keyword(Fn),
 | 
					            "fn" => Keyword(Fn),
 | 
				
			||||||
            "class" => Keyword(Class),
 | 
					            "class" => Keyword(Class),
 | 
				
			||||||
            "module" => Keyword(Module),
 | 
					            "module" => Keyword(Module),
 | 
				
			||||||
 | 
					            "static" => Keyword(Static),
 | 
				
			||||||
            "let" => Keyword(Let),
 | 
					            "let" => Keyword(Let),
 | 
				
			||||||
            "ret" => Keyword(Ret),
 | 
					            "ret" => Keyword(Ret),
 | 
				
			||||||
            "if" => Keyword(If),
 | 
					            "if" => Keyword(If),
 | 
				
			||||||
@@ -400,6 +405,7 @@ impl<'a> Lexer<'a> {
 | 
				
			|||||||
                '\n' => {
 | 
					                '\n' => {
 | 
				
			||||||
                    self.next();
 | 
					                    self.next();
 | 
				
			||||||
                    self.line += 1;
 | 
					                    self.line += 1;
 | 
				
			||||||
 | 
					                    self.col = 0;
 | 
				
			||||||
                    self.new_token(TokenKind::Newline)
 | 
					                    self.new_token(TokenKind::Newline)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                '0'..='9' => self.get_numeric(),
 | 
					                '0'..='9' => self.get_numeric(),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,4 @@
 | 
				
			|||||||
pub mod args;
 | 
					pub mod args;
 | 
				
			||||||
pub mod ast;
 | 
					pub mod ast;
 | 
				
			||||||
pub mod lexer;
 | 
					pub mod lexer;
 | 
				
			||||||
 | 
					pub mod parser;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										14
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								src/main.rs
									
									
									
									
									
								
							@@ -4,10 +4,7 @@ use std::{
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use tricc::args::Args;
 | 
					use tricc::args::Args;
 | 
				
			||||||
use tricc::lexer::{
 | 
					use tricc::parser::Parser;
 | 
				
			||||||
    Lexer,
 | 
					 | 
				
			||||||
    TokenKind,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn main() {
 | 
					fn main() {
 | 
				
			||||||
    panic::set_hook(Box::new(|panic_info| {
 | 
					    panic::set_hook(Box::new(|panic_info| {
 | 
				
			||||||
@@ -30,11 +27,8 @@ fn main() {
 | 
				
			|||||||
    args.handle();
 | 
					    args.handle();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let file = args.get_file();
 | 
					    let file = args.get_file();
 | 
				
			||||||
    let content = fs::read_to_string(&file).expect("Couldn't read the file");
 | 
					    let content = fs::read_to_string(file).expect("Couldn't read the file");
 | 
				
			||||||
 | 
					    let mut parser = Parser::new(&content);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut lexer = Lexer::new(content.as_str());
 | 
					    println!("{:?}", parser.parse());
 | 
				
			||||||
 | 
					 | 
				
			||||||
    while lexer.peek_token().kind != TokenKind::Eof {
 | 
					 | 
				
			||||||
        println!("{:?}", lexer.next_token());
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										206
									
								
								src/parser/entity.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										206
									
								
								src/parser/entity.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,206 @@
 | 
				
			|||||||
 | 
					use super::Parser;
 | 
				
			||||||
 | 
					use crate::ast::*;
 | 
				
			||||||
 | 
					use crate::lexer::{
 | 
				
			||||||
 | 
					    TokenDelimiter,
 | 
				
			||||||
 | 
					    TokenKeyword,
 | 
				
			||||||
 | 
					    TokenKind,
 | 
				
			||||||
 | 
					    TokenSymbol,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					use std::rc::Rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<'a> Parser<'a> {
 | 
				
			||||||
 | 
					    pub(super) fn parse_entity(&mut self) -> Option<Entity> {
 | 
				
			||||||
 | 
					        use TokenKeyword::*;
 | 
				
			||||||
 | 
					        let token = self.peek_token();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if let TokenKind::Keyword(keyword) = &token.kind {
 | 
				
			||||||
 | 
					            match keyword {
 | 
				
			||||||
 | 
					                Module => Some(Entity::Module(self.parse_module()?)),
 | 
				
			||||||
 | 
					                Class => Some(Entity::Class(self.parse_class()?)),
 | 
				
			||||||
 | 
					                Fn => Some(Entity::Fn(self.parse_function()?)),
 | 
				
			||||||
 | 
					                _ => {
 | 
				
			||||||
 | 
					                    self.error_expected_peek("entity");
 | 
				
			||||||
 | 
					                    None
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            self.error_expected_peek("entity");
 | 
				
			||||||
 | 
					            None
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn parse_module(&mut self) -> Option<Module> {
 | 
				
			||||||
 | 
					        self.next_token();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let name = self.parse_ident()?;
 | 
				
			||||||
 | 
					        let mut children = vec![];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if !self.skip_token(TokenKind::Delimiter(TokenDelimiter::BraceOpen)) {
 | 
				
			||||||
 | 
					            self.error_expected_peek("{");
 | 
				
			||||||
 | 
					            return None;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        loop {
 | 
				
			||||||
 | 
					            use TokenKeyword::*;
 | 
				
			||||||
 | 
					            self.trim_newlines();
 | 
				
			||||||
 | 
					            if let TokenKind::Keyword(keyword) = &self.peek_token().kind {
 | 
				
			||||||
 | 
					                children.push(match keyword {
 | 
				
			||||||
 | 
					                    Module => ModuleChildren::Module(self.parse_module()?),
 | 
				
			||||||
 | 
					                    Fn => ModuleChildren::Fn(self.parse_function()?),
 | 
				
			||||||
 | 
					                    Static => ModuleChildren::Static(self.parse_static()?),
 | 
				
			||||||
 | 
					                    Class => ModuleChildren::Class(self.parse_class()?),
 | 
				
			||||||
 | 
					                    _ => {
 | 
				
			||||||
 | 
					                        self.error_expected_peek("module child");
 | 
				
			||||||
 | 
					                        return None;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            } else if !self.skip_token(TokenKind::Delimiter(TokenDelimiter::BraceClose)) {
 | 
				
			||||||
 | 
					                self.error_expected_peek("}");
 | 
				
			||||||
 | 
					                return None;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Some(Module { name, children })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn parse_class(&mut self) -> Option<Class> {
 | 
				
			||||||
 | 
					        self.next_token();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let name = self.parse_ident()?;
 | 
				
			||||||
 | 
					        let mut children = vec![];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if !self.skip_token(TokenKind::Delimiter(TokenDelimiter::BraceOpen)) {
 | 
				
			||||||
 | 
					            self.error_expected_peek("{");
 | 
				
			||||||
 | 
					            return None;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        loop {
 | 
				
			||||||
 | 
					            use TokenKeyword::*;
 | 
				
			||||||
 | 
					            self.trim_newlines();
 | 
				
			||||||
 | 
					            if let TokenKind::Keyword(keyword) = &self.peek_token().kind {
 | 
				
			||||||
 | 
					                children.push(match keyword {
 | 
				
			||||||
 | 
					                    Fn => ClassChildren::Fn(self.parse_function()?),
 | 
				
			||||||
 | 
					                    Static => ClassChildren::Static(self.parse_static()?),
 | 
				
			||||||
 | 
					                    Let => ClassChildren::Let(self.parse_let()?),
 | 
				
			||||||
 | 
					                    _ => {
 | 
				
			||||||
 | 
					                        self.error_expected_peek("class child");
 | 
				
			||||||
 | 
					                        return None;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            } else if !self.skip_token(TokenKind::Delimiter(TokenDelimiter::BraceClose)) {
 | 
				
			||||||
 | 
					                self.error_expected_peek("}");
 | 
				
			||||||
 | 
					                return None;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Some(Class { name, children })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn parse_function(&mut self) -> Option<Fn> {
 | 
				
			||||||
 | 
					        self.next_token();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let name = self.parse_ident()?;
 | 
				
			||||||
 | 
					        let mut params: Vec<(Rc<str>, Ty)> = vec![];
 | 
				
			||||||
 | 
					        let mut return_typ: Option<Ty> = None;
 | 
				
			||||||
 | 
					        let mut children: Vec<Statement> = vec![];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if !self.skip_token(TokenKind::Delimiter(TokenDelimiter::ParenOpen)) {
 | 
				
			||||||
 | 
					            self.error_expected_peek("(");
 | 
				
			||||||
 | 
					            return None;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        loop {
 | 
				
			||||||
 | 
					            if self.peek_token().kind == TokenKind::Identifier {
 | 
				
			||||||
 | 
					                params.push(self.parse_ident_with_type()?);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if !self.skip_token(TokenKind::Symbol(TokenSymbol::Comma)) {
 | 
				
			||||||
 | 
					                if !self.skip_token(TokenKind::Delimiter(TokenDelimiter::ParenClose)) {
 | 
				
			||||||
 | 
					                    self.error_expected_peek(", or )");
 | 
				
			||||||
 | 
					                    return None;
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if self.skip_token(TokenKind::Symbol(TokenSymbol::Colon)) {
 | 
				
			||||||
 | 
					            return_typ = Some(self.parse_ty()?);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if !self.skip_token(TokenKind::Delimiter(TokenDelimiter::BraceOpen)) {
 | 
				
			||||||
 | 
					            self.error_expected_peek("{");
 | 
				
			||||||
 | 
					            return None;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        loop {
 | 
				
			||||||
 | 
					            self.trim_newlines();
 | 
				
			||||||
 | 
					            if self.skip_token(TokenKind::Delimiter(TokenDelimiter::BraceClose)) {
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            children.push(self.parse_statement()?)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Some(Fn {
 | 
				
			||||||
 | 
					            name,
 | 
				
			||||||
 | 
					            return_ty: return_typ,
 | 
				
			||||||
 | 
					            params,
 | 
				
			||||||
 | 
					            children,
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[test]
 | 
				
			||||||
 | 
					fn test_parse_entity() {
 | 
				
			||||||
 | 
					    let mut parser = Parser::new(
 | 
				
			||||||
 | 
					        r#"module module01 {
 | 
				
			||||||
 | 
					             class class01 {
 | 
				
			||||||
 | 
					               fn fn01(param01: char, param02: float) {
 | 
				
			||||||
 | 
					                 static let let01: int = 4
 | 
				
			||||||
 | 
					               }
 | 
				
			||||||
 | 
					             }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					             fn fn02(): int {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }"#,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    assert_eq!(
 | 
				
			||||||
 | 
					        parser.parse_entity(),
 | 
				
			||||||
 | 
					        Some(Entity::Module(Module {
 | 
				
			||||||
 | 
					            name: "module01".into(),
 | 
				
			||||||
 | 
					            children: vec![
 | 
				
			||||||
 | 
					                ModuleChildren::Class(Class {
 | 
				
			||||||
 | 
					                    name: "class01".into(),
 | 
				
			||||||
 | 
					                    children: vec![ClassChildren::Fn(Fn {
 | 
				
			||||||
 | 
					                        name: "fn01".into(),
 | 
				
			||||||
 | 
					                        return_ty: None,
 | 
				
			||||||
 | 
					                        params: vec![("param01".into(), Ty::Char), ("param02".into(), Ty::Float)],
 | 
				
			||||||
 | 
					                        children: vec![Statement::Static(Let {
 | 
				
			||||||
 | 
					                            name: "let01".into(),
 | 
				
			||||||
 | 
					                            ty: Ty::Int,
 | 
				
			||||||
 | 
					                            expr: Some(Expr::Int(4))
 | 
				
			||||||
 | 
					                        })]
 | 
				
			||||||
 | 
					                    })]
 | 
				
			||||||
 | 
					                }),
 | 
				
			||||||
 | 
					                ModuleChildren::Fn(Fn {
 | 
				
			||||||
 | 
					                    name: "fn02".into(),
 | 
				
			||||||
 | 
					                    return_ty: Some(Ty::Int),
 | 
				
			||||||
 | 
					                    params: vec![],
 | 
				
			||||||
 | 
					                    children: vec![]
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        }))
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										109
									
								
								src/parser/expr.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								src/parser/expr.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,109 @@
 | 
				
			|||||||
 | 
					use super::Parser;
 | 
				
			||||||
 | 
					use crate::ast::*;
 | 
				
			||||||
 | 
					use crate::lexer::{
 | 
				
			||||||
 | 
					    TokenKeyword,
 | 
				
			||||||
 | 
					    TokenKind,
 | 
				
			||||||
 | 
					    TokenLiteral,
 | 
				
			||||||
 | 
					    TokenSymbol,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<'a> Parser<'a> {
 | 
				
			||||||
 | 
					    pub(super) fn parse_statement(&mut self) -> Option<Statement> {
 | 
				
			||||||
 | 
					        use TokenKeyword::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        match self.peek_token().kind {
 | 
				
			||||||
 | 
					            TokenKind::Keyword(Static) => Some(Statement::Static(self.parse_static()?)),
 | 
				
			||||||
 | 
					            TokenKind::Keyword(Let) => Some(Statement::Let(self.parse_let()?)),
 | 
				
			||||||
 | 
					            _ => Some(Statement::Expr(self.parse_expr()?)),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub(super) fn parse_static(&mut self) -> Option<Let> {
 | 
				
			||||||
 | 
					        self.next_token();
 | 
				
			||||||
 | 
					        if self.peek_token().kind != TokenKind::Keyword(TokenKeyword::Let) {
 | 
				
			||||||
 | 
					            self.error_expected_peek("let");
 | 
				
			||||||
 | 
					            return None;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.parse_let()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub(super) fn parse_let(&mut self) -> Option<Let> {
 | 
				
			||||||
 | 
					        self.next_token();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let (name, ty) = self.parse_ident_with_type()?;
 | 
				
			||||||
 | 
					        let expr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if self.skip_token(TokenKind::Symbol(TokenSymbol::Eq)) {
 | 
				
			||||||
 | 
					            expr = Some(self.parse_expr()?);
 | 
				
			||||||
 | 
					            self.trim_newlines();
 | 
				
			||||||
 | 
					        } else if self.skip_token(TokenKind::Newline) {
 | 
				
			||||||
 | 
					            expr = None;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            self.error_expected_peek("= or newline");
 | 
				
			||||||
 | 
					            return None;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Some(Let { name, ty, expr })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn parse_expr(&mut self) -> Option<Expr> {
 | 
				
			||||||
 | 
					        use TokenKind::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        match self.peek_token().kind {
 | 
				
			||||||
 | 
					            Literal(TokenLiteral::Int) => Some(Expr::Int(self.parse_int()?)),
 | 
				
			||||||
 | 
					            Literal(TokenLiteral::Float) => Some(Expr::Float(self.parse_float()?)),
 | 
				
			||||||
 | 
					            Literal(TokenLiteral::Char) => Some(Expr::Char(self.parse_char()?)),
 | 
				
			||||||
 | 
					            _ => {
 | 
				
			||||||
 | 
					                self.error_expected_peek("expression");
 | 
				
			||||||
 | 
					                None
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[test]
 | 
				
			||||||
 | 
					fn test_parse_let() {
 | 
				
			||||||
 | 
					    let mut parser = Parser::new(
 | 
				
			||||||
 | 
					        r#"static let test01: int = 4
 | 
				
			||||||
 | 
					           let test02: char = '6'
 | 
				
			||||||
 | 
					           static let test03: float
 | 
				
			||||||
 | 
					           let test04 = 9"#,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    assert_eq!(
 | 
				
			||||||
 | 
					        parser.parse_static(),
 | 
				
			||||||
 | 
					        Some(Let {
 | 
				
			||||||
 | 
					            name: "test01".into(),
 | 
				
			||||||
 | 
					            ty: Ty::Int,
 | 
				
			||||||
 | 
					            expr: Some(Expr::Int(4))
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    assert_eq!(
 | 
				
			||||||
 | 
					        parser.parse_let(),
 | 
				
			||||||
 | 
					        Some(Let {
 | 
				
			||||||
 | 
					            name: "test02".into(),
 | 
				
			||||||
 | 
					            ty: Ty::Char,
 | 
				
			||||||
 | 
					            expr: Some(Expr::Char('6'))
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    assert_eq!(
 | 
				
			||||||
 | 
					        parser.parse_static(),
 | 
				
			||||||
 | 
					        Some(Let {
 | 
				
			||||||
 | 
					            name: "test03".into(),
 | 
				
			||||||
 | 
					            ty: Ty::Float,
 | 
				
			||||||
 | 
					            expr: None
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    assert_eq!(parser.parse_let(), None);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[test]
 | 
				
			||||||
 | 
					fn test_parse_expr_literals() {
 | 
				
			||||||
 | 
					    let mut parser = Parser::new("4524 3123.15e4 9e2 9083482.429455 'c' 3331.13.3");
 | 
				
			||||||
 | 
					    assert_eq!(parser.parse_expr(), Some(Expr::Int(4524)));
 | 
				
			||||||
 | 
					    assert_eq!(parser.parse_expr(), Some(Expr::Float(3123.15e4)));
 | 
				
			||||||
 | 
					    assert_eq!(parser.parse_expr(), Some(Expr::Float(9e2)));
 | 
				
			||||||
 | 
					    assert_eq!(parser.parse_expr(), Some(Expr::Float(9083482.429455)));
 | 
				
			||||||
 | 
					    assert_eq!(parser.parse_expr(), Some(Expr::Char('c')));
 | 
				
			||||||
 | 
					    assert_eq!(parser.parse_expr(), None);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										100
									
								
								src/parser/literal.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								src/parser/literal.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,100 @@
 | 
				
			|||||||
 | 
					use super::Parser;
 | 
				
			||||||
 | 
					use crate::lexer::{
 | 
				
			||||||
 | 
					    TokenKind,
 | 
				
			||||||
 | 
					    TokenSymbol,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<'a> Parser<'a> {
 | 
				
			||||||
 | 
					    pub(super) fn parse_int(&mut self) -> Option<i32> {
 | 
				
			||||||
 | 
					        let val = self.next_token().val;
 | 
				
			||||||
 | 
					        let mut integer: i32 = 0;
 | 
				
			||||||
 | 
					        let error = || {
 | 
				
			||||||
 | 
					            self.error(&format!(
 | 
				
			||||||
 | 
					                "integer values must be in range [{}, {}]",
 | 
				
			||||||
 | 
					                i32::MIN,
 | 
				
			||||||
 | 
					                i32::MAX
 | 
				
			||||||
 | 
					            ))
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for c in val.chars() {
 | 
				
			||||||
 | 
					            // c is always ['0'..='9']
 | 
				
			||||||
 | 
					            let d = c.to_digit(10)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            match integer.checked_mul(10) {
 | 
				
			||||||
 | 
					                Some(m) => integer = m,
 | 
				
			||||||
 | 
					                None => {
 | 
				
			||||||
 | 
					                    error();
 | 
				
			||||||
 | 
					                    return None;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            match integer.checked_add(d as i32) {
 | 
				
			||||||
 | 
					                Some(a) => integer = a,
 | 
				
			||||||
 | 
					                None => {
 | 
				
			||||||
 | 
					                    error();
 | 
				
			||||||
 | 
					                    return None;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Some(integer)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// f32 can be NaN and inf as well
 | 
				
			||||||
 | 
					    pub(super) fn parse_float(&mut self) -> Option<f32> {
 | 
				
			||||||
 | 
					        let token = self.next_token();
 | 
				
			||||||
 | 
					        let mut chars = token.val.chars();
 | 
				
			||||||
 | 
					        let mut float: f32 = 0.0;
 | 
				
			||||||
 | 
					        let mut fraction: f32 = 0.0;
 | 
				
			||||||
 | 
					        let mut prec: i32 = 0;
 | 
				
			||||||
 | 
					        let mut exp: i32 = 0;
 | 
				
			||||||
 | 
					        let mut decimal: bool = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // lexer takes care of multiple decimals and non digit characters
 | 
				
			||||||
 | 
					        for c in chars.by_ref() {
 | 
				
			||||||
 | 
					            match c {
 | 
				
			||||||
 | 
					                '.' => decimal = true,
 | 
				
			||||||
 | 
					                'e' | 'E' => {
 | 
				
			||||||
 | 
					                    // lexer takes care that decimal doesnt come after e
 | 
				
			||||||
 | 
					                    let s;
 | 
				
			||||||
 | 
					                    match self.peek_token().kind {
 | 
				
			||||||
 | 
					                        TokenKind::Symbol(TokenSymbol::Minus) => {
 | 
				
			||||||
 | 
					                            s = -1;
 | 
				
			||||||
 | 
					                            self.next_token();
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        TokenKind::Symbol(TokenSymbol::Plus) => {
 | 
				
			||||||
 | 
					                            s = 1;
 | 
				
			||||||
 | 
					                            self.next_token();
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        _ => s = 1,
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    exp = self.parse_int()? * s;
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                _ => {
 | 
				
			||||||
 | 
					                    // c is always ['0'..='9']
 | 
				
			||||||
 | 
					                    let d = c.to_digit(10)? as f32;
 | 
				
			||||||
 | 
					                    if decimal {
 | 
				
			||||||
 | 
					                        fraction *= 10.0;
 | 
				
			||||||
 | 
					                        fraction += d;
 | 
				
			||||||
 | 
					                        prec += 1;
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        float *= 10.0;
 | 
				
			||||||
 | 
					                        float += d;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        fraction /= 10f32.powi(prec);
 | 
				
			||||||
 | 
					        float += fraction;
 | 
				
			||||||
 | 
					        float *= 10f32.powi(exp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Some(float)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub(super) fn parse_char(&mut self) -> Option<char> {
 | 
				
			||||||
 | 
					        // the lexer ensures that the 0th and 2nd characters are both '
 | 
				
			||||||
 | 
					        self.next_token().val.chars().nth(1)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										136
									
								
								src/parser/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								src/parser/mod.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,136 @@
 | 
				
			|||||||
 | 
					//! A naive parser just to get started
 | 
				
			||||||
 | 
					//!
 | 
				
			||||||
 | 
					//! Can only parse module, class and function declaration now along with let statements
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mod entity;
 | 
				
			||||||
 | 
					mod expr;
 | 
				
			||||||
 | 
					mod literal;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use crate::ast::{
 | 
				
			||||||
 | 
					    Parent,
 | 
				
			||||||
 | 
					    Ty,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					use crate::lexer::{
 | 
				
			||||||
 | 
					    Lexer,
 | 
				
			||||||
 | 
					    Token,
 | 
				
			||||||
 | 
					    TokenKeyword,
 | 
				
			||||||
 | 
					    TokenKind,
 | 
				
			||||||
 | 
					    TokenSymbol,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					use std::rc::Rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct Parser<'a> {
 | 
				
			||||||
 | 
					    pub lexer: Lexer<'a>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<'a> Parser<'a> {
 | 
				
			||||||
 | 
					    /// Creates a new [`Parser`] instance.
 | 
				
			||||||
 | 
					    pub fn new(contents: &'a str) -> Parser<'a> {
 | 
				
			||||||
 | 
					        Parser {
 | 
				
			||||||
 | 
					            lexer: Lexer::new(contents),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[inline]
 | 
				
			||||||
 | 
					    fn error(&self, message: &str) {
 | 
				
			||||||
 | 
					        eprintln!(
 | 
				
			||||||
 | 
					            "Parser: {}, at \"{}:{}\"",
 | 
				
			||||||
 | 
					            message, self.lexer.line, self.lexer.col
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[inline]
 | 
				
			||||||
 | 
					    fn error_expected(&self, expected: &str, found: &str) {
 | 
				
			||||||
 | 
					        self.error(&format!("expected {}, found {}", expected, found));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[inline]
 | 
				
			||||||
 | 
					    fn error_expected_peek(&mut self, expected: &str) {
 | 
				
			||||||
 | 
					        let found = &Rc::clone(&self.peek_token().val);
 | 
				
			||||||
 | 
					        self.error_expected(expected, found);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[inline]
 | 
				
			||||||
 | 
					    fn next_token(&mut self) -> Token {
 | 
				
			||||||
 | 
					        self.lexer.next_token()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[inline]
 | 
				
			||||||
 | 
					    fn peek_token(&mut self) -> &Token {
 | 
				
			||||||
 | 
					        return self.lexer.peek_token();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn trim_newlines(&mut self) {
 | 
				
			||||||
 | 
					        while self.peek_token().kind == TokenKind::Newline {
 | 
				
			||||||
 | 
					            self.next_token();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn skip_token(&mut self, kind: TokenKind) -> bool {
 | 
				
			||||||
 | 
					        if self.peek_token().kind == kind {
 | 
				
			||||||
 | 
					            self.next_token();
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        false
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn parse_ty(&mut self) -> Option<Ty> {
 | 
				
			||||||
 | 
					        let ty: Ty;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if let TokenKind::Keyword(keyword) = &self.peek_token().kind {
 | 
				
			||||||
 | 
					            ty = match keyword {
 | 
				
			||||||
 | 
					                TokenKeyword::Int => Ty::Int,
 | 
				
			||||||
 | 
					                TokenKeyword::Char => Ty::Char,
 | 
				
			||||||
 | 
					                TokenKeyword::Float => Ty::Float,
 | 
				
			||||||
 | 
					                _ => {
 | 
				
			||||||
 | 
					                    self.error_expected_peek("ty");
 | 
				
			||||||
 | 
					                    return None;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            self.error_expected_peek("ty");
 | 
				
			||||||
 | 
					            return None;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        self.next_token();
 | 
				
			||||||
 | 
					        Some(ty)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn parse_ident(&mut self) -> Option<Rc<str>> {
 | 
				
			||||||
 | 
					        if self.peek_token().kind != TokenKind::Identifier {
 | 
				
			||||||
 | 
					            self.error_expected_peek("identifier");
 | 
				
			||||||
 | 
					            return None;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Some(Rc::clone(&self.next_token().val))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn parse_ident_with_type(&mut self) -> Option<(Rc<str>, Ty)> {
 | 
				
			||||||
 | 
					        let ident = self.parse_ident()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if !self.skip_token(TokenKind::Symbol(TokenSymbol::Colon)) {
 | 
				
			||||||
 | 
					            self.error_expected_peek(":");
 | 
				
			||||||
 | 
					            return None;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Some((ident, self.parse_ty()?))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Returns an [`Entity`] vector after parsing
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// [`Entity`]: crate::ast::Entity
 | 
				
			||||||
 | 
					    pub fn parse(&mut self) -> Option<Parent> {
 | 
				
			||||||
 | 
					        let mut parent = vec![];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        loop {
 | 
				
			||||||
 | 
					            match self.peek_token().kind {
 | 
				
			||||||
 | 
					                TokenKind::Newline => self.trim_newlines(),
 | 
				
			||||||
 | 
					                TokenKind::Eof => break,
 | 
				
			||||||
 | 
					                _ => {
 | 
				
			||||||
 | 
					                    parent.push(self.parse_entity()?);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Some(parent)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user