use crate::runtimes::TranslateError;
use anyhow::Result;
use nar_dev_utils::{if_return, pipe};
use narsese::{
conversion::string::impl_lexical::{format_instances::FORMAT_ASCII, ParseResult},
lexical::Narsese,
};
use navm::{
cmd::Cmd,
output::{Operation, Output},
};
use regex::Regex;
pub fn input_translate(cmd: Cmd) -> Result<String> {
let content = match cmd {
Cmd::NSE(..) => cmd.tail(),
Cmd::CYC(n) => n.to_string(),
Cmd::REM { .. } => String::new(),
Cmd::EXI { .. } => "/q".into(),
_ => return Err(TranslateError::UnsupportedInput(cmd).into()),
};
Ok(content)
}
pub fn output_translate(content_raw: String) -> Result<Output> {
if_return! {
content_raw.contains("Error: Cannot find module") => Ok(Output::TERMINATED { description: content_raw })
}
let line_r = Regex::new(r"\[(\w+)\]\s*(.*)").unwrap();
let head;
let tail;
if let Some(captures) = line_r.captures(&content_raw) {
head = captures[1].to_lowercase();
tail = captures[2].to_owned();
} else {
head = String::new();
tail = content_raw.clone();
}
let output = match head.as_str() {
"answer" => Output::ANSWER {
narsese: segment_narsese(&head, &tail),
content_raw,
},
"in" => Output::IN {
narsese: segment_narsese(&head, &tail),
content: tail,
},
"out" => Output::OUT {
narsese: segment_narsese(&head, &tail),
content_raw: tail,
},
"comment" => Output::COMMENT { content: tail },
"err" | "error" => Output::ERROR { description: tail },
"exe" => Output::EXE {
operation: parse_operation(&tail),
content_raw: tail,
},
_ if !content_raw.contains(char::is_whitespace) => Output::UNCLASSIFIED {
r#type: head,
narsese: match try_segment_narsese(&tail) {
Some(Ok(narsese)) => Some(narsese),
_ => None,
},
content: tail,
},
_ => Output::OTHER {
content: content_raw,
},
};
Ok(output)
}
pub fn parse_operation(content_raw: &str) -> Operation {
#![allow(unused_variables)]
todo!("CXinNARS.js暂不支持NAL-8")
}
fn segment_narsese(head: &str, tail: &str) -> Option<Narsese> {
match try_segment_narsese(tail) {
Some(Ok(narsese)) => Some(narsese),
Some(Err(e)) => {
println!("【{head}】在解析Narsese时出现错误:{e}");
None
}
None => {
println!("【{head}】未匹配到输出中的Narsese块");
None
}
}
}
pub fn try_segment_narsese(input: &str) -> Option<ParseResult> {
let re_narsese = Regex::new(r"Narsese\{\{ (.+) \}\}").unwrap();
pipe!(
re_narsese.captures(input)
=> .map(
|captures| try_parse_narsese(&captures[1])
)
)
}
pub fn try_parse_narsese(narsese: &str) -> ParseResult {
FORMAT_ASCII.parse(narsese)
}