This commit is contained in:
2025-05-28 03:41:40 +02:00
parent d8422261f6
commit 3125ee5a96
6 changed files with 161 additions and 47 deletions

View File

@ -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>,
},
} }

View File

@ -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()
);
}
} }

View File

@ -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
View 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
View 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()
}
}

View File

@ -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,