1
1
Fork 0
mirror of https://github.com/azur1s/bobbylisp.git synced 2024-09-28 07:17:41 +00:00

feat: simpler instruction parser

This commit is contained in:
Natapat Samutpong 2022-01-27 10:43:46 +07:00
parent c80637cf6c
commit cac125bd1c
7 changed files with 64 additions and 80 deletions

View file

@ -1,19 +0,0 @@
; ------------------------------
; (if true (print (+ 34 35)) (print "False"))
; ------- Condition block ------
1: STORE r1 $true ; r1 = True
2: JUMP_IF_FALSE r1 9 ; if
; --------- True block ---------
3: STORE r2 $34 ; r2 = 34
4: STORE r3 $35 ; r3 = 35
5: IADD r2 r3 r4 ; r2 + r3 -> r4
6: STORE r5 $1 ; r5 = 1 (function calling)
7: CALL r5 r4 ; call 1 (print) 34 (r4)
8: JUMP 12
; -------- False block ---------
9: STORE r6 $"False" ; r6 = "False"
10: STORE r7 $1 ; r7 = 1 (function calling)
11: CALL r7 r6 ; call 1 (print) "False" (r6)
12: STORE r8 $0 ; r8 = 0 (return value)
13: RETURN r8 ; return 0 (exit code)
; ------------ End -------------

View file

@ -12,9 +12,9 @@ pub enum Type {
impl Display for Type {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Type::Int(i) => write!(f, "${}", i),
Type::Float(fl) => write!(f, "${}", fl),
Type::Boolean(b) => write!(f, "${}", b),
Type::Int(i) => write!(f, ":{}", i),
Type::Float(fl) => write!(f, ":{}", fl),
Type::Boolean(b) => write!(f, ":{}", b),
Type::String(s) => write!(f, "$\"{}\"", s),
}
}
@ -24,7 +24,7 @@ impl FromStr for Type {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if !s.starts_with("$") {
if !s.starts_with("$") && !s.starts_with(":") {
return Err(format!("Invalid literal: {}", s));
}
@ -92,17 +92,17 @@ impl Display for Instr {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
// Instr::Load { address, label } => write!(f, "{}: LOAD {}", label, address),
Instr::Store { address, value , label} => write!(f, "{}: STORE {} {}", label, address, value),
Instr::Call { address, args, label } => write!(f, "{}: CALL {} {}", label, address, args),
Instr::Push { value, label } => write!(f, "{}: PUSH {}", label, value),
Instr::Pop { address, label } => write!(f, "{}: POP {}", label, address),
Instr::Add { label } => write!(f, "{}: ADD", label),
Instr::Sub { label } => write!(f, "{}: SUB", label),
Instr::Mul { label } => write!(f, "{}: MUL", label),
Instr::Div { label } => write!(f, "{}: DIV", label),
Instr::Jump { to, label } => write!(f, "{}: JUMP {}", label, to),
Instr::PopJumpIfFalse { to, label } => write!(f, "{}: POP_JUMP_IF_FALSE {}", label, to),
Instr::Return { value, label } => write!(f, "{}: RETURN {}", label, value),
Instr::Store { address, value , label} => write!(f, "{} STORE {} {}", label, address, value),
Instr::Call { address, args, label } => write!(f, "{} CALL {} {}", label, address, args),
Instr::Push { value, label } => write!(f, "{} PUSH {}", label, value),
Instr::Pop { address, label } => write!(f, "{} POP {}", label, address),
Instr::Add { label } => write!(f, "{} ADD", label),
Instr::Sub { label } => write!(f, "{} SUB", label),
Instr::Mul { label } => write!(f, "{} MUL", label),
Instr::Div { label } => write!(f, "{} DIV", label),
Instr::Jump { to, label } => write!(f, "{} JMP {}", label, to),
Instr::PopJumpIfFalse { to, label } => write!(f, "{} POP_JUMP_IF_FALSE {}", label, to),
Instr::Return { value, label } => write!(f, "{} RETURN {}", label, value),
}
}
}

View file

@ -1,58 +1,61 @@
use regex::Regex;
use crate::vm::instr::*;
const REGEX: &str = r###"[^\s\$";]+|\$"[^"]*"|;.*"###;
macro_rules! value { ($s:expr) => { $s.parse::<Type>().unwrap() }; }
macro_rules! register { ($s:expr) => { $s.parse::<Register>().unwrap() }; }
macro_rules! label { ($s:expr) => { $s.parse::<usize>().unwrap() }; }
pub fn parse_instr(src: &str) -> Vec<Instr> {
let regex = Regex::new(REGEX).unwrap();
let mut result = Vec::new();
for line in src.lines() {
// <label>: <instr> <arg>+
let mut parts = line.split_whitespace();
let tokens = regex.find_iter(line).map(|m| m.as_str()).collect::<Vec<_>>();
if tokens[0].starts_with(";") { continue; }
let label = parts.next();
if label == Some(";") { continue; }
let instr = parts.next();
let label = label!(tokens[0]);
let mut args = Vec::new();
let mut in_quote = false;
let mut str = String::new();
while let Some(part) = parts.next() { match in_quote {
true => {
if part.ends_with("\"") {
str.push_str(&format!(" {}", part.trim_end_matches("\"")));
args.push(str);
str = String::new();
in_quote = false;
} else { str.push_str(&format!(" {}", part)); }
},
false => {
if part.starts_with("$\"") {
str.push_str(&part.trim_start_matches("$\""));
in_quote = true;
} else { args.push(part.to_string()); }
match tokens[1] {
"STORE" => { result.push(Instr::Store {
address: register!(tokens[2]),
value: value!(tokens[3]),
label,
}); },
"CALL" => { result.push(Instr::Call {
address: register!(tokens[2]),
args: register!(tokens[3]),
label,
}); },
"PUSH" => { result.push(Instr::Push {
value: value!(tokens[2]),
label,
}); },
"POP" => { result.push(Instr::Pop {
address: register!(tokens[2]),
label,
}); },
"ADD" => { result.push(Instr::Add { label }); },
"SUB" => { result.push(Instr::Sub { label }); },
"MUL" => { result.push(Instr::Mul { label }); },
"DIV" => { result.push(Instr::Div { label }); },
"JMP" => { result.push(Instr::Jump {
to: label!(tokens[2]),
label,
}); },
"POP_JUMP_IF_FALSE" => { result.push(Instr::PopJumpIfFalse {
to: label!(tokens[2]),
label,
}); },
"RETURN" => { result.push(Instr::Return {
value: register!(tokens[2]),
label,
}); },
_ => panic!("Unknown instruction: {}", tokens[1]),
}
}
}
result.push(match instr {
Some("STORE") => {
let address = args[0].parse::<Register>().unwrap();
let value = args[1].parse::<Type>().unwrap();
let label = label.map(|l| l[..1].parse::<usize>().unwrap()).unwrap();
Instr::Store { address, value, label }
},
Some("CALL") => {
let address = args[0].parse::<Register>().unwrap();
let args = args[1].parse::<Register>().unwrap();
let label = label.map(|l| l[..1].parse::<usize>().unwrap()).unwrap();
Instr::Call { address, args, label }
},
Some("RETURN") => {
let value = args[0].parse::<Register>().unwrap();
let label = label.map(|l| l[..1].parse::<usize>().unwrap()).unwrap();
Instr::Return { value, label }
},
_ => panic!("Unknown instruction: {}", instr.unwrap())
});
}
result
}