introduced notion of a token
This commit is contained in:
parent
c34a09fc7a
commit
fed3be5614
|
@ -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]
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
|
@ -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"))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
15
src/lexer.rs
15
src/lexer.rs
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
128
src/parser.rs
128
src/parser.rs
|
@ -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)),
|
|
||||||
"-" => 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)),
|
|
||||||
|
|
||||||
|
|
||||||
|
//"print" => tokens.push(Operator::new(OpType::Print, 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"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
src/util.rs
10
src/util.rs
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user