Skip to content

Instantly share code, notes, and snippets.

@Krout0n
Created May 13, 2020 05:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Krout0n/68ef74fb326bb82f0d16c862f5614fc0 to your computer and use it in GitHub Desktop.
Save Krout0n/68ef74fb326bb82f0d16c862f5614fc0 to your computer and use it in GitHub Desktop.
type AST = Expression;
#[derive(Debug, PartialEq)]
pub enum Expression {
Apply {
fn_lit: Box<Expression>,
args: Vec<Expression>,
},
FunctionLiteral {
params: Vec<String>,
expr: Box<Expression>,
},
If {
condition: Box<Expression>,
consequence: Box<Expression>,
alternative: Box<Expression>,
},
Match {
pat: Box<Expression>,
matcher_and_consequence: Vec<(Box<Expression>, Box<Expression>)>,
},
Number(usize),
Ident(String),
}
impl From<usize> for Expression {
fn from(u: usize) -> Self {
Number(u)
}
}
impl<'a> From<&'a str> for Expression {
fn from(s: &'a str) -> Self {
Ident(s.to_string())
}
}
use Expression::*;
macro_rules! ast {
((If $cond:tt $conseq:tt $alt:tt)) => {
If {
condition: box_ast!($cond),
consequence: box_ast!($conseq),
alternative: box_ast!($alt),
}
};
((Lambda ($( $arg:ident )*) $expr:tt)) => (FunctionLiteral {
params: vec![$( stringify!($arg).to_string() ), *],
expr: box_ast!($expr)
});
((Match $pat:tt ( $(($matcher:tt => $expr:tt))* ))) => {
Match {
pat: box_ast!($pat),
matcher_and_consequence: vec![$((box_ast!($matcher), box_ast!($expr))), *]
}
};
(($fn_lit:tt $( $arg:tt )*)) => (Apply {
fn_lit: box_ast!($fn_lit),
args: vec![$( ast!($arg) ), *],
});
($name:ident) => (Expression::from(stringify!($name)));
($e:expr) => (Expression::from($e));
($symbol:tt) => (Expression::from(stringify!($symbol)));
}
macro_rules! box_ast {
($t:tt) => {
Box::new(ast!($t))
};
}
fn main() {
dbg!(ast!(2)); // Number(2)
dbg!(ast!(id)); // Ident("id")
dbg!(ast!((+ 1 2))); // Apply { fn_lit: Ident("+"), args: [Number(1) Number(2)] }
dbg!(ast!((Lambda (x y) 2))); // FunctionLiteral { params: ["x", "y",], expr: Number(2) }
dbg!(ast!((If 1 2 3))); // If { condition: Number(1), consequence: Number(2), alternative: Number(3) }
dbg!(ast!((Match 1 ((1 => 2) (2 => 3) (3 => 4))))); // Match { pat: Number(1) matcher_and_consequence: [ (Number(1), Number(2)), (Number(2), Number(3)), (Number(3), Number(4))]}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment