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 }
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 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 result.push(token);
190 }
191 Rule::COMMENT => {}
192 Rule::EOI => {}
193 _ => unreachable!(),
194 }
195 }
196
197 Ok(Suite(result))
198}