mirror of
https://github.com/TheM1Stery/izanami.git
synced 2025-04-19 16:31:11 +00:00
chapter 5
This commit is contained in:
parent
0b437fe5e1
commit
5f80dfe498
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
||||
/target
|
||||
*.izn
|
||||
|
19
src/ast.rs
Normal file
19
src/ast.rs
Normal file
@ -0,0 +1,19 @@
|
||||
use crate::token::{LiteralType, Token};
|
||||
|
||||
pub enum Expr {
|
||||
Binary {
|
||||
left: Box<Expr>,
|
||||
op: Token,
|
||||
right: Box<Expr>,
|
||||
},
|
||||
Grouping {
|
||||
expression: Box<Expr>,
|
||||
},
|
||||
Literal {
|
||||
value: Option<LiteralType>,
|
||||
},
|
||||
Unary {
|
||||
op: Token,
|
||||
right: Box<Expr>,
|
||||
},
|
||||
}
|
@ -7,6 +7,8 @@ use std::{
|
||||
use scanner::Scanner;
|
||||
use token::Token;
|
||||
|
||||
mod ast;
|
||||
mod printer;
|
||||
mod scanner;
|
||||
mod token;
|
||||
mod utils;
|
||||
|
84
src/printer.rs
Normal file
84
src/printer.rs
Normal file
@ -0,0 +1,84 @@
|
||||
use crate::{ast::Expr, token::LiteralType};
|
||||
|
||||
pub fn pretty_print(expr: &Expr) -> String {
|
||||
match expr {
|
||||
Expr::Binary { left, op, right } => parenthesize(&op.lexeme, &[left, right]),
|
||||
Expr::Grouping { expression } => parenthesize("group", &[expression]),
|
||||
Expr::Literal { value } => match value {
|
||||
Some(LiteralType::String(v)) => v.to_string(),
|
||||
Some(LiteralType::Number(v)) => v.to_string(),
|
||||
None => "None".to_string(),
|
||||
},
|
||||
Expr::Unary { op, right } => parenthesize(&op.lexeme, &[right]),
|
||||
}
|
||||
}
|
||||
|
||||
fn parenthesize(name: &str, exprs: &[&Expr]) -> String {
|
||||
let mut parenthesized = format!("({name}");
|
||||
|
||||
for expr in exprs {
|
||||
parenthesized.push(' ');
|
||||
parenthesized.push_str(&pretty_print(expr));
|
||||
}
|
||||
|
||||
parenthesized.push(')');
|
||||
|
||||
parenthesized
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::token::{Token, TokenType};
|
||||
|
||||
use super::*;
|
||||
use Expr::*;
|
||||
|
||||
#[test]
|
||||
fn equal_print_binary() {
|
||||
use TokenType::*;
|
||||
let expression = Binary {
|
||||
left: Box::new(Literal {
|
||||
value: Some(LiteralType::Number(10.2)),
|
||||
}),
|
||||
op: Token {
|
||||
t_type: Plus,
|
||||
lexeme: "+".to_string(),
|
||||
literal: None,
|
||||
line: 0,
|
||||
},
|
||||
right: Box::new(Literal {
|
||||
value: Some(LiteralType::Number(10.2)),
|
||||
}),
|
||||
};
|
||||
|
||||
let actual = pretty_print(&expression);
|
||||
let expected = "(+ 10.2 10.2)";
|
||||
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
// tests all cases
|
||||
fn equal_test_whole() {
|
||||
use TokenType::*;
|
||||
let expression = Binary {
|
||||
left: Box::new(Unary {
|
||||
op: Token::new(Minus, "-", None, 0),
|
||||
right: Box::new(Expr::Literal {
|
||||
value: Some(LiteralType::number_literal(123.0)),
|
||||
}),
|
||||
}),
|
||||
op: Token::new(Star, "*", None, 0),
|
||||
right: Box::new(Grouping {
|
||||
expression: Box::new(Literal {
|
||||
value: Some(LiteralType::number_literal(45.67)),
|
||||
}),
|
||||
}),
|
||||
};
|
||||
|
||||
let actual = pretty_print(&expression);
|
||||
let expected = "(* (- 123) (group 45.67))";
|
||||
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
}
|
@ -370,7 +370,7 @@ mod tests {
|
||||
|
||||
let mut scanner = Scanner::new(value);
|
||||
|
||||
let expected_value = LiteralType::Number(123.456);
|
||||
let expected_value = LiteralType::Number(123.0);
|
||||
|
||||
let tokens = scanner.scan_tokens().expect("There shouldn't be an error");
|
||||
|
||||
|
22
src/token.rs
22
src/token.rs
@ -54,6 +54,16 @@ pub enum LiteralType {
|
||||
Number(f64),
|
||||
}
|
||||
|
||||
impl LiteralType {
|
||||
pub fn string_literal(val: &str) -> LiteralType {
|
||||
return LiteralType::String(val.to_string());
|
||||
}
|
||||
|
||||
pub fn number_literal(val: f64) -> LiteralType {
|
||||
return LiteralType::Number(val);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Token {
|
||||
pub t_type: TokenType,
|
||||
@ -62,6 +72,18 @@ pub struct Token {
|
||||
pub line: usize,
|
||||
}
|
||||
|
||||
impl Token {
|
||||
pub fn new(t_type: TokenType, lexeme: &str, literal: Option<LiteralType>, line: usize) -> Self {
|
||||
let lexeme = lexeme.to_string();
|
||||
Self {
|
||||
t_type,
|
||||
lexeme,
|
||||
literal,
|
||||
line,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Token {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?} {} {:?}", self.t_type, self.lexeme, self.literal)
|
||||
|
Loading…
Reference in New Issue
Block a user