mirror of
https://github.com/azur1s/bobbylisp.git
synced 2024-10-16 02:37:40 -05:00
feat: simpler instruction parser
This commit is contained in:
parent
c80637cf6c
commit
cac125bd1c
|
@ -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 -------------
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
Loading…
Reference in a new issue