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}