diff options
| author | Jan Tuomi <jans.tuomi@gmail.com> | 2021-11-21 20:03:08 +0200 |
|---|---|---|
| committer | Jan Tuomi <jans.tuomi@gmail.com> | 2021-11-21 20:03:08 +0200 |
| commit | 4b845f566fabcab20992aa75dee5b6bf64f39573 (patch) | |
| tree | 4ac21887af8d18d35bef3d7210959756003cf082 /src/ast.rs | |
| parent | 54e14921df8c5402066979e645e4ca49748238a8 (diff) | |
Split project into separate files
Diffstat (limited to 'src/ast.rs')
| -rw-r--r-- | src/ast.rs | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/src/ast.rs b/src/ast.rs new file mode 100644 index 0000000..dc0aa79 --- /dev/null +++ b/src/ast.rs @@ -0,0 +1,134 @@ +use super::lparser::Rule; +use std::rc::Rc; + +pub fn from_parse_tree(parse_tree: &mut pest::iterators::Pairs<Rule>) -> Program { + let root = parse_tree.next().unwrap(); + + match root.as_rule() { + Rule::program => { + let statements_with_eoi: Vec<pest::iterators::Pair<Rule>> = root.into_inner().collect(); + let statements_split = statements_with_eoi.split_last().unwrap(); + let statements = statements_split.1.to_vec(); + + statements + .iter() + .map(|s| Statement::from_pair(s.clone())) + .collect() + } + _ => panic!("[ast] first Pair is not a program"), + } +} + +pub type Program = Vec<Statement>; + +#[derive(Debug)] +pub enum Statement { + Definition { + symbol: Symbol, + expression: Rc<Expression>, + }, + Expression(Rc<Expression>), +} + +impl Statement { + fn from_pair(pair: pest::iterators::Pair<Rule>) -> Statement { + let def_or_expr = pair.into_inner().next().unwrap(); + + fn definition_from_pair(pair: pest::iterators::Pair<Rule>) -> Statement { + let mut inner = pair.into_inner(); + let symbol = inner.next().unwrap().as_span().as_str(); + let expression = inner.next().unwrap(); + let expression_inners: Vec<ExpressionInner> = expression + .into_inner() + .map(ExpressionInner::from_pair) + .collect(); + + Statement::Definition { + symbol: String::from(symbol), + expression: expression_vec_to_tuple(&expression_inners), + } + } + + match def_or_expr.as_rule() { + Rule::definition => definition_from_pair(def_or_expr), + Rule::expression => { + let expression_inners: Vec<ExpressionInner> = def_or_expr + .into_inner() + .map(ExpressionInner::from_pair) + .collect(); + Statement::Expression(expression_vec_to_tuple(&expression_inners)) + } + rule => panic!("[ast] can't make a statement from {:#?}", rule), + } + } +} + +#[derive(Debug, Clone)] +pub enum ExpressionInner { + Symbol(Symbol), + IntegerLiteral(IntegerLiteral), + StringLiteral(StringLiteral), + Expression(Rc<Expression>), +} + +impl ExpressionInner { + fn from_pair(pair: pest::iterators::Pair<Rule>) -> ExpressionInner { + match pair.as_rule() { + Rule::symbol => ExpressionInner::Symbol(string_from_pair(pair)), + Rule::integer_literal => ExpressionInner::IntegerLiteral(integer_from_pair(pair)), + Rule::string_literal => { + let s_with_quotes = string_from_pair(pair); + let mut chars = s_with_quotes.chars(); + chars.next(); + chars.next_back(); + let s = chars.as_str(); + ExpressionInner::StringLiteral(String::from(s)) + } + Rule::expression => { + let expression_inners: Vec<ExpressionInner> = + pair.into_inner().map(ExpressionInner::from_pair).collect(); + ExpressionInner::Expression(expression_vec_to_tuple(&expression_inners)) + } + rule => panic!("[ast] can't make an expression element from {:#?}", rule), + } + } +} + +#[derive(Debug)] +pub enum Expression { + Unary(ExpressionInner), + Binary(ExpressionInner, ExpressionInner), +} + +fn expression_vec_to_tuple(v: &Vec<ExpressionInner>) -> Rc<Expression> { + match v.len() { + 1 => Rc::new(Expression::Unary(v[0].clone())), + 2 => Rc::new(Expression::Binary(v[0].clone(), v[1].clone())), + _ => { + let combined = ExpressionInner::Expression(Rc::new(Expression::Binary( + v[0].clone(), + v[1].clone(), + ))); + + let mut new_v = vec![combined]; + for e in &v[2..] { + new_v.push(e.clone()); + } + + expression_vec_to_tuple(&new_v) + } + } +} + +pub type IntegerLiteral = i64; +fn integer_from_pair(pair: pest::iterators::Pair<Rule>) -> i64 { + let s = pair.as_span().as_str(); + s.parse().unwrap() +} + +pub type StringLiteral = String; +fn string_from_pair(pair: pest::iterators::Pair<Rule>) -> String { + String::from(pair.as_span().as_str()) +} + +pub type Symbol = String; |
