mod define;
mod error;
mod node;
mod report;
mod token;
use std::path::PathBuf;
pub use define::*;
pub use error::*;
pub use node::*;
use pyo3::prelude::*;
pub use report::*;
use scarf_parser::{LexedSource, PreprocessorCache};
pub use token::*;
#[pymodule]
pub mod scarf_python {
#[pymodule_export]
pub use super::lex;
#[pymodule_export]
pub use super::{
Bytes, Expectation, Node, NodeIterator, Report, ReportKind, Span,
SpannedToken, Token, VerboseError,
};
#[pymodule_export]
pub use super::{Define, define_empty, define_text};
#[pymodule_export]
pub use super::{ParserResult, parse, parse_from_preprocess};
#[pymodule_export]
pub use super::{
PreprocessorError, PreprocessorResult, preprocess, preprocess_from_lex,
};
}
#[pyfunction]
pub fn lex(src: String, file_name: String) -> Vec<SpannedToken> {
scarf_parser::lex(&src, &file_name)
.tokens()
.map(|rust_spanned_token| rust_spanned_token.into())
.collect()
}
#[pyclass(eq, from_py_object, module = "scarf_python")]
#[derive(Clone, PartialEq, Eq)]
pub enum PreprocessorResult {
Ok { tokens: Vec<SpannedToken> },
Err { errors: Vec<PreprocessorError> },
}
#[pyfunction]
pub fn preprocess_from_lex(
tokens: Vec<SpannedToken>,
include_paths: Vec<PathBuf>,
defines: Vec<crate::Define>,
) -> PreprocessorResult {
let cache = PreprocessorCache::new();
let rust_tokens = tokens
.iter()
.map(|python_token| python_token.to_rust(&cache));
let mut state = scarf_parser::PreprocessorState::new(
include_paths
.iter()
.map(|pathbuf| pathbuf.as_path())
.collect(),
defines
.iter()
.map(|python_define| python_define.to_rust(&cache))
.collect(),
);
match scarf_parser::preprocess(rust_tokens, &mut state, &cache) {
Ok(tokens) => PreprocessorResult::Ok {
tokens: tokens
.into_iter()
.map(|rust_token| rust_token.into())
.collect(),
},
Err(()) => PreprocessorResult::Err {
errors: state.errors.into_iter().map(|err| err.into()).collect(),
},
}
}
#[pyfunction]
pub fn preprocess(
src: String,
file_name: String,
include_paths: Vec<PathBuf>,
defines: Vec<crate::Define>,
) -> PreprocessorResult {
let cache = PreprocessorCache::new();
let tokens = scarf_parser::lex(&src, &file_name).tokens();
let mut state = scarf_parser::PreprocessorState::new(
include_paths
.iter()
.map(|pathbuf| pathbuf.as_path())
.collect(),
defines
.iter()
.map(|python_define| python_define.to_rust(&cache))
.collect(),
);
match scarf_parser::preprocess(tokens, &mut state, &cache) {
Ok(tokens) => PreprocessorResult::Ok {
tokens: tokens
.into_iter()
.map(|rust_token| rust_token.into())
.collect(),
},
Err(()) => PreprocessorResult::Err {
errors: state.errors.into_iter().map(|err| err.into()).collect(),
},
}
}
#[pyclass(eq, from_py_object, module = "scarf_python")]
#[derive(Clone, PartialEq, Eq)]
pub enum ParserResult {
Ok { root: Node },
ParserErr { error: VerboseError },
PreprocessorErr { errors: Vec<PreprocessorError> },
}
#[pyfunction]
pub fn parse_from_preprocess(tokens: Vec<SpannedToken>) -> ParserResult {
let cache = PreprocessorCache::new();
let rust_tokens = tokens
.iter()
.map(|python_token| python_token.to_rust(&cache))
.collect::<Vec<_>>();
match scarf_parser::parse(&rust_tokens) {
Ok(result) => {
let node: scarf_syntax::Node<'_, '_> = (&result).into();
ParserResult::Ok { root: node.into() }
}
Err(err) => ParserResult::ParserErr { error: err.into() },
}
}
#[pyfunction]
pub fn parse(
src: String,
file_name: String,
include_paths: Vec<PathBuf>,
defines: Vec<crate::Define>,
) -> ParserResult {
let cache = PreprocessorCache::new();
let tokens = scarf_parser::lex(&src, &file_name).tokens();
let mut state = scarf_parser::PreprocessorState::new(
include_paths
.iter()
.map(|pathbuf| pathbuf.as_path())
.collect(),
defines
.iter()
.map(|python_define| python_define.to_rust(&cache))
.collect(),
);
let tokens = match scarf_parser::preprocess(tokens, &mut state, &cache) {
Ok(tokens) => tokens,
Err(()) => {
return ParserResult::PreprocessorErr {
errors: state
.errors
.into_iter()
.map(|err| err.into())
.collect(),
};
}
};
match scarf_parser::parse(&tokens) {
Ok(result) => {
let node: scarf_syntax::Node<'_, '_> = (&result).into();
ParserResult::Ok { root: node.into() }
}
Err(err) => ParserResult::ParserErr { error: err.into() },
}
}