use pyo3::exceptions::PyException;
use pyo3::prelude::*;
use crate::error::RableError;
pyo3::create_exception!(
rable,
ParseError,
PyException,
"Syntax error during parsing."
);
pyo3::create_exception!(
rable,
MatchedPairError,
PyException,
"Unmatched delimiter (parenthesis, brace, bracket, quote)."
);
#[pyclass(name = "ParsedNode")]
struct ParsedNode {
sexp: String,
}
#[pymethods]
impl ParsedNode {
fn to_sexp(&self) -> &str {
&self.sexp
}
fn __repr__(&self) -> String {
format!("ParsedNode({})", self.sexp)
}
fn __str__(&self) -> &str {
self.to_sexp()
}
}
#[pyfunction]
#[pyo3(signature = (source, extglob = false))]
fn parse(source: &str, extglob: bool) -> PyResult<Vec<ParsedNode>> {
let nodes = crate::parse(source, extglob).map_err(|e| match e {
RableError::Parse { .. } => PyErr::new::<ParseError, _>(e.to_string()),
RableError::MatchedPair { .. } => PyErr::new::<MatchedPairError, _>(e.to_string()),
})?;
Ok(nodes
.into_iter()
.map(|node| ParsedNode {
sexp: node.to_string(),
})
.collect())
}
#[pymodule]
fn rable(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_function(wrap_pyfunction!(parse, m)?)?;
m.add_class::<ParsedNode>()?;
m.add("ParseError", m.py().get_type::<ParseError>())?;
m.add("MatchedPairError", m.py().get_type::<MatchedPairError>())?;
Ok(())
}