mod diff;
mod stream;
pub use diff::{diff, Change, DiffLine, DiffResult};
pub use stream::{extract, Extracted, Op, Summary};
use oq3_semantics::syntax_to_semantics::{parse_source_string, ParseResult};
use oq3_source_file::SourceString;
pub enum Error {
Qasm2,
Parse(ParseErrors),
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Error::Qasm2 => write!(f, "OpenQASM 2 is not supported"),
Error::Parse(_) => write!(f, "parse or semantic errors"),
}
}
}
impl std::fmt::Debug for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{self}")
}
}
impl std::error::Error for Error {}
pub struct ParseErrors(Box<ParseResult<SourceString>>);
impl ParseErrors {
pub fn print(&self) {
self.0.print_errors();
}
}
pub fn extract_source(source: &str, name: Option<&str>) -> Result<Extracted, Error> {
if is_qasm2(source) {
return Err(Error::Qasm2);
}
let search: Option<&[&str]> = None;
let parsed = parse_source_string(source, name, search);
if parsed.any_errors() {
return Err(Error::Parse(ParseErrors(Box::new(parsed))));
}
Ok(extract(parsed.program(), parsed.symbol_table()))
}
pub fn is_qasm2(source: &str) -> bool {
for line in source.lines() {
let t = line.trim();
if t.is_empty() || t.starts_with("//") {
continue;
}
if let Some(rest) = t.strip_prefix("OPENQASM") {
let version = rest.trim_start().trim_end_matches(';').trim();
return version.starts_with('2');
}
return false;
}
false
}