///|
pub fn NQuadsState::to_str(self : NQuadsState) -> String {
Show::to_string(self)
}
///|
pub impl GenMachine for NQuadsRecognizer with fn initial_state(
_self : NQuadsRecognizer,
) -> RdfState {
RdfState::NQuadsState(NQuadsState::ExpectSubject)
}
///|
pub impl GenMachine for NQuadsRecognizer with fn error_recovery_statemachine(
self,
) -> NQuadsRecognizer {
self.error_recovery_state()
}
///|
pub impl GenMachine for NQuadsRecognizer with fn current_state(self) -> RdfState {
StateWrapper::as_state_enum(self.current_state)
}
///|
pub impl GenMachine for NQuadsRecognizer with fn reset(self) -> NQuadsRecognizer {
self.error_recovery_state()
}
///|
pub impl GenMachine for NQuadsRecognizer with fn transition(
self : NQuadsRecognizer,
state : RdfState,
event : Event,
_context : Ctx,
) -> TransitionResult[NQuadsRecognizer, RdfState, DataAction] {
let nquads_state = match state {
RdfState::NQuadsState(s) => s
}
let token = event
self.debug_logger.info("NQuads State: \{nquads_state}, Event: \{token}")
let token_name = match token.0 {
N3Token::Punctuation(p) => "Punctuation('\{p}')"
N3Token::PlainKeyword(k) => "PlainKeyword('\{k}')"
N3Token::Iri(i) => "Iri('\{i}')"
N3Token::LongString(s) => "LongString('\{s}')"
_ => "Other"
}
self.debug_logger.info("[DEBUG] ExpectDotOrGraphName token: \{token_name}")
let (next_state, action) = match (nquads_state, token) {
// ── Start / ExpectSubject ─────────────────────────────────
(Start, LocatedToken(N3Token::Iri(iri), _)) => {
self.debug_logger.info("[Start] IRI: \{iri}")
let node = NamedNodeRef::new_unchecked(iri).as_enum()
(ExpectPredicate, DataAction::AddSubject(node))
}
(Start, LocatedToken(N3Token::BlankNodeLabel(l), _)) => {
self.debug_logger.info("[Start] Blank: _:\{l}")
let node = BlankNodeRef::new_unchecked(l).as_enum()
(ExpectPredicate, DataAction::AddSubject(node))
}
(Start, LocatedToken(N3Token::LineJump | N3Token::End, _)) => {
self.debug_logger.info("[Start] LineJump/End")
(Start, DataAction::NoOp)
}
// ── ExpectSubject ─────────────────────────────────────────
(ExpectSubject, LocatedToken(N3Token::Iri(iri), _)) => {
self.debug_logger.info("[ExpectSubject] IRI: \{iri}")
let node = NamedNodeRef::new_unchecked(iri).as_enum()
(ExpectPredicate, DataAction::AddSubject(node))
}
(ExpectSubject, LocatedToken(N3Token::BlankNodeLabel(l), _)) => {
self.debug_logger.info("[ExpectSubject] Blank: \{l}")
let node = BlankNodeRef::new_unchecked(l).as_enum()
(ExpectPredicate, DataAction::AddSubject(node))
}
(ExpectSubject, LocatedToken(N3Token::LineJump | N3Token::End, _)) =>
(ExpectSubject, DataAction::NoOp)
// ── ExpectPredicate ────────────────────────────────────────
(ExpectPredicate, LocatedToken(N3Token::Iri(iri), _)) => {
self.debug_logger.info("[ExpectPredicate] IRI: \{iri}")
let pred = NamedNodeRef::new_unchecked(iri)
(ExpectObject, DataAction::AddPredicate(pred))
}
// ── ExpectObject ───────────────────────────────────────────
(ExpectObject, LocatedToken(N3Token::Iri(iri), _)) => {
self.debug_logger.info("[ExpectObject] IRI: \{iri}")
let obj = TermRef::NamedNodeRef(NamedNodeRef::new_unchecked(iri))
(ExpectDotOrGraphName, DataAction::AddObject(obj))
}
(ExpectObject, LocatedToken(N3Token::BlankNodeLabel(l), _)) => {
self.debug_logger.info("[ExpectObject] Blank: \{l}")
let obj = BlankNodeRef::new_unchecked(l).as_term()
(ExpectDotOrGraphName, DataAction::AddObject(obj))
}
(ExpectObject, LocatedToken(N3Token::String(v), _)) => {
self.debug_logger.info("[ExpectObject] STRING: '\{v}'")
(ExpectLiteralSuffix, DataAction::SetTempLiteral(v))
}
// ★ 添加 LongString 处理
(ExpectObject, LocatedToken(N3Token::LongString(v), _)) => {
self.debug_logger.info("[ExpectObject] LONGSTRING: '\{v}'")
(ExpectLiteralSuffix, DataAction::SetTempLiteral(v))
}
(ExpectObject, LocatedToken(N3Token::PlainKeyword(k), range)) if k.length() >
0 &&
k[0] == '"' => {
self.debug_logger.error("Invalid token: \{k}")
return Err(RuleRecognizerError::SyntaxError("Expected string", range))
}
(ExpectObject, LocatedToken(N3Token::PlainKeyword(k), range)) => {
let quote_count = {
let mut count = 0
for c in k {
if c == '"' {
count += 1
}
}
count
}
if quote_count % 2 != 0 {
self.debug_logger.error("Unmatched quote: \{k}")
return Err(RuleRecognizerError::SyntaxError("Unmatched quote", range))
}
return Err(RuleRecognizerError::SyntaxError("Unexpected string", range))
}
// ── ExpectLiteralSuffix ────────────────────────────────────
(
ExpectLiteralSuffix,
// | LocatedToken(N3Token::PlainKeyword("."), _),
LocatedToken(N3Token::Punctuation("."), _),
) => {
self.debug_logger.info("[ExpectLiteralSuffix] DOT, finalize=Simple")
(ExpectLineJump, DataAction::EmitQuadWithLiteral(LiteralKind::Simple))
}
(
ExpectLiteralSuffix,
LocatedToken(N3Token::LangTag(language~, direction~), _),
) => {
let dir = direction.unwrap_or(BaseDirection::Ltr)
let tag = match LanguageTag::parse(language) {
Ok(tag) => tag
Err(_) =>
return Err(
RuleRecognizerError::SyntaxError(
"Invalid language tag",
self.last_range,
),
)
}
(
ExpectDotOrGraphName,
DataAction::EmitQuadWithLiteral(LiteralKind::Lang(tag, dir)),
)
}
(ExpectLiteralSuffix, LocatedToken(N3Token::Punctuation("^^"), _)) =>
(ExpectDatatype, DataAction::NoOp)
(ExpectDatatype, LocatedToken(N3Token::Iri(iri), _)) => {
self.debug_logger.info("[ExpectDatatype] IRI: \{iri}")
let datatype_node = NamedNodeRef::new_unchecked(iri)
(ExpectDotOrGraphName, DataAction::EmitQuadWithTempLiteral(datatype_node))
}
// ── ExpectDotOrGraphName ───────────────────────────────────
(
ExpectDotOrGraphName,
LocatedToken(N3Token::Punctuation("."), _)
| LocatedToken(N3Token::PlainKeyword("."), _),
) =>
match self.temp_literal {
Some(_) => (ExpectLiteralSuffix, DataAction::NoOp)
None => (ExpectLineJump, DataAction::EmitQuad)
}
(ExpectDotOrGraphName, LocatedToken(N3Token::Iri(iri), _)) => {
self.debug_logger.info("[ExpectDotOrGraphName] GraphName IRI: \{iri}")
let gn = GraphNameRef::new_unchecked(iri)
(ExpectDot, DataAction::SetGraphName(gn))
}
(ExpectDotOrGraphName, LocatedToken(N3Token::BlankNodeLabel(l), _)) => {
self.debug_logger.info("[ExpectDotOrGraphName] GraphName Blank: _:\{l}")
let gn = GraphNameRef::new_unchecked(l)
(ExpectDot, DataAction::SetGraphName(gn))
}
// 添加转换
(ExpectDotOrGraphName, LocatedToken(N3Token::LineJump, _)) => {
self.debug_logger.info("[ExpectDotOrGraphName] LineJump")
(ExpectDotOrGraphName, DataAction::NoOp) // 跳过换行
}
// ── ExpectDot ──────────────────────────────────────────────
(
ExpectDot,
LocatedToken(N3Token::Punctuation(".") | N3Token::PlainKeyword("."), _),
) => {
self.debug_logger.info("[ExpectDot] DOT")
(ExpectLineJump, DataAction::EmitQuad)
}
// ── ExpectLineJump ─────────────────────────────────────────
(ExpectLineJump, LocatedToken(N3Token::LineJump, _)) => {
self.debug_logger.info("[ExpectLineJump] LineJump")
(ExpectSubject, DataAction::ClearAccumulator)
}
(ExpectLineJump, LocatedToken(N3Token::End, _)) => {
self.debug_logger.info("[ExpectLineJump] End")
(ExpectSubject, DataAction::ClearAccumulator)
}
// ── Error fallback ─────────────────────────────────────────
_ => {
let err = RuleRecognizerError::SyntaxError(
"Unexpected token in state '\{nquads_state}': \{token.0}",
token.1,
)
self.debug_logger.error("\{err}")
return Ok(
(
self.add_error(err),
StateWrapper::as_state_enum(nquads_state),
DataAction::NoOp,
),
)
}
}
self.debug_logger.info(
"[TRANSITION] \{nquads_state} + \{token.0} -> \{next_state}",
)
Ok(
(
self.set_current_state(next_state),
StateWrapper::as_state_enum(next_state),
action,
),
)
}
///|
pub impl GenMachine for NQuadsRecognizer with fn is_accepting(
self : NQuadsRecognizer,
) -> Bool {
match self.current_state() {
RdfState::NQuadsState(NQuadsState::ExpectSubject) => true
RdfState::NQuadsState(NQuadsState::ExpectLineJump) => true
_ => false // self.stack.is_empty()
}
}
///|
pub impl GenMachine for NQuadsRecognizer with fn context(
_self : NQuadsRecognizer,
) -> RdfContext {
RdfContext::NQuadsRecognizerContext({
lexer_options: LexerOptions::{ base_iri: None },
with_graph_name: false,
})
}
///|
pub impl GenMachine for NQuadsRecognizer with fn[ST : StateWrapper] set_current_state(
self : NQuadsRecognizer,
state : ST,
) -> NQuadsRecognizer {
let state = ST::as_state_enum(state)
match state {
RdfState::NQuadsState(s) => { ..self, current_state: s }
}
}
///|
pub impl GenMachine for NQuadsRecognizer with fn accumulate(
self : NQuadsRecognizer,
data_world : DataWorld,
action : DataAction,
) -> (NQuadsRecognizer, DataWorld) {
let dw = data_world
let m = self
self.debug_logger.info("[ACCUMULATE] \{action}")
match action {
DataAction::NoOp => return (m, dw)
DataAction::AddSubject(s) => dw.subjects.push(s)
DataAction::AddPredicate(p) => dw.predicates.push(p)
DataAction::AddObject(o) => dw.objects.push(o)
DataAction::SetTempLiteral(s) => {
self.debug_logger.info("[ACCUMULATE] SetTempLiteral: \{s}")
dw.temp_literal = Some(s)
}
DataAction::SetGraphName(gn) => dw.graph_name = Some(gn)
DataAction::EmitQuad => m.emit_quad = true
DataAction::EmitQuadWithLiteral(kind) => {
let lit = match kind {
LiteralKind::Simple =>
LiteralRef::new_simple_literal(dw.temp_literal.unwrap_or(""))
LiteralKind::Lang(lang, dir) =>
LiteralRef::new_directional_language_tagged_literal_unchecked(
dw.temp_literal.unwrap_or(""),
lang,
dir,
)
LiteralKind::Typed(value, iri) =>
LiteralRef::new_typed_literal(value, iri)
}
dw.objects.push(lit.as_term())
m.emit_quad = true
}
// accumulate 中
DataAction::EmitQuadWithTempLiteral(datatype_node) => {
let temp = dw.temp_literal.unwrap_or("")
let lit = LiteralRef::new_typed_literal(temp, datatype_node)
dw.objects.push(lit.as_term())
m.emit_quad = true
}
DataAction::PushStack(state) => m.stack.push(state)
DataAction::ClearAccumulator => {
dw.subjects.clear()
dw.predicates.clear()
dw.objects.clear()
dw.temp_literal = None
dw.graph_name = None
}
DataAction::FinalizeLiteral(kind) => {
let lit = match kind {
LiteralKind::Simple =>
LiteralRef::new_simple_literal(dw.temp_literal.unwrap_or(""))
LiteralKind::Lang(lang, dir) =>
LiteralRef::new_directional_language_tagged_literal_unchecked(
dw.temp_literal.unwrap_or(""),
lang,
dir,
)
LiteralKind::Typed(value, iri) =>
LiteralRef::new_typed_literal(value, iri)
}
dw.objects.push(lit.as_term())
// m.finalize_literal = Some(kind)
}
DataAction::FinalizeQuotedTriple =>
match (dw.subjects.pop(), dw.predicates.pop(), dw.objects.pop()) {
(Some(s), Some(p), Some(o)) =>
dw.objects.push(
TermRef::TripleRef(TripleRef::{
subject: s,
predicate: p,
object: o,
}),
)
_ => m.errors.push(RuleRecognizerError::TripleMissingDot)
}
}
(m, dw)
}
///|
pub impl GenMachine for NQuadsRecognizer with fn get_and_clear_output(
self : NQuadsRecognizer,
data_world : DataWorld,
) -> (NQuadsRecognizer, RdfOut?) {
let m = self
let dw = data_world
let output = if m.emit_quad {
self.pop_quad_from_data_world(dw)
} else {
None
}
// emit_quad 成功后,从数组末尾删除
if output is Some(_) {
let _ = dw.subjects.pop()
let _ = dw.predicates.pop()
let _ = dw.objects.pop()
}
// 清除标志
m.emit_quad = false
// m.finalize_literal = None
(m, output)
}
///|
fn NQuadsRecognizer::pop_quad_from_data_world(
_self : NQuadsRecognizer,
dw : DataWorld,
) -> RdfOut? {
let subject = dw.subjects.pop()
let predicate = dw.predicates.pop()
let object = dw.objects.pop()
match (subject, predicate, object) {
(Some(s), Some(p), Some(o)) => {
let graph_name = dw.graph_name.unwrap_or(GraphNameRef::DefaultGraph)
Some(
RdfOut::Quad(
Quad::Quad(
s.into_owned(),
p.into_owned(),
o.into_owned(),
graph_name.into_owned(),
),
),
)
}
_ => None
}
}
///|
fn NQuadsRecognizer::add_error(
self : NQuadsRecognizer,
err : RuleRecognizerError,
) -> NQuadsRecognizer {
let new_errors = self.errors
new_errors.push(err)
{ ..self, errors: new_errors }
}