wip
This commit is contained in:
		
							
								
								
									
										16
									
								
								src/ast.rs
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								src/ast.rs
									
									
									
									
									
								
							| @@ -4,20 +4,28 @@ pub struct Module { | ||||
|     pub statements: Vec<Statement>, | ||||
| } | ||||
|  | ||||
| #[derive(Debug)] | ||||
| pub enum Statement { | ||||
|     FunctionDeclaration { | ||||
|         name: Token, | ||||
|         parameters: Vec<ParameterDeclaration>, | ||||
|         statements: Vec<Statement>, | ||||
|     }, | ||||
|     Expression, | ||||
|     Expression(Expression), | ||||
| } | ||||
|  | ||||
| #[derive(Debug)] | ||||
| pub struct ParameterDeclaration { | ||||
|     name: Token, | ||||
|     typename: Token, | ||||
|     pub name: Token, | ||||
|     pub typename: Token, | ||||
| } | ||||
|  | ||||
| #[derive(Debug)] | ||||
| pub enum Expression { | ||||
|     Identifier(Token), | ||||
|     FunctionCall {}, | ||||
|     FunctionCall { | ||||
|         function: Box<Expression>, | ||||
|         arguments: Vec<Expression>, | ||||
|         return_type: Option<Token>, | ||||
|     }, | ||||
| } | ||||
|   | ||||
							
								
								
									
										29
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								src/main.rs
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| use token::Token; | ||||
| use parse::Parser; | ||||
|  | ||||
| mod ast; | ||||
| mod format; | ||||
| @@ -7,34 +7,21 @@ mod parse; | ||||
| mod token; | ||||
|  | ||||
| fn main() { | ||||
|     println!("Hello, world!"); | ||||
| } | ||||
|  | ||||
| #[cfg(test)] | ||||
| mod tests { | ||||
|     use crate::{ | ||||
|         format::Formatter, | ||||
|         lexer::{self, Lexer}, | ||||
|     }; | ||||
|  | ||||
|     use format::Formatter; | ||||
|     use lexer::Lexer; | ||||
|     const BASIC: &str = r#" | ||||
| function hello(name: string){ | ||||
|    console.log("Hey, ", name);  | ||||
|    println("Hey, ", name);  | ||||
| } | ||||
|  | ||||
|  | ||||
| console.log("Starting!"); | ||||
| println("Starting!"); | ||||
|  | ||||
| hello(); | ||||
| "#; | ||||
|     #[test] | ||||
|     fn lex() { | ||||
|         println!("Running lex"); | ||||
|     let lexer = Lexer::new(BASIC, Some("basic.file".to_string())); | ||||
|     let tokens = lexer.lex(); | ||||
|         println!( | ||||
|             "{}", | ||||
|             tokens.format(crate::format::FormatterOptions {}).unwrap() | ||||
|         ); | ||||
|     } | ||||
|     let mut parser = Parser::new(tokens); | ||||
|     let statement = parser.statement(); | ||||
|     println!("{statement:?}"); | ||||
| } | ||||
|   | ||||
							
								
								
									
										13
									
								
								src/parse.rs
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								src/parse.rs
									
									
									
									
									
								
							| @@ -1,13 +0,0 @@ | ||||
| use crate::token::Token; | ||||
|  | ||||
| pub struct Parser { | ||||
|     tokens: Vec<Token>, | ||||
| } | ||||
|  | ||||
| impl Parser { | ||||
|     pub fn new(tokens: Vec<Token>) -> Parser { | ||||
|         Self { tokens } | ||||
|     } | ||||
|  | ||||
|     fn parse(&mut self) {} | ||||
| } | ||||
							
								
								
									
										55
									
								
								src/parse/macros.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								src/parse/macros.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | ||||
| #[macro_export] | ||||
| macro_rules! expect_token { | ||||
|     ($self:ident, $expect:pat) => { | ||||
|         let t = $self.consume(); | ||||
|         if !matches!(t.kind, $expect) { | ||||
|             todo!("Expected token, found {:?}", t.kind) | ||||
|         } | ||||
|     }; | ||||
| } | ||||
|  | ||||
| #[macro_export] | ||||
| macro_rules! expect_identifier { | ||||
|     ($self:ident) => {{ | ||||
|         let t = $self.consume(); | ||||
|         if !matches!(t.kind, TokenKind::Identifier(_)) { | ||||
|             todo!("Expected token, found {:?}", t.kind) | ||||
|         } | ||||
|         t | ||||
|     }}; | ||||
| } | ||||
|  | ||||
| #[macro_export] | ||||
| macro_rules! expect_any_keyword { | ||||
|     ($self:ident) => {{ | ||||
|         let t = $self.consume(); | ||||
|         if !matches!(t.kind, TokenKind::Keyword(_)) { | ||||
|             todo!("Expected token, found {:?}", t.kind) | ||||
|         } | ||||
|         t | ||||
|     }}; | ||||
| } | ||||
|  | ||||
| #[macro_export] | ||||
| macro_rules! expect_keyword { | ||||
|     ($self:ident, $keyword:pat) => { | ||||
|         let t = $self.consume(); | ||||
|         if !matches!(t.kind, TokenKind::Keyword($keyword)) { | ||||
|             todo!("Expected token, found {:?}", t.kind) | ||||
|         } | ||||
|     }; | ||||
| } | ||||
|  | ||||
| #[macro_export] | ||||
| macro_rules! peek_keyword { | ||||
|     ($self:ident, $keyword:pat) => { | ||||
|         matches!($self.peek().kind, TokenKind::Keyword($keyword)) | ||||
|     }; | ||||
| } | ||||
|  | ||||
| #[macro_export] | ||||
| macro_rules! peek_match { | ||||
|     ($self:ident, $p:pat) => { | ||||
|         matches!($self.peek().kind, $p) | ||||
|     }; | ||||
| } | ||||
							
								
								
									
										77
									
								
								src/parse/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/parse/mod.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | ||||
