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>, |     pub statements: Vec<Statement>, | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #[derive(Debug)] | ||||||
| pub enum Statement { | pub enum Statement { | ||||||
|     FunctionDeclaration { |     FunctionDeclaration { | ||||||
|         name: Token, |         name: Token, | ||||||
|         parameters: Vec<ParameterDeclaration>, |         parameters: Vec<ParameterDeclaration>, | ||||||
|  |         statements: Vec<Statement>, | ||||||
|     }, |     }, | ||||||
|     Expression, |     Expression(Expression), | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #[derive(Debug)] | ||||||
| pub struct ParameterDeclaration { | pub struct ParameterDeclaration { | ||||||
|     name: Token, |     pub name: Token, | ||||||
|     typename: Token, |     pub typename: Token, | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #[derive(Debug)] | ||||||
| pub enum Expression { | pub enum Expression { | ||||||
|     Identifier(Token), |     Identifier(Token), | ||||||
|     FunctionCall {}, |     FunctionCall { | ||||||
|  |         function: Box<Expression>, | ||||||
|  |         arguments: Vec<Expression>, | ||||||
|  |         return_type: Option<Token>, | ||||||
|  |     }, | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										33
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								src/main.rs
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| use token::Token; | use parse::Parser; | ||||||
|  |  | ||||||
| mod ast; | mod ast; | ||||||
| mod format; | mod format; | ||||||
| @@ -7,34 +7,21 @@ mod parse; | |||||||
| mod token; | mod token; | ||||||
|  |  | ||||||
| fn main() { | fn main() { | ||||||
|     println!("Hello, world!"); |     use format::Formatter; | ||||||
| } |     use lexer::Lexer; | ||||||
|  |  | ||||||
| #[cfg(test)] |  | ||||||
| mod tests { |  | ||||||
|     use crate::{ |  | ||||||
|         format::Formatter, |  | ||||||
|         lexer::{self, Lexer}, |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     const BASIC: &str = r#" |     const BASIC: &str = r#" | ||||||
| function hello(name: string){ | function hello(name: string){ | ||||||
|    console.log("Hey, ", name);  |    println("Hey, ", name);  | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| console.log("Starting!"); | println("Starting!"); | ||||||
|  |  | ||||||
| hello(); | hello(); | ||||||
| "#; | "#; | ||||||
|     #[test] |     let lexer = Lexer::new(BASIC, Some("basic.file".to_string())); | ||||||
|     fn lex() { |     let tokens = lexer.lex(); | ||||||
|         println!("Running lex"); |     let mut parser = Parser::new(tokens); | ||||||
|         let lexer = Lexer::new(BASIC, Some("basic.file".to_string())); |     let statement = parser.statement(); | ||||||
|         let tokens = lexer.lex(); |     println!("{statement:?}"); | ||||||
|         println!( |  | ||||||
|             "{}", |  | ||||||
|             tokens.format(crate::format::FormatterOptions {}).unwrap() |  | ||||||
|         ); |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										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; | use anyhow::anyhow; | ||||||
|  |  | ||||||
| #[derive(Debug)] | #[derive(Debug, Clone)] | ||||||
| pub struct Token { | pub struct Token { | ||||||
|     pub kind: TokenKind, |     pub kind: TokenKind, | ||||||
|     pub location: TokenLocation, |     pub location: TokenLocation, | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Debug)] | #[derive(Debug, Clone)] | ||||||
| pub enum TokenKind { | pub enum TokenKind { | ||||||
|     Identifier(String), |     Identifier(String), | ||||||
|     Literal(LiteralKind), |     Literal(LiteralKind), | ||||||
| @@ -25,14 +25,14 @@ pub enum TokenKind { | |||||||
|     EndOfFile, |     EndOfFile, | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Debug)] | #[derive(Debug, Clone)] | ||||||
| pub enum CommentKind { | pub enum CommentKind { | ||||||
|     Line, |     Line, | ||||||
|     Block, |     Block, | ||||||
| } | } | ||||||
|  |  | ||||||
| #[allow(non_camel_case_types)] | #[allow(non_camel_case_types)] | ||||||
| #[derive(Debug)] | #[derive(Debug, Clone)] | ||||||
| pub enum KeywordKind { | pub enum KeywordKind { | ||||||
|     function, |     function, | ||||||
|     string, |     string, | ||||||
| @@ -51,19 +51,19 @@ impl TryFrom<&str> for KeywordKind { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Debug)] | #[derive(Debug, Clone)] | ||||||
| pub enum LiteralKind { | pub enum LiteralKind { | ||||||
|     String(String), |     String(String), | ||||||
|     Number(Number), |     Number(Number), | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Debug)] | #[derive(Debug, Clone)] | ||||||
| pub enum Number { | pub enum Number { | ||||||
|     Integer(usize), |     Integer(usize), | ||||||
|     Float(f64), |     Float(f64), | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Debug)] | #[derive(Debug, Clone)] | ||||||
| pub struct TokenLocation { | pub struct TokenLocation { | ||||||
|     pub file: Option<String>, |     pub file: Option<String>, | ||||||
|     pub line: usize, |     pub line: usize, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user