xassembler/
parser.rs

1use crate::{compile::compile, rust::Rust, target::Compile, token::*};
2use pest::*;
3use pest::{
4    iterators::{Pair, Pairs},
5    Parser,
6};
7
8#[derive(Parser)]
9#[grammar = "xasm.pest"]
10pub struct Xasm;
11
12fn identifier(pair: Pair<Rule>) -> Identifier {
13    Identifier(pair.as_span().as_str().trim().to_string())
14}
15
16fn dot_identifier(mut pairs: Pairs<Rule>) -> Name {
17    Name::DotName(
18        Box::new({
19            let accessing = pairs.next().unwrap();
20            match accessing.as_rule() {
21                Rule::identifier => Value::Name(Name::Name(identifier(accessing))),
22                Rule::group => value(accessing.into_inner().into_iter().next().unwrap()),
23                _ => unreachable!(),
24            }
25        }),
26        pairs
27            .into_iter()
28            .map(identifier)
29            .collect::<Vec<Identifier>>(),
30    )
31}
32
33fn index_identifier(mut pairs: Pairs<Rule>) -> Name {
34    Name::IndexName(
35        Box::new({
36            let accessing = pairs.next().unwrap();
37            match accessing.as_rule() {
38                Rule::identifier => Value::Name(Name::Name(identifier(accessing))),
39                Rule::group => value(accessing.into_inner().into_iter().next().unwrap()),
40                _ => unreachable!(),
41            }
42        }),
43        pairs.into_iter().map(value).collect::<Vec<Value>>(),
44    )
45}
46
47fn name(pair: Pair<Rule>) -> Name {
48    let pair = pair.into_inner().next().unwrap();
49    match pair.as_rule() {
50        Rule::dot_identifier => dot_identifier(pair.into_inner()),
51        Rule::index_identifier => index_identifier(pair.into_inner()),
52        Rule::identifier => Name::Name(identifier(pair)),
53        Rule::name => name(pair),
54        _ => unreachable!(),
55    }
56}
57
58fn fncall(pair: Pair<Rule>) -> FnCall {
59    let mut pairs = pair.clone().into_inner();
60    let call_operand = pairs.next().unwrap();
61    FnCall(
62        Box::new(match call_operand.as_rule() {
63            Rule::name => Value::Name(name(call_operand)),
64            Rule::group => value(call_operand),
65            Rule::fncall => Value::FnCall(fncall(call_operand)),
66            _ => unreachable!(),
67        }),
68        pairs.into_iter().map(value).collect(),
69    )
70}
71
72fn literal(pair: Pair<Rule>) -> Literal {
73    let pair = pair.into_inner().next().unwrap();
74    match pair.as_rule() {
75        Rule::string_literal => {
76            let result = pair.as_str().to_string();
77            Literal::String(String::from(&result[1..result.len() - 1]))
78        }
79        Rule::number_literal => Literal::Number(pair.as_str().to_string()),
80        Rule::foreign_function_literal => Literal::ForeignFunction(pair.as_str()[1..].to_string()),
81        _ => unreachable!(),
82    }
83}
84
85fn value(pair: Pair<Rule>) -> Value {
86    let pair = pair.into_inner().next().unwrap();
87    match pair.as_rule() {
88        Rule::function => Value::Function(function(pair)),
89        Rule::fncall => Value::FnCall(fncall(pair)),
90        Rule::name => Value::Name(name(pair)),
91        Rule::literal => Value::Literal(literal(pair)),
92        Rule::group => value(pair),
93        Rule::value => value(pair),
94        _ => unreachable!(),
95    }
96}
97
98fn assignment(mut pairs: Pairs<Rule>) -> Expr {
99    Expr::Assignment(name(pairs.next().unwrap()), value(pairs.next().unwrap()))
100}
101
102fn args(pair: Pair<Rule>) -> Vec<Identifier> {
103    pair.into_inner().into_iter().map(identifier).collect()
104}
105
106fn suite(pair: Pair<Rule>) -> Suite {
107    Suite(pair.into_inner().into_iter().map(expr).collect())
108}
109
110fn function(pair: Pair<Rule>) -> Function {
111    let mut pairs = pair.into_inner();
112    Function(args(pairs.next().unwrap()), suite(pairs.next().unwrap()))
113}
114
115fn function_def(pair: Pair<Rule>) -> FunctionDef {
116    let mut pairs = pair.into_inner();
117    FunctionDef(
118        name(pairs.next().unwrap()),
119        Function(args(pairs.next().unwrap()), suite(pairs.next().unwrap())),
120    )
121}
122
123fn class_def(mut pairs: Pairs<Rule>) -> Expr {
124    Expr::StructDef(StructDef(
125        name(pairs.next().unwrap()),
126        pairs
127            .into_iter()
128            .map(function_def)
129            .collect::<Vec<FunctionDef>>(),
130    ))
131}
132
133fn while_loop(mut pairs: Pairs<Rule>) -> Expr {
134    Expr::WhileLoop(value(pairs.next().unwrap()), suite(pairs.next().unwrap()))
135}
136
137fn for_loop(mut pairs: Pairs<Rule>) -> Expr {
138    Expr::ForLoop {
139        counter: identifier(pairs.next().unwrap()),
140        element: identifier(pairs.next().unwrap()),
141        list: value(pairs.next().unwrap()),
142        body: suite(pairs.next().unwrap()),
143    }
144}
145
146fn if_then_else(mut pairs: Pairs<Rule>) -> Expr {
147    Expr::IfThenElse(
148        value(pairs.next().unwrap()),
149        suite(pairs.next().unwrap()),
150        pairs
151            .next()
152            .and_then(|s| Some(suite(s)))
153            .or_else(|| Some(Suite(vec![])))
154            .unwrap(),
155    )
156}
157
158fn expr(pair: Pair<Rule>) -> Expr {
159    let pair = pair.into_inner().next().unwrap();
160    match pair.as_rule() {
161        Rule::assignment => assignment(pair.into_inner()),
162        Rule::class_def => class_def(pair.into_inner()),
163        Rule::function_def => Expr::FunctionDef(function_def(pair)),
164        Rule::while_loop => while_loop(pair.into_inner()),
165        Rule::for_loop => for_loop(pair.into_inner()),
166        Rule::if_then_else => if_then_else(pair.into_inner()),
167        Rule::value => Expr::Value(value(pair)),
168        Rule::expr => expr(pair),
169        _ => unreachable!(),
170    }
171
172    // Ok(Expr(vec![]))
173}
174
175pub fn parse(input: &str) -> Result<Suite, String> {
176    let pairs = match Xasm::parse(Rule::program, input) {
177        Ok(parsed) => Ok(parsed),
178        Err(e) => Err(format!("{}", e)),
179    }?;
180
181    let mut result = vec![];
182    // println!("pairs {:#?}", pairs);
183    for pair in pairs {
184        match pair.as_rule() {
185            Rule::expr => {
186                let token = expr(pair.clone());
187                let compiled = Compile::<Rust>::compile(token.clone()).unwrap();
188                // println!("{:#?}\n\t=>\n{}", token, compiled);
189                result.push(token);
190            }
191            Rule::COMMENT => {}
192            Rule::EOI => {}
193            _ => unreachable!(),
194        }
195    }
196
197    Ok(Suite(result))
198}