91 lines
2.3 KiB
Rust
91 lines
2.3 KiB
Rust
use hence::assembler::ToCode;
|
|
use itertools::Itertools;
|
|
|
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
|
pub struct StackResult {
|
|
pub before: Vec<String>,
|
|
pub after: Vec<String>,
|
|
}
|
|
|
|
impl ToCode for StackResult {
|
|
fn to_code(&self) -> String {
|
|
format!(
|
|
"{}--{}",
|
|
if self.before.is_empty() {
|
|
"".to_string()
|
|
} else {
|
|
format!("{} ", self.before.join(" "))
|
|
},
|
|
if self.after.is_empty() {
|
|
"".to_string()
|
|
} else {
|
|
format!("{} ", self.after.join(" "))
|
|
}
|
|
)
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Eq)]
|
|
pub enum Node {
|
|
Comment(String),
|
|
String {
|
|
mode: String,
|
|
string: String,
|
|
},
|
|
Number(i32),
|
|
WordDefinition {
|
|
name: String,
|
|
stack: Option<StackResult>,
|
|
body: Body,
|
|
},
|
|
Condition {
|
|
if_body: Body,
|
|
else_body: Body,
|
|
},
|
|
Word(String),
|
|
}
|
|
|
|
impl ToCode for Node {
|
|
fn to_code(&self) -> String {
|
|
match self {
|
|
Node::Comment(x) => format!("\\ {}", x),
|
|
Node::String { mode, string } => format!("{}\" {}\"", mode, string),
|
|
Node::Number(x) => x.to_string(),
|
|
Node::WordDefinition { name, stack, body } => format!(
|
|
": {}{} {} ;",
|
|
name,
|
|
match stack {
|
|
Some(x) => format!(" {}", x.to_code()),
|
|
None => "".to_string(),
|
|
},
|
|
body.iter().map(|x| x.to_code()).join(" ")
|
|
),
|
|
Node::Condition { if_body, else_body } => {
|
|
if else_body.is_empty() {
|
|
format!("if {} then", if_body.iter().map(|x| x.to_code()).join(" "))
|
|
} else {
|
|
format!(
|
|
"if {} else {} then",
|
|
if_body.iter().map(|x| x.to_code()).join(" "),
|
|
else_body.iter().map(|x| x.to_code()).join(" ")
|
|
)
|
|
}
|
|
}
|
|
Node::Word(x) => x.to_owned(),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub type Body = Vec<Node>;
|
|
|
|
#[derive(Debug)]
|
|
pub struct AST {
|
|
pub body: Body,
|
|
}
|
|
|
|
impl ToCode for AST {
|
|
fn to_code(&self) -> String {
|
|
self.body.iter().map(|x| x.to_code()).join(" ")
|
|
}
|
|
}
|