From 11b4704d996b032996d776e341bb9ae309c107aa Mon Sep 17 00:00:00 2001 From: ElBe-Plaq <90863907+ElBe-Plaq@users.noreply.github.com> Date: Thu, 21 Mar 2024 07:57:53 +0100 Subject: [PATCH 01/10] del(language): Removed `default` keyword Tracking issue: #119 --- crates/lexer/src/tokens/keyword.rs | 10 +--------- crates/lexer/tests/tokens/keyword.rs | 2 -- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/crates/lexer/src/tokens/keyword.rs b/crates/lexer/src/tokens/keyword.rs index dc39601..dce1c5a 100644 --- a/crates/lexer/src/tokens/keyword.rs +++ b/crates/lexer/src/tokens/keyword.rs @@ -52,8 +52,6 @@ pub enum Keyword { Const, /// The `continue` keyword. Used to continue a loop before all of it's code is executed. Continue, - /// The `default` keyword. Used in combination with the [`match`](`Keyword::Match`) and [`case`](`Keyword::Case`) keywords to match the default case. - Default, /// The `else` keyword. Used to define the "otherwise" block of an [`if`](`Keyword::If`) statement. Else, /// The `finally` keyword. Used in combination with the [`try`](`Keyword::Try`) keyword to execute code even after an exception has been raised. @@ -66,7 +64,7 @@ pub enum Keyword { If, /// The `import` keyword. Used to import code from other modules. Import, - /// The `match` keyword. Used in combination with the [`case`](`Keyword::Case`) and [`default`](`Keyword::Default`) keywords. + /// The `match` keyword. Used in combination with the [`case`](`Keyword::Case`) keyword. Match, /// The `pub` keyword. Used to export an item out of the current scope. Pub, @@ -96,7 +94,6 @@ impl core::fmt::Display for Keyword { &Self::Class => write!(formatter, "class"), &Self::Const => write!(formatter, "const"), &Self::Continue => write!(formatter, "continue"), - &Self::Default => write!(formatter, "default"), &Self::Else => write!(formatter, "else"), &Self::Finally => write!(formatter, "finally"), &Self::For => write!(formatter, "for"), @@ -157,11 +154,6 @@ impl GetToken for Keyword { content: "continue".to_owned(), token_type: TokenType::Keyword(Keyword::Continue), }), - "default" => Some(Token { - location, - content: "default".to_owned(), - token_type: TokenType::Keyword(Keyword::Default), - }), "else" => Some(Token { location, content: "else".to_owned(), diff --git a/crates/lexer/tests/tokens/keyword.rs b/crates/lexer/tests/tokens/keyword.rs index 2db1437..dbb9fb2 100644 --- a/crates/lexer/tests/tokens/keyword.rs +++ b/crates/lexer/tests/tokens/keyword.rs @@ -48,7 +48,6 @@ mod tests { assert_eq!(&format!("{}", Keyword::Class), "class"); assert_eq!(&format!("{}", Keyword::Const), "const"); assert_eq!(&format!("{}", Keyword::Continue), "continue"); - assert_eq!(&format!("{}", Keyword::Default), "default"); assert_eq!(&format!("{}", Keyword::Else), "else"); assert_eq!(&format!("{}", Keyword::Finally), "finally"); assert_eq!(&format!("{}", Keyword::For), "for"); @@ -81,7 +80,6 @@ mod tests { assert!(generate_test(&location, "class", Keyword::Class)); assert!(generate_test(&location, "const", Keyword::Const)); assert!(generate_test(&location, "continue", Keyword::Continue)); - assert!(generate_test(&location, "default", Keyword::Default)); assert!(generate_test(&location, "else", Keyword::Else)); assert!(generate_test(&location, "finally", Keyword::Finally)); assert!(generate_test(&location, "for", Keyword::For)); From 48e0470a5184c6f4980d4bafcf1e021a5b099f22 Mon Sep 17 00:00:00 2001 From: ElBe-Plaq <90863907+ElBe-Plaq@users.noreply.github.com> Date: Fri, 22 Mar 2024 21:42:10 +0100 Subject: [PATCH 02/10] del(language): Removed `function` keyword Tracking issue: #121 --- crates/lexer/src/tokens/keyword.rs | 8 -------- crates/lexer/tests/tokens/keyword.rs | 2 -- 2 files changed, 10 deletions(-) diff --git a/crates/lexer/src/tokens/keyword.rs b/crates/lexer/src/tokens/keyword.rs index dce1c5a..39b8f78 100644 --- a/crates/lexer/src/tokens/keyword.rs +++ b/crates/lexer/src/tokens/keyword.rs @@ -58,8 +58,6 @@ pub enum Keyword { Finally, /// The `for` keyword. Used to create a loop over an iterator. For, - /// The `function` keyword. Will probably be replaced by either `fn` or `func` soon. Used to define a function. - Function, // TODO (ElBe): Replace with "fn" or "func"? /// The `if` keyword. Used to check whether a condition is true or false and execute code based on that condition. If, /// The `import` keyword. Used to import code from other modules. @@ -97,7 +95,6 @@ impl core::fmt::Display for Keyword { &Self::Else => write!(formatter, "else"), &Self::Finally => write!(formatter, "finally"), &Self::For => write!(formatter, "for"), - &Self::Function => write!(formatter, "function"), &Self::If => write!(formatter, "if"), &Self::Import => write!(formatter, "import"), &Self::Match => write!(formatter, "match"), @@ -169,11 +166,6 @@ impl GetToken for Keyword { content: "for".to_owned(), token_type: TokenType::Keyword(Keyword::For), }), - "function" => Some(Token { - location, - content: "function".to_owned(), - token_type: TokenType::Keyword(Keyword::Function), - }), "if" => Some(Token { location, content: "if".to_owned(), diff --git a/crates/lexer/tests/tokens/keyword.rs b/crates/lexer/tests/tokens/keyword.rs index dbb9fb2..1d678fd 100644 --- a/crates/lexer/tests/tokens/keyword.rs +++ b/crates/lexer/tests/tokens/keyword.rs @@ -51,7 +51,6 @@ mod tests { assert_eq!(&format!("{}", Keyword::Else), "else"); assert_eq!(&format!("{}", Keyword::Finally), "finally"); assert_eq!(&format!("{}", Keyword::For), "for"); - assert_eq!(&format!("{}", Keyword::Function), "function"); assert_eq!(&format!("{}", Keyword::If), "if"); assert_eq!(&format!("{}", Keyword::Import), "import"); assert_eq!(&format!("{}", Keyword::Match), "match"); @@ -83,7 +82,6 @@ mod tests { assert!(generate_test(&location, "else", Keyword::Else)); assert!(generate_test(&location, "finally", Keyword::Finally)); assert!(generate_test(&location, "for", Keyword::For)); - assert!(generate_test(&location, "function", Keyword::Function)); assert!(generate_test(&location, "if", Keyword::If)); assert!(generate_test(&location, "import", Keyword::Import)); assert!(generate_test(&location, "match", Keyword::Match)); From 2c91b63460c31437c8d27573cac1928d70f28c5e Mon Sep 17 00:00:00 2001 From: ElBe-Plaq <90863907+ElBe-Plaq@users.noreply.github.com> Date: Fri, 22 Mar 2024 21:45:50 +0100 Subject: [PATCH 03/10] del(language): Removed `->` operator Tracking issue: #121 --- crates/lexer/src/tokens/mark.rs | 8 -------- crates/lexer/tests/tokens/mark.rs | 2 -- 2 files changed, 10 deletions(-) diff --git a/crates/lexer/src/tokens/mark.rs b/crates/lexer/src/tokens/mark.rs index b7cc603..5f70947 100644 --- a/crates/lexer/src/tokens/mark.rs +++ b/crates/lexer/src/tokens/mark.rs @@ -44,8 +44,6 @@ pub enum Mark { AddAssign, /// The `&&` (**logical** and) mark. Used for creating a true/false value based on whether both the left and right tokens are true. And, - /// The `->` mark. Used for indicating what value will be returned from a function. - Arrow, /// The `=` mark. Used for assigning a value to a variable. Assign, /// The `@` mark. Currently, it has no use, but it's reserved for later usage and will probably be used in future. @@ -146,7 +144,6 @@ impl core::fmt::Display for Mark { &Self::Add => write!(formatter, "+"), &Self::AddAssign => write!(formatter, "+="), &Self::And => write!(formatter, "&&"), - &Self::Arrow => write!(formatter, "->"), &Self::Assign => write!(formatter, "="), &Self::At => write!(formatter, "@"), &Self::Bang => write!(formatter, "!"), @@ -218,11 +215,6 @@ impl GetToken for Mark { content: "&&".to_owned(), token_type: TokenType::Mark(Mark::And), }), - "->" => Some(Token { - location, - content: "->".to_owned(), - token_type: TokenType::Mark(Mark::Arrow), - }), "=" => Some(Token { location, content: "=".to_owned(), diff --git a/crates/lexer/tests/tokens/mark.rs b/crates/lexer/tests/tokens/mark.rs index dd5aa11..13fe212 100644 --- a/crates/lexer/tests/tokens/mark.rs +++ b/crates/lexer/tests/tokens/mark.rs @@ -44,7 +44,6 @@ mod tests { assert_eq!(&format!("{}", Mark::Add), "+"); assert_eq!(&format!("{}", Mark::AddAssign), "+="); assert_eq!(&format!("{}", Mark::And), "&&"); - assert_eq!(&format!("{}", Mark::Arrow), "->"); assert_eq!(&format!("{}", Mark::Assign), "="); assert_eq!(&format!("{}", Mark::At), "@"); assert_eq!(&format!("{}", Mark::Bang), "!"); @@ -104,7 +103,6 @@ mod tests { assert!(generate_test(&location, "+", Mark::Add)); assert!(generate_test(&location, "+=", Mark::AddAssign)); assert!(generate_test(&location, "&&", Mark::And)); - assert!(generate_test(&location, "->", Mark::Arrow)); assert!(generate_test(&location, "=", Mark::Assign)); assert!(generate_test(&location, "@", Mark::At)); assert!(generate_test(&location, "!", Mark::Bang)); From 30fe6a1d49013d3ec6c722a6105822c9c296de97 Mon Sep 17 00:00:00 2001 From: ElBe-Plaq <90863907+ElBe-Plaq@users.noreply.github.com> Date: Sun, 24 Mar 2024 22:29:25 +0100 Subject: [PATCH 04/10] perf(lexer): Removed unnecessary macro expansions --- crates/lexer/src/tokens/token.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/lexer/src/tokens/token.rs b/crates/lexer/src/tokens/token.rs index 5aa8b9a..bceea53 100644 --- a/crates/lexer/src/tokens/token.rs +++ b/crates/lexer/src/tokens/token.rs @@ -314,10 +314,10 @@ impl core::fmt::Display for TokenType { #[allow(clippy::pattern_type_mismatch)] fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { - Self::Type(type_name) => write!(formatter, "{type_name}"), - Self::TypeDefinition(type_definition) => write!(formatter, "{type_definition}"), - Self::Keyword(keyword) => write!(formatter, "{keyword}"), - Self::Mark(mark) => write!(formatter, "{mark}"), + Self::Type(type_name) => type_name.fmt(formatter), + Self::TypeDefinition(type_definition) => type_definition.fmt(formatter), + Self::Keyword(keyword) => keyword.fmt(formatter), + Self::Mark(mark) => mark.fmt(formatter), Self::Identifier => write!(formatter, "identifier"), Self::Comment => write!(formatter, "comment"), } From 8c5badc23cbf747eb7726b82b4d473fe9aea4e3c Mon Sep 17 00:00:00 2001 From: ElBe-Plaq <90863907+ElBe-Plaq@users.noreply.github.com> Date: Tue, 26 Mar 2024 21:28:39 +0100 Subject: [PATCH 05/10] feat(lexer): Added pretty error message to LexerErrors --- crates/lexer/src/error.rs | 12 ++++++++---- crates/lexer/src/lex.rs | 15 +++++++++------ crates/lexer/src/tokens/token.rs | 33 +++++++++++++++++++++----------- src/main.rs | 19 ++++++++++++++++++ 4 files changed, 58 insertions(+), 21 deletions(-) diff --git a/crates/lexer/src/error.rs b/crates/lexer/src/error.rs index 1b94b68..41e0937 100644 --- a/crates/lexer/src/error.rs +++ b/crates/lexer/src/error.rs @@ -43,18 +43,22 @@ pub enum LexerError { /// An error which will be returned if a mark was invalid for some reason. /// This can occur when the starting character of a mark is valid, but the character after it is not. #[error("invalid mark at {location}")] - InvalidMark { location: Location }, + InvalidMark { location: Location, error: String }, /// An error which will be returned if an unexpected character is encountered. /// this is most likely to occur when using unicode characters as they are not supported. #[error("unexpected character `{character}` at {location}")] - UnexpectedCharacter { character: char, location: Location }, + UnexpectedCharacter { + character: char, + location: Location, + error: String, + }, /// An error which will be returned if a comment is not terminated by a closing `*/`. #[error("unterminated comment at {location}")] - UnterminatedComment { location: Location }, + UnterminatedComment { location: Location, error: String }, /// An error which will be returned if a string is not terminated by a closing quote or the quote is escaped. #[error("unterminated string at {location}")] - UnterminatedString { location: Location }, + UnterminatedString { location: Location, error: String }, } diff --git a/crates/lexer/src/lex.rs b/crates/lexer/src/lex.rs index df0a8e6..9721116 100644 --- a/crates/lexer/src/lex.rs +++ b/crates/lexer/src/lex.rs @@ -189,10 +189,12 @@ pub fn lex(input: &str, file: &str) -> Result, LexerError> { }], }; - let renderer: annotate_snippets::Renderer = - annotate_snippets::Renderer::styled(); - eprintln!("{}", renderer.render(snippet)); - error = Some(LexerError::InvalidMark { location }); + error = Some(LexerError::InvalidMark { + location, + error: annotate_snippets::Renderer::styled() + .render(snippet) + .to_string(), + }); } } else if character.is_ascii_digit() { buffer.push(character); @@ -261,11 +263,12 @@ pub fn lex(input: &str, file: &str) -> Result, LexerError> { }], }; - let renderer: annotate_snippets::Renderer = annotate_snippets::Renderer::styled(); - eprintln!("{}", renderer.render(snippet)); error = Some(LexerError::UnexpectedCharacter { character, location, + error: annotate_snippets::Renderer::styled() + .render(snippet) + .to_string(), }); } diff --git a/crates/lexer/src/tokens/token.rs b/crates/lexer/src/tokens/token.rs index bceea53..110a3d9 100644 --- a/crates/lexer/src/tokens/token.rs +++ b/crates/lexer/src/tokens/token.rs @@ -221,6 +221,7 @@ impl TypeDefinition { .collect::>(); let help: String = format!("Add `{quote_type}` here"); + let file: String = location.file.clone(); let snippet: annotate_snippets::Snippet = annotate_snippets::Snippet { title: Some(annotate_snippets::Annotation { id: Some("E0002"), @@ -231,7 +232,7 @@ impl TypeDefinition { slices: vec![annotate_snippets::Slice { source: line, line_start: location.line, - origin: Some(&location.file), + origin: Some(&file), annotations: vec![ annotate_snippets::SourceAnnotation { range: (location.column - 1, location.column), @@ -268,14 +269,20 @@ impl TypeDefinition { if let Some((_, next_character)) = iterator.next() { if next_character != quote_type { - let renderer: annotate_snippets::Renderer = annotate_snippets::Renderer::styled(); - eprintln!("{}", renderer.render(snippet)); - return Err(LexerError::UnterminatedString { location }); + return Err(LexerError::UnterminatedString { + location, + error: annotate_snippets::Renderer::styled() + .render(snippet) + .to_string(), + }); } } else { - let renderer: annotate_snippets::Renderer = annotate_snippets::Renderer::styled(); - eprintln!("{}", renderer.render(snippet)); - return Err(LexerError::UnterminatedString { location }); + return Err(LexerError::UnterminatedString { + location, + error: annotate_snippets::Renderer::styled() + .render(snippet) + .to_string(), + }); } Ok(Token { @@ -414,6 +421,7 @@ impl TokenType { .collect::>(); if buffer.last() != Some(&'*') { + let file: String = location.file.clone(); let snippet: annotate_snippets::Snippet = annotate_snippets::Snippet { title: Some(annotate_snippets::Annotation { id: Some("E0001"), @@ -424,7 +432,7 @@ impl TokenType { slices: vec![annotate_snippets::Slice { source: line, line_start: location.line, - origin: Some(&location.file), + origin: Some(&file), annotations: vec![annotate_snippets::SourceAnnotation { range: (location.column - 1, line.len() - iterator.clone().count()), label: "Unterminated comment", @@ -434,9 +442,12 @@ impl TokenType { }], }; - let renderer: annotate_snippets::Renderer = annotate_snippets::Renderer::styled(); - eprintln!("{}", renderer.render(snippet)); - return Err(LexerError::UnterminatedComment { location }); + return Err(LexerError::UnterminatedComment { + location, + error: annotate_snippets::Renderer::styled() + .render(snippet) + .to_string(), + }); } iterator.next(); diff --git a/src/main.rs b/src/main.rs index 741dcdf..4760476 100644 --- a/src/main.rs +++ b/src/main.rs @@ -103,6 +103,25 @@ fn main() { match output { Err(error) => { + let (lexer::error::LexerError::InvalidMark { + error: error_message, + .. + } + | lexer::error::LexerError::UnexpectedCharacter { + error: error_message, + .. + } + | lexer::error::LexerError::UnterminatedComment { + error: error_message, + .. + } + | lexer::error::LexerError::UnterminatedString { + error: error_message, + .. + }) = error; + + eprintln!("{error_message}"); + eprintln!("Compiling `{file_name}` was not successful:\n{error}"); std::process::exit(1); } From afe22d47c22b8181353cec9e39db0c5a329b78e6 Mon Sep 17 00:00:00 2001 From: ElBe-Plaq <90863907+ElBe-Plaq@users.noreply.github.com> Date: Tue, 26 Mar 2024 21:30:45 +0100 Subject: [PATCH 06/10] feat(lexer): Distinguished block comments from line comments --- crates/lexer/src/tokens/token.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/lexer/src/tokens/token.rs b/crates/lexer/src/tokens/token.rs index 110a3d9..02abb64 100644 --- a/crates/lexer/src/tokens/token.rs +++ b/crates/lexer/src/tokens/token.rs @@ -314,6 +314,8 @@ pub enum TokenType { Identifier, /// A token representing a comment, e.g. `// comment`. Comment, + /// A token representing a comment across multiple lines, e.g. `/* comment */`. + BlockComment, } impl core::fmt::Display for TokenType { @@ -327,6 +329,7 @@ impl core::fmt::Display for TokenType { Self::Mark(mark) => mark.fmt(formatter), Self::Identifier => write!(formatter, "identifier"), Self::Comment => write!(formatter, "comment"), + Self::BlockComment => write!(formatter, "block comment"), } } } @@ -459,7 +462,7 @@ impl TokenType { .collect::() .trim() .to_owned(), - token_type: TokenType::Comment, + token_type: TokenType::BlockComment, })); } else if &buffer.iter().collect::() == "//" { buffer = line[location.column + 1..].chars().collect::>(); From 4401281501eba09e5f9df5d13186febe048cd48e Mon Sep 17 00:00:00 2001 From: ElBe-Plaq <90863907+ElBe-Plaq@users.noreply.github.com> Date: Tue, 26 Mar 2024 21:45:51 +0100 Subject: [PATCH 07/10] fix(cli): Fixed borrow of partially moved value --- src/main.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 4760476..c08c5a5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -104,19 +104,19 @@ fn main() { match output { Err(error) => { let (lexer::error::LexerError::InvalidMark { - error: error_message, + error: ref error_message, .. } | lexer::error::LexerError::UnexpectedCharacter { - error: error_message, + error: ref error_message, .. } | lexer::error::LexerError::UnterminatedComment { - error: error_message, + error: ref error_message, .. } | lexer::error::LexerError::UnterminatedString { - error: error_message, + error: ref error_message, .. }) = error; From 026b09ce264f878d84a7b72d13c3c0454fe389cd Mon Sep 17 00:00:00 2001 From: ElBe-Plaq <90863907+ElBe-Plaq@users.noreply.github.com> Date: Tue, 26 Mar 2024 22:01:55 +0100 Subject: [PATCH 08/10] feat(tools): Added terminal tool --- crates/tools/Cargo.toml | 1 + crates/tools/src/lib.rs | 1 + crates/tools/src/terminal.rs | 71 ++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 crates/tools/src/terminal.rs diff --git a/crates/tools/Cargo.toml b/crates/tools/Cargo.toml index cdf06dd..3983fe2 100644 --- a/crates/tools/Cargo.toml +++ b/crates/tools/Cargo.toml @@ -20,6 +20,7 @@ clap-verbosity-flag = { version = "2.1.1", optional = true } current_locale = { version = "0.1.1", optional = true } env_logger = "0.10.1" localizer-rs = { version = "1.2.0", optional = true } +regex = "1.10.4" log.workspace = true diff --git a/crates/tools/src/lib.rs b/crates/tools/src/lib.rs index 156ee89..2cf2303 100644 --- a/crates/tools/src/lib.rs +++ b/crates/tools/src/lib.rs @@ -30,5 +30,6 @@ pub mod beta; pub mod iterator; pub mod logging; pub mod panic_handler; +pub mod terminal; #[cfg(feature = "localization")] pub mod translation; diff --git a/crates/tools/src/terminal.rs b/crates/tools/src/terminal.rs new file mode 100644 index 0000000..39b88eb --- /dev/null +++ b/crates/tools/src/terminal.rs @@ -0,0 +1,71 @@ +// I Language terminal styling tools. +// Version: 1.0.0 + +// Copyright (c) 2023-present I Language Development. + +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the 'Software'), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +///////////// +// IMPORTS // +///////////// + +use regex::{Error, Regex}; + + +//////////////////// +// REMOVE STYLING // +//////////////////// + +// A trait for removing terminal styling (colors, formatting, etc.) from text. +// Used for using unstyled text in places where styled text can't be used. +pub trait RemoveStyling { + /// Removes all terminal styling from the text. + /// + /// # Parameters + /// + /// - `self`: The text to remove the terminal styling in. + /// + /// # Returns + /// + /// A result of the text with the terminal styling removed or a regex compile error. + /// + /// # Errors + /// + /// Errors when the creation of the regex fails. + /// + /// # Examples + /// + /// ```rust + /// + /// # use tools::terminal::RemoveStyling; + /// assert_eq!(&(r"\x1B[31mRed\x1B[0m".remove_styling().unwrap()), "Red"); + /// + /// ``` + fn remove_styling(&self) -> Result; +} + +impl RemoveStyling for &str { + #[inline] + fn remove_styling(&self) -> Result { + match Regex::new(r"\\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]") { + Ok(regex) => Ok(regex.replace_all(self, "").to_string()), + Err(error) => Err(error), + } + } +} From e6980d2354d79a8804906607f662ae2522042472 Mon Sep 17 00:00:00 2001 From: Aitareo Das Date: Tue, 26 Mar 2024 21:24:25 -0700 Subject: [PATCH 09/10] Improving the compiler #1 --- crates/compiler/src/lexer.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 crates/compiler/src/lexer.rs diff --git a/crates/compiler/src/lexer.rs b/crates/compiler/src/lexer.rs new file mode 100644 index 0000000..6b61fa0 --- /dev/null +++ b/crates/compiler/src/lexer.rs @@ -0,0 +1,31 @@ +// lexer.rs + +#[derive(Debug, PartialEq)] +enum Token { + Number(i64), + Plus, + Minus, + Multiply, + Divide, +} + +fn lex(input: &str) -> Vec { + let mut tokens = Vec::new(); + // Implement your lexer logic here + // For simplicity, let's assume input contains only numbers, +, -, *, / + // You'd need to handle whitespace, error cases, and more complex tokens in a real compiler + for token_str in input.split_whitespace() { + match token_str { + "+" => tokens.push(Token::Plus), + "-" => tokens.push(Token::Minus), + "*" => tokens.push(Token::Multiply), + "/" => tokens.push(Token::Divide), + _ => { + if let Ok(num) = token_str.parse::() { + tokens.push(Token::Number(num)); + } + } + } + } + tokens +} From ae0df6e685e9a61fa24620d374877724d658fddd Mon Sep 17 00:00:00 2001 From: Aitareo Das Date: Tue, 26 Mar 2024 21:25:02 -0700 Subject: [PATCH 10/10] Create parser.rs --- crates/compiler/src/parser.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 crates/compiler/src/parser.rs diff --git a/crates/compiler/src/parser.rs b/crates/compiler/src/parser.rs new file mode 100644 index 0000000..036a48c --- /dev/null +++ b/crates/compiler/src/parser.rs @@ -0,0 +1,23 @@ +// parser.rs + +#[derive(Debug)] +enum Expr { + Number(i64), + BinaryOp(Box, Token, Box), +} + +fn parse(tokens: &[Token]) -> Expr { + // Implement your parser logic here + // For simplicity, assume correct input and only handle + and * operators + // You'd need to handle operator precedence and other expressions in a real compiler + // Recursive descent parsing is a common approach + // Build the AST based on the token stream + // ... +} + +fn main() { + let input = "10 + 5 * 3"; + let tokens = lex(input); + let ast = parse(&tokens); + println!("{:?}", ast); +}