sexprs_parser/
lib.rs

1use std::borrow::Cow;
2pub mod errors;
3pub use errors::{Caller, Error, Result};
4pub mod macros;
5pub mod test;
6
7pub mod source;
8use std::str::FromStr;
9
10use sexprs_data_structures::{Cell, Value};
11use sexprs_util::unexpected;
12use pest::iterators::{Pair, Pairs};
13use pest::Parser;
14use pest_derive::Parser;
15pub use source::{Source, Span, SpanPosition};
16pub const GRAMMAR: &'static str = include_str!("./grammar.pest");
17
18#[derive(Parser, Debug, Clone)]
19#[grammar = "src/grammar.pest"]
20pub struct MinilispSource;
21pub fn parse_source<'a>(input: &'a str) -> Result<'a, Value<'a>> {
22    let source_info = Source {
23        source: Cow::from(input),
24        filename: None,
25    };
26    let mut pairs = MinilispSource::parse(Rule::file, input).map_err(|e| {
27        Error::new(
28            e.variant.message().to_string(),
29            Some(Span::from_error(e, source_info.clone())),
30        )
31    })?;
32    let file = pairs.next().unwrap();
33    let nodes = (|pair: Pair<'a, Rule>| -> Option<Value<'a>> {
34        Some(pair_to_value(
35            pair.clone()
36                .into_inner()
37                .next()?
38                .into_inner()
39                .next()?,
40        ))
41    })(file)
42    .unwrap_or_default();
43    Ok(nodes)
44}
45
46pub fn map_pairs_to_list<'a>(pairs: Pairs<'a, Rule>) -> Value<'a> {
47    pairs.map(|pair| pair_to_value(pair)).collect()
48}
49pub fn pair_to_value<'a>(pair: Pair<'a, Rule>) -> Value<'a> {
50    match pair.as_rule() {
51        Rule::float =>
52            Value::float(f64::from_str(pair.as_span().as_str()).expect("float")),
53        Rule::integer =>
54            Value::integer(i64::from_str(pair.as_span().as_str()).expect("integer")),
55        Rule::string => Value::string(Cow::from(pair.as_span().as_str())),
56        Rule::symbol => Value::symbol(Cow::from(pair.as_span().as_str())),
57        Rule::quoted_symbol => {
58            let mut pairs = pair.clone().into_inner();
59            pairs.next().expect("quote");
60            let symbol = pairs.next().expect("symbol");
61            Value::quoted_symbol(symbol.as_span().as_str())
62        },
63        Rule::t => Value::T,
64        Rule::unsigned => Value::unsigned_integer(
65            u32::from_str(pair.as_span().as_str()).expect("unsigned integer"),
66        ),
67        Rule::value => pair_to_value(pair.clone().into_inner().next().expect("value")),
68        Rule::sexpr => {
69            let mut items = Cell::nil();
70            let mut pairs = pair.clone().into_inner();
71            let mut quoted = false;
72            loop {
73                if let Some(pair) = pairs.peek() {
74                    if pair.as_rule() == Rule::close_paren {
75                        break;
76                    }
77                }
78                let pair = pairs.next().expect("quote, open_paren or item");
79                match pair.as_rule() {
80                    Rule::quote => {
81                        quoted = true;
82                    },
83                    Rule::open_paren => continue,
84                    Rule::close_paren => continue,
85                    _ => {
86                        items.push_value(pair_to_value(pair));
87                        continue;
88                    },
89                }
90            }
91            pairs.next().expect("close_paren");
92            let value = Value::from_iter(items.into_iter());
93            if quoted {
94                value.quote()
95            } else {
96                value
97            }
98        },
99        Rule::nil => Value::nil(),
100        _ => unexpected!(pair),
101    }
102}