diff options
| Commit | 3ea01bbd75cc252453cd21074f56eb9cc6cff317 (patch) | |
|---|---|---|
| Author | 2025-02-13 20:31:03 +0200 | |
| Committer | 2025-02-13 20:31:03 +0200 | |
| Files | c20d29c5c9aa100943fc82482b4d6778bed1235d /assembler/src | |
| tonkobali-3ea01bbd75cc252453cd21074f56eb9cc6cff317.tar tonkobali-3ea01bbd75cc252453cd21074f56eb9cc6cff317.tar.gz tonkobali-3ea01bbd75cc252453cd21074f56eb9cc6cff317.zip | ||
| Parent | f685950f30bbcfca8ab3cdceb90f6deee09a45fb (diff) | |
feat(assembler): Implement lexer
2 files changed, 101 insertions, 1 deletions
| -rw-r--r-- | assembler/src/lexer/mod.rs | 85 | ||||
| -rw-r--r-- | assembler/src/main.rs | 17 |
diff --git a/assembler/src/lexer/mod.rs b/assembler/src/lexer/mod.rs new file mode 100644 index 0000000..617aca1 --- /dev/null +++ b/assembler/src/lexer/mod.rs @@ -0,0 +1,85 @@ +#[derive(Debug, Clone, PartialEq, Eq)] +pub(crate) enum Token { + Label(String), + Operator(String), + Symbol(String), + Number(i64), + String(String), +} + +pub fn split(mut line: String) -> Vec<Token> { + line.push('\n'); + + let mut res = Vec::new(); + let mut buffer = String::new(); + + let mut has_label = false; + let mut string_started = false; + let mut skip_next = false; + + for c in line.chars() { + buffer.push(c); + if skip_next || (string_started && c != '"') { + skip_next = false; + continue; + } + + match c { + ':' => if ! has_label { + buffer.pop(); + res.push(Token::Label(buffer.clone())); + buffer.clear(); + has_label = true; + } + else { + panic!("Found double labels!"); + }, + ' ' | '\t' => { + buffer.pop(); + if buffer.is_empty() { continue; } + + if (has_label && (res.len() == 1)) || + (!has_label && (res.is_empty())) { + res.push(Token::Operator(buffer.clone())); + buffer.clear(); + } + }, + '"' => { + buffer.pop(); + if string_started { + res.push(Token::String(buffer.clone())); + buffer.clear(); + } + string_started = !string_started; + }, + ',' | '\n' => { + buffer.pop(); + if buffer.is_empty() { continue; } + + if let Some(num) = buffer.parse::<i64>().ok() { + res.push(Token::Number(num)); + } + else { + res.push(Token::Symbol(buffer.clone())); + } + buffer.clear(); + }, + '\\' => skip_next = true, + ';' => break, + '=' => if buffer.is_empty() { + panic!("Cannot begin the line with an =") + } + else if let Token::Operator(name) = &res[0] { + res[0] = Token::Symbol(name.clone()); + buffer.clear(); + } + else { + panic!("Before an = you may only have a symbol name!"); + }, + 'A'..='Z' | 'a'..='z' | '0'..='9' | '_' | '-' | '.' | '$' | '?' + => {}, + _ => panic!("Found invalid character '{}'", c), + } + } + res +} diff --git a/assembler/src/main.rs b/assembler/src/main.rs index e7a11a9..0cda74e 100644 --- a/assembler/src/main.rs +++ b/assembler/src/main.rs @@ -1,3 +1,18 @@ +mod lexer; + +use std::fs::File; +use std::io::{BufRead, BufReader}; + fn main() { - println!("Hello, world!"); + let file_path = "./example.s"; + + let file = File::open(file_path).unwrap(); + let lines = BufReader::new(file).lines(); + + let mut tokens = Vec::new(); + for line in lines.map_while(Result::ok) { + tokens.extend(lexer::split(line)); + } + + println!("{:#?}", tokens); } |
