Website Summary Files Commits Branches @commit @diff @stats
path: root / assembler / src
diff options
context:
space:
mode:
Commit3ea01bbd75cc252453cd21074f56eb9cc6cff317 (patch)
Author
 Syndamia <kamen@syndamia.com>
2025-02-13 20:31:03 +0200
Committer
 Syndamia <kamen@syndamia.com>
2025-02-13 20:31:03 +0200
Filesc20d29c5c9aa100943fc82482b4d6778bed1235d /assembler/src
tonkobali-3ea01bbd75cc252453cd21074f56eb9cc6cff317.tar
tonkobali-3ea01bbd75cc252453cd21074f56eb9cc6cff317.tar.gz
tonkobali-3ea01bbd75cc252453cd21074f56eb9cc6cff317.zip
Parentf685950f30bbcfca8ab3cdceb90f6deee09a45fb (diff)
feat(assembler): Implement lexer
2 files changed, 101 insertions, 1 deletions
-rw-r--r--assembler/src/lexer/mod.rs85
-rw-r--r--assembler/src/main.rs17
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);
}