| mod macros; | ||||
|  | ||||
| use crate::{ | ||||
|     ast, expect_any_keyword, expect_identifier, expect_keyword, expect_token, peek_keyword, | ||||
|     peek_match, | ||||
|     token::{KeywordKind, Token, TokenKind}, | ||||
| }; | ||||
|  | ||||
| pub struct Parser { | ||||
|     tokens: Vec<Token>, | ||||
|     current: usize, | ||||
| } | ||||
|  | ||||
| impl Parser { | ||||
|     pub fn new(tokens: Vec<Token>) -> Parser { | ||||
|         Self { tokens, current: 0 } | ||||
|     } | ||||
|  | ||||
|     pub fn statement(&mut self) -> ast::Statement { | ||||
|         if peek_keyword!(self, KeywordKind::function) { | ||||
|             return self.function_declaration(); | ||||
|         } | ||||
|         return self.expression_statement(); | ||||
|         todo!("No statement"); | ||||
|     } | ||||
|  | ||||
|     fn function_declaration(&mut self) -> ast::Statement { | ||||
|         expect_keyword!(self, KeywordKind::function); | ||||
|         let id = expect_identifier!(self); | ||||
|         expect_token!(self, TokenKind::LeftParen); | ||||
|  | ||||
|         let mut parameters = Vec::new(); | ||||
|         while peek_match!(self, TokenKind::Identifier(_)) { | ||||
|             let name = expect_identifier!(self); | ||||
|             expect_token!(self, TokenKind::Colon); | ||||
|             let typename = expect_any_keyword!(self); | ||||
|             let parameter = ast::ParameterDeclaration { | ||||
|                 name: name.clone(), | ||||
|                 typename: typename.clone(), | ||||
|             }; | ||||
|             parameters.push(parameter); | ||||
|         } | ||||
|  | ||||
|         expect_token!(self, TokenKind::RightParen); | ||||
|  | ||||
|         expect_token!(self, TokenKind::LeftCurly); | ||||
|  | ||||
|         let mut statements = Vec::new(); | ||||
|         while !peek_match!(self, TokenKind::RightCurly) { | ||||
|             let statement = self.statement(); | ||||
|             statements.push(statement); | ||||
|         } | ||||
|  | ||||
|         expect_token!(self, TokenKind::RightCurly); | ||||
|  | ||||
|         ast::Statement::FunctionDeclaration { | ||||
|             name: id.clone(), | ||||
|             parameters, | ||||
|             statements, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn expression_statement(&mut self) -> ast::Statement { | ||||
|         todo!() | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Parser { | ||||
|     fn peek(&self) -> &Token { | ||||
|         &self.tokens[self.current] | ||||
|     } | ||||
|     fn consume(&mut self) -> Token { | ||||
|         let token = &self.tokens[self.current]; | ||||
|         self.current += 1; | ||||
|         token.clone() | ||||
|     } | ||||
| } | ||||
							
								
								
									
										14
									
								
								src/token.rs
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								src/token.rs
									
									
									
									
									
								
							| @@ -1,12 +1,12 @@ | ||||
| use anyhow::anyhow; | ||||
|  | ||||
| #[derive(Debug)] | ||||
| #[derive(Debug, Clone)] | ||||
| pub struct Token { | ||||
|     pub kind: TokenKind, | ||||
|     pub location: TokenLocation, | ||||
| } | ||||
|  | ||||
| #[derive(Debug)] | ||||
| #[derive(Debug, Clone)] | ||||
| pub enum TokenKind { | ||||
|     Identifier(String), | ||||
|     Literal(LiteralKind), | ||||
| @@ -25,14 +25,14 @@ pub enum TokenKind { | ||||
|     EndOfFile, | ||||
| } | ||||
|  | ||||
| #[derive(Debug)] | ||||
| #[derive(Debug, Clone)] | ||||
| pub enum CommentKind { | ||||
|     Line, | ||||
|     Block, | ||||
| } | ||||
|  | ||||
| #[allow(non_camel_case_types)] | ||||
| #[derive(Debug)] | ||||
| #[derive(Debug, Clone)] | ||||
| pub enum KeywordKind { | ||||
|     function, | ||||
|     string, | ||||
| @@ -51,19 +51,19 @@ impl TryFrom<&str> for KeywordKind { | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[derive(Debug)] | ||||
| #[derive(Debug, Clone)] | ||||
| pub enum LiteralKind { | ||||
|     String(String), | ||||
|     Number(Number), | ||||
| } | ||||
|  | ||||
| #[derive(Debug)] | ||||
| #[derive(Debug, Clone)] | ||||
| pub enum Number { | ||||
|     Integer(usize), | ||||
|     Float(f64), | ||||
| } | ||||
|  | ||||
| #[derive(Debug)] | ||||
| #[derive(Debug, Clone)] | ||||
| pub struct TokenLocation { | ||||
|     pub file: Option<String>, | ||||
|     pub line: usize, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user