mirror of
https://git.fddl.dev/fddl/fddl.git
synced 2024-12-25 21:50:31 +00:00
building parser
This commit is contained in:
parent
6273dbdd7b
commit
c08f292bd8
7 changed files with 142 additions and 24 deletions
|
@ -1,3 +1,3 @@
|
|||
func main() {
|
||||
print(`hello, world in fddl`);
|
||||
print("hello, world in fddl");
|
||||
}
|
||||
|
|
5
hello.fddl
Normal file
5
hello.fddl
Normal file
|
@ -0,0 +1,5 @@
|
|||
!test
|
||||
|
||||
func main() {
|
||||
print("Hello World");
|
||||
}
|
29
readme.md
29
readme.md
|
@ -27,11 +27,20 @@ To start experimenting with fddl, you can run it in two ways:
|
|||
cargo run
|
||||
```
|
||||
|
||||
### Run a fddl Script
|
||||
### Parse a fddl Script
|
||||
```sh
|
||||
cargo run path/to/script.fddl
|
||||
```
|
||||
|
||||
## Running the Project
|
||||
|
||||
Make sure your project compiles and the tests pass:
|
||||
|
||||
```bash
|
||||
cargo build
|
||||
cargo test
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
@ -77,7 +86,7 @@ fddl is very much a work in progress, with lots of planned improvements and addi
|
|||
- [ ] Currently a placeholder. Implement parsing for function calls, expressions, etc.
|
||||
|
||||
- **Compiler**:
|
||||
- [ ] Currently a placeholder. Implement the compiler to execute parsed code.
|
||||
- [ ] Currently a placeholder. Implement the compiler to compile parsed code.
|
||||
|
||||
- **Comments**:
|
||||
- [x] Added support for single-line and documentation comments.
|
||||
|
@ -85,26 +94,14 @@ fddl is very much a work in progress, with lots of planned improvements and addi
|
|||
- [ ] Implement document building comments.
|
||||
|
||||
- **Error Handling**:
|
||||
- [ ] Replace basic error reporting with a more robust error handling mechanism.
|
||||
|
||||
- **String Interpolation**:
|
||||
- [ ] Implement string interpolation using backticks with `$variable` syntax.
|
||||
- [ ] Replace `stderr` with a more robust error handling mechanism.
|
||||
|
||||
- **Testing**:
|
||||
- [x] Added initial lexer tests.
|
||||
- [x] Added initial `lexer` tests.
|
||||
- [ ] Expand tests to cover more syntax and edge cases.
|
||||
|
||||
---
|
||||
|
||||
## Running the Project
|
||||
|
||||
Make sure your project compiles and the tests pass:
|
||||
|
||||
```bash
|
||||
cargo build
|
||||
cargo test
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the MIT License.
|
||||
|
|
|
@ -23,7 +23,12 @@ impl Lexer {
|
|||
while !self.is_at_end() {
|
||||
self.start = self.current;
|
||||
if let Some(token) = self.scan_token() {
|
||||
if matches!(token, Token::Error(_)) {
|
||||
tokens.push(token);
|
||||
break;
|
||||
} else {
|
||||
tokens.push(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,7 +76,7 @@ impl Lexer {
|
|||
if self.match_char('=') {
|
||||
Some(Token::BangEqual)
|
||||
} else {
|
||||
None // Or handle as an error or another token if needed
|
||||
Some(Token::Error(format!("Unexpected character '{}'", c)))
|
||||
}
|
||||
},
|
||||
'=' => {
|
||||
|
@ -111,7 +116,7 @@ impl Lexer {
|
|||
// Any other character
|
||||
_ => {
|
||||
eprintln!("Unexpected character '{}' on line {}", c, self.line);
|
||||
None
|
||||
Some(Token::Error(format!("Unexpected character '{}'", c)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -238,6 +243,8 @@ impl Lexer {
|
|||
"print" => Token::Print,
|
||||
"pub" => Token::Pub,
|
||||
"sym" => Token::Sym,
|
||||
"module" => Token::Module,
|
||||
"import" => Token::Import,
|
||||
_ => Token::Identifier(text),
|
||||
};
|
||||
|
||||
|
|
|
@ -43,9 +43,14 @@ pub enum Token {
|
|||
Print,
|
||||
Pub,
|
||||
Sym,
|
||||
Module,
|
||||
Import,
|
||||
|
||||
// Comments
|
||||
Comment(String),
|
||||
|
||||
// Errors
|
||||
Error(String),
|
||||
|
||||
EOF,
|
||||
}
|
||||
|
|
|
@ -1,9 +1,47 @@
|
|||
// placeholder for ast defintions
|
||||
|
||||
pub enum Expression {
|
||||
// Define expression types
|
||||
Literal(Literal),
|
||||
Variable(String),
|
||||
Binary(Box<Expression>, Operator, Box<Expression>),
|
||||
Unary(Operator, Box<Expression>),
|
||||
Grouping(Box<Expression>),
|
||||
Assignment(String, Box<Expression>),
|
||||
FunctionCall(Box<Expression>, Vec<Expression>),
|
||||
}
|
||||
|
||||
pub enum Literal {
|
||||
Number(f64),
|
||||
String(String),
|
||||
Boolean(bool),
|
||||
Nil,
|
||||
}
|
||||
|
||||
pub enum Operator {
|
||||
Plus,
|
||||
Minux,
|
||||
Multiply,
|
||||
Divide,
|
||||
Greater,
|
||||
Less,
|
||||
GreaterEqual,
|
||||
LessEqual,
|
||||
EqualEqual,
|
||||
NotEqual,
|
||||
AlmostEqual,
|
||||
Almost,
|
||||
}
|
||||
|
||||
pub enum Statement {
|
||||
// Define statement types
|
||||
ExpressionStatement(Expression),
|
||||
PrintStatement(Expression),
|
||||
VariableDeclaration(String, Option<Expression>),
|
||||
Block(Vec<Statement>),
|
||||
IfStatement(Expression, Box<Statement>, Option<Box<Statement>>),
|
||||
WhileStatement(Expression, Box<Statement>),
|
||||
ForStatement(Box<Statement>, Expression, Box<Statement>, Box<Statement>),
|
||||
FunctionDeclaration {
|
||||
name: String,
|
||||
params: Vec<String>,
|
||||
body: Vec<Statement>,
|
||||
},
|
||||
ReturnStatement(Option<Expression>),
|
||||
}
|
66
src/parser/parser.rs
Normal file
66
src/parser/parser.rs
Normal file
|
@ -0,0 +1,66 @@
|
|||
use crate::lexer::token::Token;
|
||||
|
||||
pub struct Parser {
|
||||
tokens: Vec<Token>,
|
||||
current: usize,
|
||||
}
|
||||
|
||||
impl Parser {
|
||||
fn parse_statement(&mut self) -> Option<Statement> {
|
||||
if self.match_token(Token::Print) {
|
||||
self.parse_print_statement()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn new(tokens: Vec<Token>) -> Self {
|
||||
Parser {
|
||||
tokens,
|
||||
current: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn current_token(&self) -> &Token {
|
||||
&self.tokens[self.current]
|
||||
}
|
||||
|
||||
fn peek(&self) -> &Token {
|
||||
&self.tokens[self.current + 1]
|
||||
}
|
||||
|
||||
fn is_at_end(&self) -> bool {
|
||||
matches!(self.current_token(), Token::EOF)
|
||||
}
|
||||
|
||||
fn advance(&mut self) -> &Token {
|
||||
if !self.is_at_end() {
|
||||
self.current += 1;
|
||||
}
|
||||
self.current_token()
|
||||
}
|
||||
|
||||
fn match_token(&mut self, expected: Token) -> bool {
|
||||
if self.current_token() == &expected {
|
||||
self.advance();
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn previous_token(&self) -> &Token {
|
||||
&self.tokens[self.current - 1]
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let source = String::from("let x = 10;");
|
||||
let mut lexer = Lexer::new(source);
|
||||
let tokens = lexer.scan_tokens();
|
||||
let mut parser = Parser::new(tokens);
|
||||
|
||||
while !parser.is_at_end() {
|
||||
println!("{:?}", parser.current_token());
|
||||
parser.advance();
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue