hence/henceforth/src/parser/ast.rs

108 lines
2.8 KiB
Rust

use hence::assembler::ToCode;
use std::fmt;
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct StackResult {
pub before: Vec<String>,
pub after: Vec<String>,
}
impl fmt::Display for StackResult {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}--{}",
if self.before.is_empty() {
"".to_string()
} else {
format!("{} ", self.before.join(" "))
},
if self.after.is_empty() {
"".to_string()
} else {
format!("{} ", self.after.join(" "))
}
)
}
}
impl ToCode for StackResult {}
#[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 fmt::Display for Node {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Node::Comment(x) => write!(f, "\\ {}", x),
Node::String { mode, string } => write!(f, "{}\" {}\"", mode, string),
Node::Number(x) => write!(f, "{}", x),
Node::WordDefinition { name, stack, body } => write!(
f,
": {}{} {} ;",
name,
match stack {
Some(x) => format!(" {}", x),
None => "".to_string(),
},
// body.iter().map(|x| x.to_code()).join(" ")
itertools::free::join(body, " ")
),
Node::Condition { if_body, else_body } => {
if else_body.is_empty() {
write!(
f,
"if {} then",
// if_body.iter().map(|x| x.to_code()).join(" ")
itertools::free::join(if_body, " ")
)
} else {
write!(
f,
"if {} else {} then",
// if_body.iter().map(|x| x.to_code()).join(" "),
itertools::free::join(if_body, " "),
// else_body.iter().map(|x| x.to_code()).join(" ")
itertools::free::join(else_body, " "),
)
}
}
Node::Word(x) => write!(f, "{}", x),
}
}
}
impl ToCode for Node {}
pub type Body = Vec<Node>;
#[derive(Debug)]
pub struct AST {
pub body: Body,
}
impl fmt::Display for AST {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", itertools::free::join(&self.body, "\n"))
}
}
impl ToCode for AST {}