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 {
|
impl Display for Type {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Type::Int(i) => write!(f, "${}", i),
|
Type::Int(i) => write!(f, ":{}", i),
|
||||||
Type::Float(fl) => write!(f, "${}", fl),
|
Type::Float(fl) => write!(f, ":{}", fl),
|
||||||
Type::Boolean(b) => write!(f, "${}", b),
|
Type::Boolean(b) => write!(f, ":{}", b),
|
||||||
Type::String(s) => write!(f, "$\"{}\"", s),
|
Type::String(s) => write!(f, "$\"{}\"", s),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ impl FromStr for Type {
|
||||||
type Err = String;
|
type Err = String;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
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));
|
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 {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
// Instr::Load { address, label } => write!(f, "{}: LOAD {}", label, address),
|
// Instr::Load { address, label } => write!(f, "{}: LOAD {}", label, address),
|
||||||
Instr::Store { address, value , label} => write!(f, "{}: STORE {} {}", label, address, value),
|
Instr::Store { address, value , label} => write!(f, "{} STORE {} {}", label, address, value),
|
||||||
Instr::Call { address, args, label } => write!(f, "{}: CALL {} {}", label, address, args),
|
Instr::Call { address, args, label } => write!(f, "{} CALL {} {}", label, address, args),
|
||||||
Instr::Push { value, label } => write!(f, "{}: PUSH {}", label, value),
|
Instr::Push { value, label } => write!(f, "{} PUSH {}", label, value),
|
||||||
Instr::Pop { address, label } => write!(f, "{}: POP {}", label, address),
|
Instr::Pop { address, label } => write!(f, "{} POP {}", label, address),
|
||||||
Instr::Add { label } => write!(f, "{}: ADD", label),
|
Instr::Add { label } => write!(f, "{} ADD", label),
|
||||||
Instr::Sub { label } => write!(f, "{}: SUB", label),
|
Instr::Sub { label } => write!(f, "{} SUB", label),
|
||||||
Instr::Mul { label } => write!(f, "{}: MUL", label),
|
Instr::Mul { label } => write!(f, "{} MUL", label),
|
||||||
Instr::Div { label } => write!(f, "{}: DIV", label),
|
Instr::Div { label } => write!(f, "{} DIV", label),
|
||||||
Instr::Jump { to, label } => write!(f, "{}: JUMP {}", label, to),
|
Instr::Jump { to, label } => write!(f, "{} JMP {}", label, to),
|
||||||
Instr::PopJumpIfFalse { to, label } => write!(f, "{}: POP_JUMP_IF_FALSE {}", label, to),
|
Instr::PopJumpIfFalse { to, label } => write!(f, "{} POP_JUMP_IF_FALSE {}", label, to),
|
||||||
Instr::Return { value, label } => write!(f, "{}: RETURN {}", label, value),
|
Instr::Return { value, label } => write!(f, "{} RETURN {}", label, value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,57 +1,60 @@
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
use crate::vm::instr::*;
|
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> {
|
pub fn parse_instr(src: &str) -> Vec<Instr> {
|
||||||
|
let regex = Regex::new(REGEX).unwrap();
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
|
|
||||||
for line in src.lines() {
|
for line in src.lines() {
|
||||||
// <label>: <instr> <arg>+
|
let tokens = regex.find_iter(line).map(|m| m.as_str()).collect::<Vec<_>>();
|
||||||
let mut parts = line.split_whitespace();
|
if tokens[0].starts_with(";") { continue; }
|
||||||
|
|
||||||
let label = parts.next();
|
let label = label!(tokens[0]);
|
||||||
if label == Some(";") { continue; }
|
|
||||||
let instr = parts.next();
|
|
||||||
|
|
||||||
let mut args = Vec::new();
|
match tokens[1] {
|
||||||
let mut in_quote = false;
|
"STORE" => { result.push(Instr::Store {
|
||||||
let mut str = String::new();
|
address: register!(tokens[2]),
|
||||||
while let Some(part) = parts.next() { match in_quote {
|
value: value!(tokens[3]),
|
||||||
true => {
|
label,
|
||||||
if part.ends_with("\"") {
|
}); },
|
||||||
str.push_str(&format!(" {}", part.trim_end_matches("\"")));
|
"CALL" => { result.push(Instr::Call {
|
||||||
args.push(str);
|
address: register!(tokens[2]),
|
||||||
str = String::new();
|
args: register!(tokens[3]),
|
||||||
in_quote = false;
|
label,
|
||||||
} else { str.push_str(&format!(" {}", part)); }
|
}); },
|
||||||
},
|
"PUSH" => { result.push(Instr::Push {
|
||||||
false => {
|
value: value!(tokens[2]),
|
||||||
if part.starts_with("$\"") {
|
label,
|
||||||
str.push_str(&part.trim_start_matches("$\""));
|
}); },
|
||||||
in_quote = true;
|
"POP" => { result.push(Instr::Pop {
|
||||||
} else { args.push(part.to_string()); }
|
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
|
result
|
||||||
|
|
Loading…
Reference in a new issue