introduced notion of a token

This commit is contained in:
MCorange 2023-03-18 20:21:45 +02:00
parent c34a09fc7a
commit fed3be5614
6 changed files with 101 additions and 68 deletions

View File

@ -2,7 +2,6 @@
name = "mclang" name = "mclang"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]

View File

@ -75,5 +75,14 @@ pub struct Token {
pub file: String, pub file: String,
pub line: u32, pub line: u32,
pub col: u32, pub col: u32,
pub text: String pub text: String,
pub typ: TokenType
}
#[derive(Debug, Clone)]
pub enum TokenType {
Word,
Int,
// String,
//TODO: Add char
} }

View File

@ -8,7 +8,7 @@ fn stack_pop(stack: &mut Vec<u64>, pos: &(String, u32, u32)) -> Result<u64> {
match stack.pop() { match stack.pop() {
Some(i) => Ok(i), Some(i) => Ok(i),
None => { None => {
util::logger::pos_error(pos.clone(), "Stack underflow"); util::logger::pos_error(&pos.clone(), "Stack underflow");
Err(eyre!("Stack underflow")) Err(eyre!("Stack underflow"))
}, },
} }

View File

@ -1,8 +1,17 @@
use crate::constants::Token; use crate::constants::{Token, TokenType};
use color_eyre::Result; use color_eyre::Result;
fn lex_word(s: String) -> (TokenType, String) {
match s {
s if s.parse::<u64>().is_ok() => { // negative numbers not yet implemented
return (TokenType::Int, s);
},
s => {
return(TokenType::Word, s);
}
}
}
pub fn find_col<F>(text: String, mut col: u32, predicate: F) -> Result<u32> where F: Fn(char) -> bool { pub fn find_col<F>(text: String, mut col: u32, predicate: F) -> Result<u32> where F: Fn(char) -> bool {
while (col as usize) < text.len() && !predicate(text.chars().nth(col as usize).unwrap()) { while (col as usize) < text.len() && !predicate(text.chars().nth(col as usize).unwrap()) {
@ -49,11 +58,13 @@ pub fn lex(code: String, file: &String) -> Result<Vec<Token>> {
for (row, line) in lines { for (row, line) in lines {
let lt = lex_line(line)?; let lt = lex_line(line)?;
for (col, tok) in lt { for (col, tok) in lt {
let (tok_type, tok) = lex_word(tok);
let t = Token{ let t = Token{
file: file.clone(), file: file.clone(),
line: row + 1, line: row + 1,
col: col, col: col,
text: tok, text: tok,
typ: tok_type
}; };
tokens.push(t); tokens.push(t);
} }

View File

@ -1,4 +1,6 @@
use crate::{constants::{Operator, OpType, Token}, util}; use std::{collections::HashMap, ops::Deref};
use crate::{constants::{Operator, OpType, Token, TokenType}, util};
use color_eyre::Result; use color_eyre::Result;
use eyre::eyre; use eyre::eyre;
@ -13,7 +15,7 @@ pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
OpType::Else => { OpType::Else => {
let if_ip = stack.pop().unwrap(); let if_ip = stack.pop().unwrap();
if program[if_ip as usize].typ != OpType::If { if program[if_ip as usize].typ != OpType::If {
util::logger::pos_error(op.clone().pos,"'end' can only close 'if' blocks"); util::logger::pos_error(&op.clone().pos,"'end' can only close 'if' blocks");
std::process::exit(1); // idc std::process::exit(1); // idc
} }
@ -35,7 +37,7 @@ pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
program[ip].jmp = program[block_ip as usize].jmp; program[ip].jmp = program[block_ip as usize].jmp;
program[block_ip as usize].jmp = (ip + 1) as i32; program[block_ip as usize].jmp = (ip + 1) as i32;
} else { } else {
util::logger::pos_error(op.clone().pos,"'end' can only close 'if' blocks"); util::logger::pos_error(&op.clone().pos,"'end' can only close 'if' blocks");
std::process::exit(1); // idc std::process::exit(1); // idc
} }
@ -53,7 +55,7 @@ pub fn cross_ref(mut program: Vec<Operator>) -> Result<Vec<Operator>> {
} }
if stack.len() > 0 { if stack.len() > 0 {
util::logger::pos_error(program[stack.pop().expect("Empy stack") as usize].clone().pos,"Unclosed block"); util::logger::pos_error(&program[stack.pop().expect("Empy stack") as usize].clone().pos,"Unclosed block");
return Err(eyre!("Unclosed block")); return Err(eyre!("Unclosed block"));
} }
@ -79,65 +81,75 @@ impl Parser {
continue; continue;
} }
let pos = (token.file.clone(), token.line, token.col); let pos = (token.file.clone(), token.line, token.col);
match token.text.as_str() { match token.typ {
t if t.parse::<u64>().is_ok() => { // negative numbers not yet implemented TokenType::Word => {
let num = t.parse::<i64>().unwrap(); let word_type = lookup_word(token.text.clone(), &pos)?;
tokens.push(Operator::new(OpType::Push, num, token.file.clone(), token.line, token.col)); tokens.push(Operator { typ: word_type , value: 0, jmp: 0, pos: pos });
}, },
TokenType::Int => {// negative numbers not yet implemented
"print" => tokens.push(Operator::new(OpType::Print, 0, token.file.clone(), token.line, token.col)), tokens.push(Operator::new(OpType::Push, token.text.parse::<i64>()?, token.file.clone(), token.line, token.col));
},
// stack };
"dup" => tokens.push(Operator::new(OpType::Dup, 0, token.file.clone(), token.line, token.col)),
"drop" => tokens.push(Operator::new(OpType::Drop, 0, token.file.clone(), token.line, token.col)),
"2dup" => tokens.push(Operator::new(OpType::Dup2, 0, token.file.clone(), token.line, token.col)),
"rot" => tokens.push(Operator::new(OpType::Rot, 0, token.file.clone(), token.line, token.col)),
"over" => tokens.push(Operator::new(OpType::Over, 0, token.file.clone(), token.line, token.col)),
"swap" => tokens.push(Operator::new(OpType::Swap, 0, token.file.clone(), token.line, token.col)),
// comp and math
"+" => tokens.push(Operator::new(OpType::Plus, 0, token.file.clone(), token.line, token.col)), //"print" => tokens.push(Operator::new(OpType::Print, 0, token.file.clone(), token.line, token.col)),
"-" => tokens.push(Operator::new(OpType::Minus, 0, token.file.clone(), token.line, token.col)),
"=" => tokens.push(Operator::new(OpType::Equals, 0, token.file.clone(), token.line, token.col)),
">" => tokens.push(Operator::new(OpType::Gt, 0, token.file.clone(), token.line, token.col)),
"<" => tokens.push(Operator::new(OpType::Lt, 0, token.file.clone(), token.line, token.col)),
"band" => tokens.push(Operator::new(OpType::Band, 0, token.file.clone(), token.line, token.col)),
"bor" => tokens.push(Operator::new(OpType::Bor, 0, token.file.clone(), token.line, token.col)),
"shr" => tokens.push(Operator::new(OpType::Shr, 0, token.file.clone(), token.line, token.col)),
"shl" => tokens.push(Operator::new(OpType::Shl, 0, token.file.clone(), token.line, token.col)),
"/" => tokens.push(Operator::new(OpType::Div, 0, token.file.clone(), token.line, token.col)),
"*" => tokens.push(Operator::new(OpType::Mul, 0, token.file.clone(), token.line, token.col)),
// block
"if" => tokens.push(Operator::new(OpType::If, 0, token.file.clone(), token.line, token.col)),
"else" => tokens.push(Operator::new(OpType::Else, 0, token.file.clone(), token.line, token.col)),
"end" => tokens.push(Operator::new(OpType::End, 0, token.file.clone(), token.line, token.col)),
"while" => tokens.push(Operator::new(OpType::While, 0, token.file.clone(), token.line, token.col)),
"do" => tokens.push(Operator::new(OpType::Do, 0, token.file.clone(), token.line, token.col)),
// mem
"mem" => tokens.push(Operator::new(OpType::Mem, 0, token.file.clone(), token.line, token.col)),
"!8" => tokens.push(Operator::new(OpType::Load8, 0, token.file.clone(), token.line, token.col)),
"@8" => tokens.push(Operator::new(OpType::Store8, 0, token.file.clone(), token.line, token.col)),
"syscall0" => tokens.push(Operator::new(OpType::Syscall0, 0, token.file.clone(), token.line, token.col)),
"syscall1" => tokens.push(Operator::new(OpType::Syscall1, 0, token.file.clone(), token.line, token.col)),
"syscall2" => tokens.push(Operator::new(OpType::Syscall2, 0, token.file.clone(), token.line, token.col)),
"syscall3" => tokens.push(Operator::new(OpType::Syscall3, 0, token.file.clone(), token.line, token.col)),
"syscall4" => tokens.push(Operator::new(OpType::Syscall4, 0, token.file.clone(), token.line, token.col)),
"syscall5" => tokens.push(Operator::new(OpType::Syscall5, 0, token.file.clone(), token.line, token.col)),
"syscall6" => tokens.push(Operator::new(OpType::Syscall6, 0, token.file.clone(), token.line, token.col)),
t => {
util::logger::pos_error(pos, format!("Unknown token '{}'", t).as_str());
return Err(eyre!("Unknown token"));
}
}
} }
Ok(cross_ref(tokens)?) Ok(cross_ref(tokens)?)
} }
}
fn lookup_word<P: Deref<Target = (String, u32, u32)>>(s: String, pos: P) -> Result<OpType>{
let lookup_table: HashMap<&str, OpType> = HashMap::from([
//stack
("print", OpType::Print),
("dup", OpType::Dup),
("drop", OpType::Drop),
("2dup", OpType::Dup2),
("rot", OpType::Rot),
("over", OpType::Over),
("swap", OpType::Swap),
// comp and math
("+", OpType::Plus),
("-", OpType::Minus),
("=", OpType::Equals),
(">", OpType::Gt),
("<", OpType::Lt),
("band", OpType::Band),
("bor", OpType::Bor),
("shr", OpType::Shr),
("shl", OpType::Shl),
("/", OpType::Div),
("*", OpType::Mul),
// block
("if", OpType::If),
("else", OpType::Else),
("end", OpType::End),
("while", OpType::While),
("do", OpType::Do),
// mem
("mem", OpType::Mem),
("!8", OpType::Load8),
("@8", OpType::Store8),
("syscall0", OpType::Syscall0),
("syscall1", OpType::Syscall1),
("syscall2", OpType::Syscall2),
("syscall3", OpType::Syscall3),
("syscall4", OpType::Syscall4),
("syscall5", OpType::Syscall5),
("syscall6", OpType::Syscall6),
]);
match lookup_table.get(s.as_str()) {
Some(v) => Ok(v.clone()),
None => {
util::logger::pos_error(pos, format!("Unknown word '{}'", s).as_str());
return Err(eyre!("Unknown word"))
}
}
} }

