// ===== State: ExpectSubject =====
///|
fn NQuadsRecognizer::handle_expect_subject_m(
self : NQuadsRecognizer,
token : LocatedTokenOrLineJump,
_ctx : NQuadsRecognizerContext,
) -> TransitionResult[NQuadsRecognizer, NQuadsState, RdfOut] {
self.debug_logger.info(
"ExpectSubject with token: \{token} Token stack: \{@debug.to_string(self.stack)}",
)
match token {
LocatedTokenOrLineJump::End => Ok((self, NQuadsState::ExpectSubject, None))
LocatedTokenOrLineJump::LocatedN3Token(LocatedN3Token(N3Token::Iri(s), _)) => {
let new_self = self
new_self.subjects.push(NamedNodeRef::new_unchecked(s).as_enum())
// 状态转换为 ExpectPredicate,无语句产生
Ok((new_self, NQuadsState::ExpectPredicate, None))
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::BlankNodeLabel(s), _)
) => {
let new_self = self
new_self.subjects.push(BlankNodeRef::new_unchecked(s).as_enum())
Ok((new_self, NQuadsState::ExpectPredicate, None))
}
_ => Err(RuleRecognizerError::BlankNodeOrIriError)
}
}
// ===== State: ExpectPredicate =====
///|
fn NQuadsRecognizer::handle_expect_predicate_m(
self : NQuadsRecognizer,
token : LocatedTokenOrLineJump,
_ctx : NQuadsRecognizerContext,
) -> TransitionResult[NQuadsRecognizer, NQuadsState, RdfOut] {
self.debug_logger.info("Entering ExpectPredicate with token: \{token}")
self.debug_logger.info("Token stack: \{@debug.to_string(self.stack)}")
match token {
LocatedTokenOrLineJump::LocatedN3Token(LocatedN3Token(N3Token::Iri(p), _)) => {
let new_self = self
new_self.predicates.push(NamedNodeRef::new_unchecked(p))
Ok((new_self, NQuadsState::ExpectedObject, None))
}
_ => Err(RuleRecognizerError::PredicateNotAnIRI)
}
}
// ===== State: ExpectedObject =====
///|
fn NQuadsRecognizer::handle_expected_object_m(
self : NQuadsRecognizer,
token : LocatedTokenOrLineJump,
ctx : NQuadsRecognizerContext,
) -> TransitionResult[NQuadsRecognizer, NQuadsState, RdfOut] {
self.debug_logger.info(
" ExpectedObject: \{token} Token stack: \{@debug.to_string(self.stack)}",
)
match token {
LocatedTokenOrLineJump::LocatedN3Token(LocatedN3Token(N3Token::Iri(o), _)) => {
let new_self = self
new_self.objects.push(
TermRef::NamedNodeRef(NamedNodeRef::new_unchecked(o)),
)
if ctx.with_graph_name {
Ok(
(new_self, NQuadsState::ExpectPossibleGraphOrEndOfQuotedTriple, None),
)
} else {
// N-Triples 直接进入 ExpectDot
Ok((new_self, NQuadsState::ExpectDot, None))
}
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::BlankNodeLabel(o), _)
) => {
let new_self = self
new_self.objects.push(NamedNodeRef::new_unchecked(o).as_term())
Ok((new_self, NQuadsState::ExpectPossibleGraphOrEndOfQuotedTriple, None))
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::String(value), _)
) => {
let new_self = self
// new_self.temp_literal_value = Some(value)
Ok(
(
new_self,
NQuadsState::ExpectLiteralAnnotationOrGraphNameOrDot(value~),
None,
),
)
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("<<("), _)
) => {
let new_self = self
new_self.stack.push(NQuadsState::AfterQuotedTriple)
new_self.stack.push(NQuadsState::ExpectSubject)
Ok((new_self, NQuadsState::ExpectSubject, None)) // 立即进入子解析
}
_ => Err(RuleRecognizerError::BlankNodeOrIriError)
}
}
// ===== State: ExpectLiteralAnnotationOrGraphNameOrDot =====
///|
fn NQuadsRecognizer::handle_expect_literal_annotation_or_graph_name_or_dot_m(
self : NQuadsRecognizer,
token : LocatedTokenOrLineJump,
_ctx : NQuadsRecognizerContext,
value : String,
) -> TransitionResult[NQuadsRecognizer, NQuadsState, RdfOut] {
// self.debug_logger.info("Entering ExpectLiteralAnnotation... value: \{value}")
self.debug_logger.info("Token stack: \{@debug.to_string(self.stack)}")
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::LangTag(language~, direction~), _)
) if direction is Some(_) => {
let dir = match direction {
Some(d) => d
None => BaseDirection::Ltr
}
let lang_tag = LanguageTag::from_str(language.to_lower()) catch {
_e => return Err(RuleRecognizerError::InvalidLanguageTag) // 简化错误处理
}
match lang_tag {
lang_tag => {
let new_self = self
let literal = LiteralRef::new_directional_language_tagged_literal_unchecked(
value, lang_tag, dir,
).as_term()
new_self.objects.push(literal)
// new_self.temp_literal_value = None // 清除临时值
Ok(
(
new_self,
NQuadsState::ExpectPossibleGraphOrEndOfQuotedTriple,
None,
),
)
}
}
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::LangTag(language~, direction~), _)
) if direction is None => {
let lang_tag = LanguageTag::from_str(language.to_lower()) catch {
_e => return Err(RuleRecognizerError::InvalidLanguageTag)
}
match lang_tag {
lang_tag => {
let new_self = self
let literal = TermRef::LiteralRef(
Literal::new_language_tagged_literal_unchecked(
value,
lang_tag.to_string(),
).as_ref(),
)
new_self.objects.push(literal)
// new_self.temp_literal_value = None
Ok(
(
new_self,
NQuadsState::ExpectPossibleGraphOrEndOfQuotedTriple,
None,
),
)
}
// Err(_e) => Err(RuleRecognizerError::InvalidLanguageTag)
}
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("^^"), _)
) => {
let new_self = self
// new_self.temp_literal_value = Some(value) // 传递给 datatype 状态
Ok((new_self, NQuadsState::ExpectLiteralDatatype(value~), None))
}
_ =>
// 检查是否是句点
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("."), _)
) => {
let new_self = self
let literal = TermRef::LiteralRef(
LiteralRef::new_simple_literal(value),
)
new_self.objects.push(literal)
let stmt = new_self.make_current_quad()
let _ = new_self.error_recovery_state()
Ok((new_self, NQuadsState::ExpectLineJump, stmt))
}
_ => {
let new_self = self
let literal = TermRef::LiteralRef(
LiteralRef::new_simple_literal(value),
)
new_self.objects.push(literal)
Ok(
(
new_self,
NQuadsState::ExpectPossibleGraphOrEndOfQuotedTriple,
None,
),
)
}
}
}
// _ => {
// let new_self = self
// let literal = TermRef::LiteralRef(LiteralRef::new_simple_literal(value))
// new_self.objects.push(literal)
// // new_self.temp_literal_value = None
// Ok((new_self, NQuadsState::ExpectPossibleGraphOrEndOfQuotedTriple, None))
// }
}
// ===== State: ExpectLiteralDatatype =====
///|
pub fn NQuadsRecognizer::handle_expect_literal_datatype_m(
self : NQuadsRecognizer,
token : LocatedTokenOrLineJump,
_ctx : NQuadsRecognizerContext,
value : String,
) -> TransitionResult[NQuadsRecognizer, NQuadsState, RdfOut] {
// let value = match self.temp_literal_value {
// Some(v) => v
// None => return Err(RuleRecognizerError::SyntaxError("Missing literal value for datatype", Range::default()))
// }
self.debug_logger.info("Entering ExpectLiteralDatatype with value: \{value}")
self.debug_logger.info("Token stack: \{@debug.to_string(self.stack)}")
match token {
LocatedTokenOrLineJump::LocatedN3Token(LocatedN3Token(N3Token::Iri(d), _)) => {
if !self.lenient && d == lwLANG_STRING.to_string() {
return Err(
RuleRecognizerError::SyntaxError(
"The datatype of a literal without a language tag must not be rdf:langString",
Range::default(),
),
)
}
if !self.lenient && d == lwDIR_LANG_STRING.to_string() {
return Err(
RuleRecognizerError::SyntaxError(
"The datatype of a literal without a base direction must not be rdf:dirLangString",
Range::default(),
),
)
}
let d_ref = NamedNodeRef::new_unchecked(d)
let data_value = d_ref.into_datatype(value)
let new_self = self
let literal = TermRef::LiteralRef(
LiteralRef::new_typed_literal(data_value, d_ref),
)
new_self.objects.push(literal)
// new_self.temp_literal_value = None
Ok((new_self, NQuadsState::ExpectPossibleGraphOrEndOfQuotedTriple, None))
}
_ => Err(RuleRecognizerError::LiteralDatatypeError)
}
}
// ===== State: ExpectPossibleGraphOrEndOfQuotedTriple =====
///|
pub fn NQuadsRecognizer::handle_expect_possible_graph_or_end_of_quoted_triple_m(
self : NQuadsRecognizer,
token : LocatedTokenOrLineJump,
ctx : NQuadsRecognizerContext,
) -> TransitionResult[NQuadsRecognizer, NQuadsState, RdfOut] {
self.debug_logger.info(
"ExpectPossibleGraphOrEndOfQuotedTriple Token stack: \{@debug.to_string(self.stack)}",
)
// 首先检查是否是图名 IRI(无论是顶层还是嵌套在引用的三元组中)
if ctx.with_graph_name {
match token {
LocatedTokenOrLineJump::LocatedN3Token(LocatedN3Token(N3Token::Iri(g), _)) => {
let stmt = self.make_current_quad(
graph_name=GraphNameRef::new_unchecked(g).into_owned(),
)
let new_self = self
let _ = new_self.error_recovery_state()
return Ok((new_self, NQuadsState::ExpectDot, stmt))
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::BlankNodeLabel(_g), _)
) => {
let stmt = self.make_current_quad()
let new_self = self
let _ = new_self.error_recovery_state()
return Ok((new_self, NQuadsState::ExpectDot, stmt))
}
_ => ()
}
}
// 检查是否是句点(默认图结束)
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("."), _)
) => {
let stmt = self.make_current_quad()
let new_self = self
let _ = new_self.error_recovery_state()
return Ok((new_self, NQuadsState::ExpectLineJump, stmt))
}
_ => ()
}
// 检查是否是引用的三元组结束
if !self.stack.is_empty() {
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation(")>>"), _)
) =>
// 结束引用三元组,返回当前解析器状态,不产生顶层语句
return Ok((self, NQuadsState::AfterQuotedTriple, None))
_ => ()
}
// 如果在栈中且不是结束符,可能是错误
return Err(
RuleRecognizerError::SyntaxError(
"Expecting the end of a quoted triple ')>>'",
Range::default(),
),
)
}
// 栈为空且没有特殊 token,返回 ExpectSubject 并输出 quad
let stmt = self.make_current_quad()
let new_self = self
let _ = new_self.error_recovery_state()
Ok((new_self, NQuadsState::ExpectSubject, stmt))
}
// ===== State: ExpectDot =====
///|
fn NQuadsRecognizer::handle_expect_dot_m(
self : NQuadsRecognizer,
token : LocatedTokenOrLineJump,
_ctx : NQuadsRecognizerContext,
) -> TransitionResult[NQuadsRecognizer, NQuadsState, RdfOut] {
self.debug_logger.info(
"ExpectDot with token: \{token} Token stack: \{@debug.to_string(self.stack)}",
)
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("."), _)
) => {
let stmt = self.make_current_quad()
Ok((self, NQuadsState::ExpectLineJump, stmt))
}
LocatedTokenOrLineJump::LocatedN3Token(t) =>
Err(
RuleRecognizerError::SyntaxError("Quads must be followed by a dot", t.1),
)
_ =>
Err(RuleRecognizerError::SyntaxError("Expecting a dot", Range::default()))
}
}
// ===== State: ExpectLineJump =====
///|
pub fn NQuadsRecognizer::handle_expect_line_jump_m(
self : NQuadsRecognizer,
token : LocatedTokenOrLineJump,
_ctx : NQuadsRecognizerContext,
) -> TransitionResult[NQuadsRecognizer, NQuadsState, RdfOut] {
self.debug_logger.info("Entering ExpectLineJump with token: \{token}")
let tok = match token {
LocatedTokenOrLineJump::LineJump(n) => "LineJump(\{n})"
LocatedTokenOrLineJump::End => "End"
LocatedTokenOrLineJump::LocatedN3Token(t) => "N3Token: \{t.0}"
}
self.debug_logger.info("Token type: \{tok}")
match token {
LocatedTokenOrLineJump::LineJump(_) =>
// 成功:换行后回到 ExpectSubject 开始下一个语句
Ok((self, NQuadsState::ExpectSubject, None))
LocatedTokenOrLineJump::End =>
// 文件结束,安静地接受
Ok((self, NQuadsState::ExpectSubject, None))
_ =>
// 换行符之后不应该有其他内容
// 跳过并继续等待换行(lenient 模式)
if self.lenient {
Ok((self, NQuadsState::ExpectLineJump, None))
} else {
Err(
RuleRecognizerError::SyntaxError(
"Only a single triple or quad can be written in a line",
Range::default(),
),
)
}
}
}
// ===== State: AfterQuotedTriple =====
///|
pub fn NQuadsRecognizer::handle_after_quoted_triple_m(
self : NQuadsRecognizer,
token : LocatedTokenOrLineJump,
_ctx : NQuadsRecognizerContext,
) -> TransitionResult[NQuadsRecognizer, NQuadsState, RdfOut] {
self.debug_logger.info("Entering AfterQuotedTriple with token: \{token}")
self.debug_logger.info("Token stack: \{@debug.to_string(self.stack)}")
let subject_opt = self.subjects.pop()
let predicate_opt = self.predicates.pop()
let object_opt = self.objects.pop()
match (subject_opt, predicate_opt, object_opt) {
(Some(subject), Some(predicate), Some(object)) => {
let triple : TripleRef = { subject, predicate, object }
let new_self = self
// 将引用的三元组作为对象推入外层对象的栈
new_self.objects.push(TermRef::TripleRef(triple))
// 弹出 AfterQuotedTriple 状态,回到之前的状态
// 原逻辑: self.stack.push(NQuadsState::ExpectPossibleGraphOrEndOfQuotedTriple)
let prev_state = new_self.stack.pop()
match prev_state {
Some(state) => Ok((new_self, state, None))
None =>
Err(
RuleRecognizerError::SyntaxError(
"Stack underflow after quoted triple",
Range::default(),
),
)
}
}
_ =>
Err(
RuleRecognizerError::SyntaxError(
"Internal error: incomplete quoted triple on stack",
Range::default(),
),
)
}
}
// ===== State: RecoverToLineJump =====
///|
pub fn NQuadsRecognizer::handle_recover_to_line_jump_m(
self : NQuadsRecognizer,
token : LocatedTokenOrLineJump,
_ctx : NQuadsRecognizerContext,
) -> TransitionResult[NQuadsRecognizer, NQuadsState, RdfOut] {
self.debug_logger.info("Entering RecoverToLineJump with token: \{token}")
self.debug_logger.info("Token stack: \{@debug.to_string(self.stack)}")
match token {
LocatedTokenOrLineJump::LineJump(_) =>
// 恢复完成,通常意味着要重新开始或结束
// 返回一个初始状态
Ok((self, NQuadsState::ExpectSubject, None))
_ =>
// 继续等待 LineJump,保持状态
Ok((self, NQuadsState::RecoverToLineJump, None))
}
}