1use crate::{
2 Exception, ExceptionValue as EV, Expression, Keyword, Operator, Source, SourcePosition, Symbol,
3 Value,
4};
5use pest::iterators::Pair;
6use pest::Parser;
7
8use crate::Locker;
9
10#[derive(Parser)]
11#[grammar = "parser/syntax.pest"]
12pub struct SyntaxParser;
13
14pub fn parse(code: &str, location: &str) -> Result<Vec<Expression>, Exception> {
15 let source = Locker::new(Source::new(String::from(code), String::from(location)));
16
17 match SyntaxParser::parse(Rule::expressions, code) {
18 Ok(pairs) => {
19 let mut exps = Vec::new();
20 for pair in pairs {
21 if pair.as_rule() == Rule::EOI {
22 continue;
24 }
25 exps.push(
26 build_expression(pair.clone(), source.clone())?
27 .with_source(SourcePosition::from_pair(&pair, &source)),
28 );
29 }
30 Ok(exps)
31 }
32 Err(err) => Err(Exception::from(err)),
33 }
34}
35
36fn build_expression(pair: Pair<'_, Rule>, source: Locker<Source>) -> Result<Expression, Exception> {
37 let pos = SourcePosition::new(
38 pair.as_span().start_pos().pos(),
39 pair.as_span().end_pos().pos(),
40 source.clone(),
41 );
42 match &pair.as_rule() {
43 Rule::list => {
44 let mut values: Vec<Expression> = Vec::new();
45 for elem in pair.into_inner() {
46 values.push(
47 build_expression(elem.clone(), source.clone())?
48 .with_source(SourcePosition::from_pair(&elem, &source)),
49 )
50 }
51 Ok(Expression::new(Value::List(values)))
52 }
53 Rule::symbol => Ok(Expression::new(Value::Symbol(Symbol::new(String::from(
54 pair.as_str(),
55 ))))
56 .with_source(pos)),
57 Rule::keyword => Ok(Expression::new(Value::Keyword(Keyword::new(String::from(
58 pair.into_inner().next().unwrap().as_str(),
59 ))))
60 .with_source(pos)),
61 Rule::number => match pair.as_str().parse::<f64>() {
62 Ok(num) => Ok(Expression::new(Value::Number(num)).with_source(pos)),
63 Err(_) => Err(Exception::new(
64 EV::Syntax,
65 None,
66 Some(format!("`{}` is not a valid number", pair.as_str())),
67 )),
68 },
69 Rule::byte => match pair.as_str().replace('b', "").parse::<u8>() {
70 Ok(num) => Ok(Expression::new(Value::Byte(num)).with_source(pos)),
71 Err(_) => Err(Exception::new(
72 EV::Syntax,
73 None,
74 Some(format!("`{}` is not a valid byte (0-255)", pair.as_str())),
75 )),
76 },
77 Rule::text => Ok(Expression::new(Value::Text(
78 pair.into_inner().as_str().to_string(),
79 ))),
80
81 Rule::quote | Rule::eval => {
83 let mut elements = vec![Expression::new(Value::Operator(match &pair.as_rule() {
84 Rule::quote => Operator::Quote,
85 Rule::eval => Operator::Eval,
86 _ => unreachable!(),
87 }))];
88 for elem in pair.into_inner() {
89 elements.push(
90 build_expression(elem.clone(), source.clone())?
91 .with_source(SourcePosition::from_pair(&elem, &source)),
92 );
93 }
94 Ok(Expression::new(Value::List(elements)))
95 }
96 _ => Err(Exception::new(
97 EV::Syntax,
98 None,
99 Some(format!("unknown syntax element `{}`", pair.as_str())),
100 )),
101 }
102}