View File

@ -30,6 +30,8 @@ pub mod color {
pub mod logger { pub mod logger {
#![allow(dead_code)] #![allow(dead_code)]
use std::ops::Deref;
use crate::util::color; use crate::util::color;
pub fn error(msg: &str) { pub fn error(msg: &str) {
@ -49,19 +51,19 @@ pub mod logger {
} }
pub fn pos_error(pos: (String, u32, u32), msg: &str) { pub fn pos_error<P: Deref<Target = (String, u32, u32)>>(pos: P, msg: &str) {
println!("{f}:{r}:{c} {red}error{rs}: {msg}", red=color::FG_RED, rs=color::RESET, f=pos.0, r=pos.1, c=pos.2); println!("{f}:{r}:{c} {red}error{rs}: {msg}", red=color::FG_RED, rs=color::RESET, f=pos.0, r=pos.1, c=pos.2);
} }
pub fn pos_warn(pos: (String, u32, u32), msg: &str) { pub fn pos_warn<P: Deref<Target = (String, u32, u32)>>(pos: P, msg: &str) {
println!("{f}:{r}:{c} {yellow}warn{rs}: {msg}", yellow=color::FG_YELLOW, rs=color::RESET, f=pos.0, r=pos.1, c=pos.2); println!("{f}:{r}:{c} {yellow}warn{rs}: {msg}", yellow=color::FG_YELLOW, rs=color::RESET, f=pos.0, r=pos.1, c=pos.2);
} }
pub fn pos_info(pos: (String, u32, u32), msg: &str) { pub fn pos_info<P: Deref<Target = (String, u32, u32)>>(pos: P, msg: &str) {
println!("{f}:{r}:{c} {green}info{rs}: {msg}", green=color::FG_GREEN, rs=color::RESET, f=pos.0, r=pos.1, c=pos.2); println!("{f}:{r}:{c} {green}info{rs}: {msg}", green=color::FG_GREEN, rs=color::RESET, f=pos.0, r=pos.1, c=pos.2);
} }
pub fn pos_note(pos: (String, u32, u32), msg: &str) { pub fn pos_note<P: Deref<Target = (String, u32, u32)>>(pos: P, msg: &str) {
println!("{f}:{r}:{c} {blue}note{rs}: {msg}", blue=color::FG_BLUE, rs=color::RESET, f=pos.0, r=pos.1, c=pos.2); println!("{f}:{r}:{c} {blue}note{rs}: {msg}", blue=color::FG_BLUE, rs=color::RESET, f=pos.0, r=pos.1, c=pos.2);
} }