From 8d3354ec9741b87b7e91baa30031cb5554b0875f Mon Sep 17 00:00:00 2001 From: bad Date: Sat, 2 Apr 2022 21:23:47 +0200 Subject: [PATCH] Refactoring --- Cargo.lock | 227 ++++++++++++++++++++++++++++++++++ Cargo.toml | 3 + src/ast/astnode.rs | 64 ++++------ src/ast/parser.rs | 11 +- src/error.rs | 39 ++++++ src/interpreter/ast_walker.rs | 53 ++++++++ src/interpreter/mod.rs | 2 + src/interpreter/types.rs | 25 ++++ src/lexer/error.rs | 11 +- src/lexer/lexer_iter.rs | 62 ++++++++++ src/lexer/mod.rs | 45 +++---- src/lexer/token.rs | 10 +- src/main.rs | 8 +- 13 files changed, 481 insertions(+), 79 deletions(-) create mode 100644 src/error.rs create mode 100644 src/interpreter/ast_walker.rs create mode 100644 src/interpreter/mod.rs create mode 100644 src/interpreter/types.rs create mode 100644 src/lexer/lexer_iter.rs diff --git a/Cargo.lock b/Cargo.lock index 2024e8d..b477e8e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "ansi_term" version = "0.12.1" @@ -11,33 +26,186 @@ dependencies = [ "winapi", ] +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e121dee8023ce33ab248d9ce1493df03c3b38a659b240096fcbd7048ff9c31f" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "color-eyre" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ebf286c900a6d5867aeff75cfee3192857bb7f24b547d4f0df2ed6baa812c90" +dependencies = [ + "backtrace", + "color-spantrace", + "eyre", + "indenter", + "once_cell", + "owo-colors", + "tracing-error", +] + +[[package]] +name = "color-spantrace" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ba75b3d9449ecdccb27ecbc479fdc0b87fa2dd43d2f8298f9bf0e59aacc8dce" +dependencies = [ + "once_cell", + "owo-colors", + "tracing-core", + "tracing-error", +] + [[package]] name = "crftng-intrprtrs" version = "0.1.0" dependencies = [ + "color-eyre", "dotenv", + "from_variants", + "match_any", "tracing", "tracing-subscriber", ] +[[package]] +name = "darling" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0d720b8683f8dd83c65155f0530560cba68cd2bf395f6513a483caee57ff7f4" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b" +dependencies = [ + "darling_core", + "quote", + "syn", +] + [[package]] name = "dotenv" version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" +[[package]] +name = "eyre" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9289ed2c0440a6536e65119725cf91fc2c6b5e513bfd2e36e1134d7cca6ca12f" +dependencies = [ + "indenter", + "once_cell", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "from_variants" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cf36180ca6f3c021e91b194e16b670ef5cbdd0cea48354ff6f5f83e3c2d1629" +dependencies = [ + "from_variants_impl", +] + +[[package]] +name = "from_variants_impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13abfd95d43eabb051a8d4b408ef92dfe6d8d4aa17651e5786d5c761e5e6e7ad" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "gimli" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "libc" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f" + [[package]] name = "log" version = "0.4.14" @@ -47,6 +215,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "match_any" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95be9b73c284f83dea49e484302dcf0ebe6b72ac59c5a9c422bd0e52676f33a3" + [[package]] name = "matchers" version = "0.1.0" @@ -56,12 +230,43 @@ dependencies = [ "regex-automata", ] +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + +[[package]] +name = "object" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" +[[package]] +name = "owo-colors" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e72e30578e0d0993c8ae20823dd9cff2bc5517d2f586a8aef462a581e8a03eb" + [[package]] name = "pin-project-lite" version = "0.2.8" @@ -110,6 +315,12 @@ version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +[[package]] +name = "rustc-demangle" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" + [[package]] name = "sharded-slab" version = "0.1.4" @@ -125,6 +336,12 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "syn" version = "1.0.89" @@ -178,6 +395,16 @@ dependencies = [ "valuable", ] +[[package]] +name = "tracing-error" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +dependencies = [ + "tracing", + "tracing-subscriber", +] + [[package]] name = "tracing-log" version = "0.1.2" diff --git a/Cargo.toml b/Cargo.toml index 8421fd9..8ffd3f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,9 @@ version = "0.1.0" edition = "2021" [dependencies] +color-eyre = "0.6.1" dotenv = "0.15.0" +from_variants = "1.0.0" +match_any = "1.0.1" tracing = "0.1.32" tracing-subscriber = { version = "0.3.9", features = ["env-filter"] } diff --git a/src/ast/astnode.rs b/src/ast/astnode.rs index 73d62e7..0688935 100644 --- a/src/ast/astnode.rs +++ b/src/ast/astnode.rs @@ -1,7 +1,9 @@ +use crate::lexer::token; +use from_variants::FromVariants; +use match_any::match_any; use std::fmt::{Debug, Display}; -use crate::lexer::token; - +#[derive(FromVariants)] pub enum ASTNode { BinaryExpr(BinaryExpr), GroupingExpr(GroupingExpr), @@ -9,38 +11,21 @@ pub enum ASTNode { UnaryExpr(UnaryExpr), } -impl From for ASTNode { - fn from(b: BinaryExpr) -> Self { - ASTNode::BinaryExpr(b) - } -} +macro_rules! all_variants { + ($expr:expr, $val_name:ident => $expr_arm:expr) => { + { + use match_any::match_any; + use $crate::ast::astnode::*; + match_any!($expr, ASTNode::BinaryExpr($val_name) | ASTNode::GroupingExpr($val_name) | ASTNode::Literal($val_name) | ASTNode::UnaryExpr($val_name) => $expr_arm) + } -impl From for ASTNode { - fn from(g: GroupingExpr) -> Self { - Self::GroupingExpr(g) - } -} - -impl From for ASTNode { - fn from(l: Literal) -> Self { - Self::Literal(l) - } -} - -impl From for ASTNode { - fn from(u: UnaryExpr) -> Self { - Self::UnaryExpr(u) - } + }; } +pub(crate) use all_variants; impl Debug for ASTNode { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::BinaryExpr(b) => b.fmt(f), - Self::GroupingExpr(g) => g.fmt(f), - Self::Literal(l) => l.fmt(f), - Self::UnaryExpr(u) => u.fmt(f), - } + all_variants!(self, n => n.fmt(f)) } } @@ -75,7 +60,6 @@ impl Display for UnaryOperator { } pub enum Operator { - Bang, BangEqual, Equal, EqualEqual, @@ -100,7 +84,6 @@ impl TryFrom for Operator { fn try_from(value: token::TokenType) -> Result { Ok(match value { - token::TokenType::Bang => Self::Bang, token::TokenType::BangEqual => Self::BangEqual, token::TokenType::Equal => Self::Equal, token::TokenType::EqualEqual => Self::EqualEqual, @@ -120,7 +103,6 @@ impl Display for Operator { f, "{}", match *self { - Operator::Bang => "!", Operator::Less => "<", Operator::Equal => "=", Operator::Greater => ">", @@ -133,18 +115,18 @@ impl Display for Operator { } } -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum Literal { String(String), - Int(i64), - Float(f64), + Int(i32), + Float(f32), Bool(bool), } pub struct BinaryExpr { - left: Box, - operator: Operator, - right: Box, + pub left: Box, + pub operator: Operator, + pub right: Box, } impl BinaryExpr { @@ -157,7 +139,7 @@ impl BinaryExpr { } } -pub struct GroupingExpr(Box); +pub struct GroupingExpr(pub Box); impl GroupingExpr { pub(crate) fn new(expr: Box) -> Self { @@ -166,8 +148,8 @@ impl GroupingExpr { } pub struct UnaryExpr { - operator: UnaryOperator, - right: Box, + pub operator: UnaryOperator, + pub right: Box, } impl UnaryExpr { diff --git a/src/ast/parser.rs b/src/ast/parser.rs index 28e6fed..343462e 100644 --- a/src/ast/parser.rs +++ b/src/ast/parser.rs @@ -10,19 +10,20 @@ type Result = StdResult; pub enum ASTParsingError { UnmatchedBrace, } + impl std::fmt::Display for ASTParsingError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { todo!() } } impl std::error::Error for ASTParsingError {} -pub struct Parser> { +pub struct Parser<'a, T: Iterator>> { token_iter: iter::Peekable, } -impl> Parser { - pub fn new(iter: T) -> Parser { +impl<'a, T: Iterator>> Parser<'a, T> { + pub fn new(iter: T) -> Parser<'a, T> { Parser { token_iter: iter.peekable(), } @@ -153,7 +154,7 @@ impl> Parser { .next_if(|v| matches!(v.token_type, TokenType::RightParen)) { Some(_) => return Ok(group.into()), - None => return Err(todo!()), + None => return Err(ASTParsingError::UnmatchedBrace), } } Some(a) => panic!("{:#?}", a), diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..c3bdd71 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,39 @@ +use std::error::Error; + +#[derive(Debug, Clone, Copy)] +pub struct Location<'a> { + pub line: usize, + pub col: usize, + pub file: Option<&'a str>, +} + +#[derive(Debug, Clone)] +pub struct OwnedLocation { + pub line: usize, + pub col: usize, + pub file: Option, +} + +impl<'a> From> for OwnedLocation { + fn from(l: Location<'a>) -> OwnedLocation { + OwnedLocation { + line: l.line, + col: l.col, + file: l.file.map(|v| v.to_string()), + } + } +} + +impl<'a> From<&'a OwnedLocation> for Location<'a> { + fn from(l: &'a OwnedLocation) -> Location<'a> { + Location { + line: l.line, + col: l.col, + file: l.file.as_ref().map(|v| v.as_str()), + } + } +} + +pub trait ErrorWithLocation: Error { + fn get_location(&self) -> Location; +} diff --git a/src/interpreter/ast_walker.rs b/src/interpreter/ast_walker.rs new file mode 100644 index 0000000..f8d93ed --- /dev/null +++ b/src/interpreter/ast_walker.rs @@ -0,0 +1,53 @@ +use super::types; +use crate::ast::astnode::{self, UnaryOperator}; + +#[derive(Debug)] +pub struct RuntimeError; + +pub trait Interpret { + fn interpret(&self) -> Result; +} + +impl Interpret for astnode::ASTNode { + fn interpret(&self) -> Result { + astnode::all_variants!(self, n => n.interpret()) + } +} + +impl Interpret for astnode::Literal { + fn interpret(&self) -> Result { + Ok(self.clone().into()) + } +} + +impl Interpret for astnode::BinaryExpr { + fn interpret(&self) -> Result { + let left_val = self.left.interpret().expect("expected lval"); + let right_val = self.right.interpret().expect("expected rval"); + match self.operator { + astnode::Operator::BangEqual => Ok((left_val != right_val).into()), + astnode::Operator::Less => Ok((left_val < right_val).into()), + astnode::Operator::LessEqual => Ok((left_val <= right_val).into()), + astnode::Operator::Greater => Ok((left_val > right_val).into()), + astnode::Operator::GreaterEqual => Ok((left_val >= right_val).into()), + astnode::Operator::EqualEqual => Ok((left_val == right_val).into()), + astnode::Operator::Equal => todo!(), + } + } +} + +impl Interpret for astnode::UnaryExpr { + fn interpret(&self) -> Result { + let _val = self.right.interpret(); + match self.operator { + UnaryOperator::Bang => todo!(), + UnaryOperator::Minus => todo!(), + } + } +} + +impl Interpret for astnode::GroupingExpr { + fn interpret(&self) -> Result { + self.0.interpret() + } +} diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs new file mode 100644 index 0000000..4c63f96 --- /dev/null +++ b/src/interpreter/mod.rs @@ -0,0 +1,2 @@ +pub mod ast_walker; +pub mod types; diff --git a/src/interpreter/types.rs b/src/interpreter/types.rs new file mode 100644 index 0000000..e23878b --- /dev/null +++ b/src/interpreter/types.rs @@ -0,0 +1,25 @@ +use crate::ast::astnode; +use from_variants::FromVariants; + +#[derive(Debug, PartialEq, PartialOrd, FromVariants)] +pub enum Primitive { + Int(i32), + Float(f32), + Bool(bool), + Null, +} + +#[derive(Debug, PartialEq, PartialOrd, FromVariants)] +pub enum Value { + #[from_variants(into)] + Primitive(Primitive), +} + +impl From for Value { + fn from(l: astnode::Literal) -> Self { + match_any::match_any!(l, + astnode::Literal::Int(v) | astnode::Literal::Bool(v)| astnode::Literal::Float(v) => v.into(), + astnode::Literal::String(_s) => todo!() + ) + } +} diff --git a/src/lexer/error.rs b/src/lexer/error.rs index 2432971..2a44866 100644 --- a/src/lexer/error.rs +++ b/src/lexer/error.rs @@ -1,15 +1,22 @@ +use crate::error::{ErrorWithLocation, Location, OwnedLocation}; use core::fmt; use std::error::Error; #[derive(Debug)] pub struct LexingError { - pub line: usize, + pub location: OwnedLocation, pub kind: LexingErrorKind, } impl fmt::Display for LexingError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Error: {}\n on line: {}", self.kind, self.line) + write!(f, "Error: {}", self.kind) + } +} + +impl ErrorWithLocation for LexingError { + fn get_location<'a>(&'a self) -> Location<'a> { + (&self.location).into() } } diff --git a/src/lexer/lexer_iter.rs b/src/lexer/lexer_iter.rs new file mode 100644 index 0000000..aa39570 --- /dev/null +++ b/src/lexer/lexer_iter.rs @@ -0,0 +1,62 @@ +use crate::error::Location; +use std::str::Chars; + +#[derive(Debug)] +pub struct LexerIter<'a> { + inner: Chars<'a>, + line: usize, + col: usize, +} + +impl<'a> Iterator for LexerIter<'a> { + type Item = char; + fn next(&mut self) -> Option { + let char = self.inner.next()?; + self.col += 1; + + if char == '\n' { + self.line += 1; + self.col = 1; + } + + Some(char) + } +} + +impl<'a> LexerIter<'a> { + pub fn new(src: &'a str) -> Self { + Self { + inner: src.chars(), + line: 0, + col: 0, + } + } + + pub fn peek(&self) -> Option { + self.as_str().chars().next() + } + + pub fn as_str(&'a self) -> &'a str { + self.inner.as_str() + } + + pub fn next_if(&mut self, func: impl FnOnce(char) -> bool) -> Option { + if func(self.peek()?) { + self.next() + } else { + None + } + } + + pub fn next_if_eq(&mut self, expected: char) -> Option { + self.next_if(|c| c == expected) + } + + pub fn get_location<'b>(&self, file: Option<&'b str>) -> Location<'b> { + Location { + line: self.line, + col: self.col, + file, + } + } +} diff --git a/src/lexer/mod.rs b/src/lexer/mod.rs index bbedc08..97237bf 100644 --- a/src/lexer/mod.rs +++ b/src/lexer/mod.rs @@ -1,7 +1,7 @@ mod error; +mod lexer_iter; pub mod token; -use std::iter; -use std::str::Chars; +use lexer_iter::LexerIter; pub use error::LexingError; @@ -9,18 +9,18 @@ use self::error::LexingErrorKind; use self::token::Token; #[derive(Debug)] -pub struct Lexer<'a> { +pub struct Lexer<'a, 'b> { + file: Option<&'b str>, _source: &'a str, - source_iter: iter::Peekable>, - line: usize, + source_iter: LexerIter<'a>, } -impl<'a> Lexer<'a> { - pub fn new(code: &'a str) -> Lexer<'a> { +impl<'a, 'b> Lexer<'a, 'b> { + pub fn new(code: &'a str, file: Option<&'b str>) -> Lexer<'a, 'b> { return Lexer { _source: code, - source_iter: code.chars().peekable(), - line: 0, + source_iter: LexerIter::new(code), + file, }; } @@ -47,10 +47,10 @@ impl<'a> Lexer<'a> { } } - fn get_token(&self, token_type: token::TokenType) -> token::Token { + fn get_token(&self, token_type: token::TokenType) -> token::Token<'b> { token::Token { token_type, - line: self.line, + location: self.source_iter.get_location(self.file), } } @@ -59,16 +59,16 @@ impl<'a> Lexer<'a> { to_eq: char, if_eq_type: token::TokenType, else_type: token::TokenType, - ) -> token::Token { + ) -> token::Token<'b> { let token_type = self .source_iter - .next_if_eq(&to_eq) + .next_if_eq(to_eq) .map(|_| if_eq_type) .unwrap_or(else_type); self.get_token(token_type) } - fn scan_token(&mut self) -> Option> { + fn scan_token(&mut self) -> Option, LexingError>> { Some(Ok(match self.source_iter.next()? { '(' => self.get_token(token::TokenType::LeftParen), ')' => self.get_token(token::TokenType::RightParen), @@ -104,15 +104,12 @@ impl<'a> Lexer<'a> { '"' => { let mut string = String::new(); let unmatched_char_error = Some(Err(LexingError { - line: self.line, kind: LexingErrorKind::UnmatchedQuote, + location: self.source_iter.get_location(self.file).into(), })); loop { let next_char = self.source_iter.next(); - if let Some('\n') = next_char { - self.line += 1; - } match next_char { Some('"') => break, Some('\\') => match self.source_iter.next() { @@ -126,10 +123,10 @@ impl<'a> Lexer<'a> { self.get_token(token::TokenType::String(string)) } c @ '0'..='9' => { - let mut num: i64 = c.to_digit(10).unwrap() as i64; + let mut num: i32 = c.to_digit(10).unwrap() as i32; while let Some(c) = self.source_iter.next_if(|c| c.is_digit(10)) { num *= 10; - num += c.to_digit(10).unwrap() as i64; + num += c.to_digit(10).unwrap() as i32; } self.get_token(token::TokenType::Int(num)) } @@ -158,14 +155,10 @@ impl<'a> Lexer<'a> { }) } // Ignore whitespace - ' ' | '\r' | '\t' => return None, - '\n' => { - self.line += 1; - return None; - } + ' ' | '\r' | '\t' | '\n' => return None, c => { return Some(Err(LexingError { - line: self.line, + location: self.source_iter.get_location(self.file).into(), kind: LexingErrorKind::UnexpectedCharacter(c), })) } diff --git a/src/lexer/token.rs b/src/lexer/token.rs index 18c11c6..7aa7479 100644 --- a/src/lexer/token.rs +++ b/src/lexer/token.rs @@ -1,7 +1,9 @@ +use crate::error::Location; + #[derive(Debug)] -pub struct Token { +pub struct Token<'a> { pub token_type: TokenType, - pub line: usize, + pub location: Location<'a>, } #[derive(Debug)] @@ -29,8 +31,8 @@ pub enum TokenType { Identifier(String), String(String), - Int(i64), - Float(f64), + Int(i32), + Float(f32), And, Else, diff --git a/src/main.rs b/src/main.rs index cdbe11f..045b5d8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,9 @@ mod ast; +mod error; +mod interpreter; mod lexer; +use interpreter::ast_walker::Interpret; use lexer::Lexer; use std::{fs, io, path}; use tracing::Level; @@ -27,22 +30,25 @@ fn run_repl() { } fn run(code: &str) -> Result<(), Vec> { - let mut lexer = Lexer::new(code); + let mut lexer = Lexer::new(code, None); let tokens = lexer.scan_tokens()?; println!("{:?}", tokens); let mut parser = crate::ast::parser::Parser::new(tokens.into_iter()); let expressions = parser.scan_expressions().unwrap(); println!("{:?}", expressions); + println!("{:?}", expressions[0].interpret()); Ok(()) } fn main() { dotenv::dotenv().ok(); + color_eyre::install().expect("Failed to install color-eyre"); let subscriber = FmtSubscriber::builder() .with_max_level(Level::TRACE) .with_env_filter(EnvFilter::from_env("LOG")) .finish(); + tracing::subscriber::set_global_default(subscriber).unwrap(); if let Some(file) = std::env::args_os().nth(1) {