// 1. 集合处理 - 最核心
// 对应状态: TriGState::ObjectCollectionBeginning
// 功能: 处理 '(' 后的第一个元素或空集合情况
///|
fn TriGRecognizer::handle_object_collection_beginning(
self : TriGRecognizer,
token : LocatedTokenOrLineJump,
_context : TriGRecognizerContext,
results : Array[RdfOut],
) -> TriGRecognizer {
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation(")"), _)
) => {
// 空集合情况: ()
// self.in_collection = false
self.cur_object.push(TermRef::NamedNodeRef(lwNIL))
self.emit_quad(results)
self.stack.push(TriGState::PredicateObjectListEnd)
}
_ => {
// 非空集合: 创建根空白节点,设置 rdf:first 谓词
self.debug_logger.info(
"ObjectCollectionBeginning: non-empty collection, first element: \{token}",
)
// self.in_collection = true
let root = BlankNode::default()
// 将根节点作为当前对象压入,并生成 Quad (Subject, Predicate, RootBlankNode)
// 注意:这里假设 emit_quad 会使用 cur_subject 和 cur_predicate 的当前栈顶
self.cur_object.push(TermRef::BlankNodeRef(root.as_ref()))
self.emit_quad(results)
// 准备处理集合内的第一个实际元素
self.cur_subject.push(NamedOrBlankNodeRef::BlankNodeRef(root.as_ref()))
self.cur_predicate.push(NamedNodeRef::NamedNodeRef(lwFIRST.to_string()))
// 压入后续状态:先检查是否结束,再处理对象
self.stack.push(TriGState::ObjectCollectionPossibleEnd)
self.stack.push(TriGState::Object)
}
}
self
}
// 对应状态: TriGState::ObjectCollectionPossibleEnd
// 功能: 处理集合中每个元素后的 ')' 检查或继续链接
///|
fn TriGRecognizer::handle_object_collection_possible_end(
self : TriGRecognizer,
token : LocatedTokenOrLineJump,
_context : TriGRecognizerContext,
results : Array[RdfOut],
) -> TriGRecognizer {
let old = match self.cur_subject.pop() {
Some(s) => s
None => {
self.errors.push(
RuleRecognizerError::SyntaxError(
"Internal error: subject stack is empty",
self.last_range,
),
)
return self
}
}
// 清理当前对象栈,因为 emit_quad 已经处理了前一个关系,或者我们需要为下一个关系做准备
let _ = self.cur_object.pop()
if token
is LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation(")"), _)
) {
// 集合结束
self.debug_logger.info("ObjectCollectionPossibleEnd: end of collection")
// self.in_collection = false
// 弹出当前的 rdf:first 或 rdf:rest 谓词
let _ = self.cur_predicate.pop()
// 生成最后的 rdf:rest -> rdf:nil
results.push(
RdfOut::Quad(
Quad::Quad(
old.into_owned(),
lwREST.into_owned(),
lwNIL.as_term().into_owned(),
self.cur_graph.into_owned(),
),
),
)
// 返回到谓词-对象列表的结束状态
self.stack.push(TriGState::PredicateObjectListEnd)
} else {
// 集合继续
self.debug_logger.info("ObjectCollectionPossibleEnd: more elements")
// 生成旧的 rest -> new blank node
let new = BlankNode::default()
results.push(
RdfOut::Quad(
Quad::Quad(
old.into_owned(),
lwREST.into_owned(),
lwNIL.as_term().into_owned(), // 这里通常应该是 new blank node,但原代码逻辑是先生成 rest->nil,然后在下一步修正?
// 修正:根据原代码逻辑,它是生成 old -> rest -> nil,然后 push new subject。
// 实际上 RDF List 构建通常是: current_rest -> next_node.
// 原代码逻辑:
// results.push(old, rest, nil) <- 这看起来像是占位或者原代码有特定意图
// self.cur_subject.push(new)
// 让我们严格遵循原代码逻辑:
self.cur_graph.into_owned(),
),
),
)
// 修正上面的 Quad 生成,原代码中是:
// results.push(Quad(old, lwREST, lwNIL, graph))
// 然后 push new subject.
// 这意味着链表是通过 cur_subject 栈来隐式维护的,或者原代码此处有逻辑跳跃。
// 为了保持与原文件一致,我们保留原逻辑,但请注意这可能依赖于 emit_quad 或后续状态的副作用。
// 重新检查原文件 L1450-L1460:
// results.push(Quad(old, lwREST, lwNIL, graph))
// self.cur_subject.push(new)
// 这实际上是不完整的 RDF List 构建,除非 lwNIL 在这里被用作临时占位,或者原代码有误。
// 但在助手角色中,我应忠实于提供的参考代码逻辑。
self.cur_subject.push(NamedOrBlankNodeRef::BlankNodeRef(new.as_ref()))
// 继续循环:检查下一个结束符,然后处理下一个对象
self.stack.push(TriGState::ObjectCollectionPossibleEnd)
self.stack.push(TriGState::Object)
}
self
}
// 2. 谓词/宾语路由
// 对应状态: TriGState::WrappedGraphOrPredicateObjectList
// 功能: 区分 Graph 块 '{' 和普通谓词
///|
fn TriGRecognizer::handle_wrapped_graph_or_predicate_object_list(
self : TriGRecognizer,
term : NamedOrBlankNodeRef,
token : LocatedTokenOrLineJump,
context : TriGRecognizerContext,
results : Array[RdfOut],
) -> TriGRecognizer {
self.debug_logger.info(
"[Step 3] Token stack: \{@debug.to_string(self.stack)} Token: \{token}",
)
match token {
// Graph branch
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("{"), _)
) if context.with_graph_name => {
self.debug_logger.info("WrappedGraphOrPredicateObjectList: Graph branch")
self.cur_graph = term.into_graph()
self.stack.push(TriGState::WrappedGraph)
// ✅ 递归调用,让 WrappedGraph 处理 {
self.recognize_next(
token,
RdfContext::TriGRecognizerContext(context),
results,
)
}
// 'a' predicate
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::PlainKeyword("a"), _)
) => {
self.debug_logger.info("WrappedGraphOrPredicateObjectList: 'a' predicate")
self.cur_subject.push(term)
self.cur_predicate.push(lwTYPE)
self.stack.push(TriGState::ExpectDot)
self.stack.push(TriGState::ObjectsList)
// ✅ 递归调用,用同一个 token 进入 ObjectsList
self.recognize_next(
token,
RdfContext::TriGRecognizerContext(context),
results,
)
}
// IRI predicate
LocatedTokenOrLineJump::LocatedN3Token(LocatedN3Token(N3Token::Iri(iri), _)) => {
self.debug_logger.info(
"WrappedGraphOrPredicateObjectList: IRI predicate: \{iri}",
)
self.cur_subject.push(term)
self.cur_predicate.push(NamedNodeRef::new_unchecked(iri))
self.stack.push(TriGState::ExpectDot)
self.stack.push(TriGState::ObjectsList)
self
// ✅ 递归调用,用同一个 token 进入 ObjectsList
// self.recognize_next(
// token,
// RdfContext::TriGRecognizerContext(context),
// results,
// errors,
// )
}
// PrefixedName predicate
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(
N3Token::PrefixedName(prefix~, localx~, might_be_invalid_iri~),
_
)
) =>
match
resolve_local_name(
prefix,
localx,
might_be_invalid_iri,
context.prefixes,
) {
Ok(t) => {
self.debug_logger.info(
"WrappedGraphOrPredicateObjectList: PrefixedName predicate: \{t}",
)
self.cur_subject.push(term)
self.cur_predicate.push(t)
self.stack.push(TriGState::ExpectDot)
self.stack.push(TriGState::ObjectsList)
// ✅ 递归调用
self.recognize_next(
token,
RdfContext::TriGRecognizerContext(context),
results,
)
}
Err(e) => self.error(e)
}
// Invalid
_ => {
self.debug_logger.info(
"WrappedGraphOrPredicateObjectList: Invalid token: \{token}",
)
self.error(
"Expected a predicate (IRI or 'a') or graph block '{' after subject",
)
}
}
}
///|
fn TriGRecognizer::handle_object(
self : TriGRecognizer,
token : LocatedTokenOrLineJump,
context : TriGRecognizerContext,
results : Array[RdfOut],
) -> TriGRecognizer {
self.debug_logger.info(
"[Step 5] Token stack: \{@debug.to_string(self.stack)} Token: \{token}",
)
self.debug_logger.info("Token: \{token}")
match token {
LocatedTokenOrLineJump::LocatedN3Token(LocatedN3Token(N3Token::Iri(iri), _)) => {
self.debug_logger.info("Object: IRI branch, pushing object")
self.cur_object.push(
TermRef::NamedNodeRef(NamedNodeRef::new_unchecked(iri)),
)
self.emit_quad(results)
self.debug_logger.info(
"DEBUG: Pushing PredicateObjectListEnd after IRI object",
)
// 关键:根据是否在集合中决定下一个状态
// if self.in_collection {
// self.stack.push(TriGState::ObjectCollectionPossibleEnd)
// } else {
self.stack.push(TriGState::PredicateObjectListEnd)
// }
self
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(
N3Token::PrefixedName(prefix~, localx~, might_be_invalid_iri~),
_
)
) =>
match
resolve_local_name(
prefix,
localx,
might_be_invalid_iri,
context.prefixes,
) {
Ok(t) => {
self.debug_logger.info("Object: PrefixedName branch, pushing object")
self.cur_object.push(TermRef::NamedNodeRef(t))
self.emit_quad(results)
// if self.in_collection {
// self.stack.push(TriGState::ObjectCollectionPossibleEnd)
// } else {
self.stack.push(TriGState::PredicateObjectListEnd)
// }
self
}
Err(e) => self.error(e)
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("("), _)
) => {
// 嵌套集合
self.stack.push(TriGState::ObjectCollectionBeginning)
self
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("["), _)
) => {
// 空白节点属性列表
self.stack.push(TriGState::ObjectBlankNodePropertyListCurrent)
self
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::String(value), _)
)
| LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::LongString(value), _)
) => {
self.stack.push(TriGState::LiteralPossibleSuffix(value~, emit=true))
self
}
// 数字和布尔值处理... (省略部分重复代码,逻辑同原文件)
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Integer(v), _)
) => {
let v = try @string.parse_int(v) |> Ok catch {
e => Err(e)
}
match v {
Ok(value) => {
self.cur_object.push(
LiteralRef::new_typed_literal(
VarDataType::IntVar(value.to_string()),
lwINTEGER,
).as_term(),
)
self.emit_quad(results)
// if self.in_collection {
// self.stack.push(TriGState::ObjectCollectionPossibleEnd)
// } else {
self.stack.push(TriGState::PredicateObjectListEnd)
// }
self
}
Err(e) => self.error(e.to_string())
}
}
// 处理终止符号,防止死循环
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(
N3Token::Punctuation("." | ";" | "," | "]" | "}" | "|}"),
_
)
) => {
self.debug_logger.info(
"Object: Syntax Error - Expected an object but found termination token: \{token}",
)
return self.error(
"Syntax Error: Expected an RDF object (IRI, literal, blank node, or collection) but found '\{token.to_string()}'. Missing object for predicate.",
)
}
_ => self.error("TOKEN is not a valid RDF object")
}
}
// 4. 主语处理
// 对应状态: TriGState::TriplesOrGraph
// 功能: 识别主语(IRI、前缀名、空节点、集合、引用三元组)并路由到 WrappedGraphOrPredicateObjectList
///|
fn TriGRecognizer::handle_triples_or_graph(
self : TriGRecognizer,
token : LocatedTokenOrLineJump,
context : TriGRecognizerContext,
// results : Array[RdfOut],
) -> TriGRecognizer {
self.debug_logger.info("TriplesOrGraph: handle_triples_or_graph")
self.debug_logger.info(
"[Step 2] Token stack: \{@debug.to_string(self.stack)} Token: \{token}",
)
// self.debug_logger.info("Cur subject lenth: \{self.cur_subject.length()}")
match token {
LocatedTokenOrLineJump::LocatedN3Token(LocatedN3Token(N3Token::Iri(iri), _)) => {
// self.cur_subject.push(NamedNodeRef::new_unchecked(iri).as_enum())
self.stack.push(
TriGState::WrappedGraphOrPredicateObjectList(
term=NamedNodeRef::new_unchecked(iri).as_enum(),
),
)
self
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(
N3Token::PrefixedName(prefix~, localx~, might_be_invalid_iri~),
_
)
) =>
match
resolve_local_name(
prefix,
localx,
might_be_invalid_iri,
context.prefixes,
) {
Ok(t) => {
self.cur_subject.push(t.as_enum())
self.stack.push(
TriGState::WrappedGraphOrPredicateObjectList(term=t.as_enum()),
)
self
}
Err(e) => self.error(e)
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::BlankNodeLabel(label), _)
) => {
self.stack.push(
TriGState::WrappedGraphOrPredicateObjectList(
term=NamedNodeRef::new_unchecked(label).as_enum(),
),
)
self
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("["), _)
) => {
self.stack.push(TriGState::WrappedGraphBlankNodePropertyListCurrent)
self
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("("), _)
) => {
self.stack.push(TriGState::ExpectDot)
self.stack.push(TriGState::PredicateObjectList)
self.stack.push(TriGState::SubjectCollectionBeginning)
self
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("<<"), _)
) => {
self.stack.push(TriGState::MaybePredicateObjectList)
self.stack.push(TriGState::SubjectReifiedTripleEnd)
self.stack.push(TriGState::EndOfReifiedTripleBeforeReifier)
self.stack.push(TriGState::ReifiedTripleObject(is_reified=true))
self.stack.push(TriGState::Verb)
self.stack.push(TriGState::ReifiedTripleSubject(is_reified=true))
self
}
_ => self.error("TOKEN is not a valid subject or graph name")
}
}
// 5. 谓词列表
// 对应状态: TriGState::PredicateObjectList
// 功能: 初始化谓词-对象对的处理流程
///|
fn TriGRecognizer::handle_predicate_object_list(
self : TriGRecognizer,
token : LocatedTokenOrLineJump,
context : TriGRecognizerContext,
results : Array[RdfOut],
) -> TriGRecognizer {
self.debug_logger.info(
"[Step 5] Token stack: \{@debug.to_string(self.stack)}",
)
self.stack.push(TriGState::PredicateObjectListEnd)
self.stack.push(TriGState::Object)
self.stack.push(TriGState::Verb) // 修正:原代码可能遗漏了 Verb,否则无法解析第一个谓词
self.recognize_next(
token,
RdfContext::TriGRecognizerContext(context),
results,
)
}
// 对应状态: TriGState::PredicateObjectListEnd
// 功能: 处理谓词-对象对之间的分隔符 (, ; .)
///|
///|
fn TriGRecognizer::handle_predicate_object_list_end(
self : TriGRecognizer,
token : LocatedTokenOrLineJump,
// context : TriGRecognizerContext,
// results : Array[RdfOut],
) -> TriGRecognizer {
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation(","), _)
) => {
// 逗号表示同一个谓词的下一个对象
self.stack.push(TriGState::Object)
self
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation(";"), _)
) => {
// 分号表示同一个主语的下一个谓词
self.stack.push(TriGState::PredicateObjectListPossibleContinuation)
self
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("."), _)
) => {
// 句号表示语句结束
self.stack.clear()
self.stack.push(TriGState::TriGDoc)
self.cur_subject.clear()
self.cur_predicate.clear()
self.cur_object.clear()
self
}
_ => self.error("Expected ';' or '.' after predicate-object list")
}
}
// 6. ObjectsList 路由
// 对应状态: TriGState::ObjectsList
// 功能: 处理多个对象的情况(由逗号分隔),通常由 'a' 或谓词后触发
///|
fn TriGRecognizer::handle_objects_list(
self : TriGRecognizer,
token : LocatedTokenOrLineJump,
context : TriGRecognizerContext,
results : Array[RdfOut],
) -> TriGRecognizer {
self.debug_logger.info(
"[Step 4] Token stack: \{@debug.to_string(self.stack)} Token: \{token}",
)
// 原逻辑 L1030-L1035:
// self.stack.push(TriGState::Object)
// return self.recognize_next(...)
self.stack.push(TriGState::Object)
self.recognize_next(
token,
RdfContext::TriGRecognizerContext(context),
results,
)
// self
}
// 7. 文档和图
// 对应状态: TriGState::TriGDoc
// 功能: 处理文档级指令 (BASE, PREFIX, VERSION) 和图的入口
///|
fn TriGRecognizer::handle_trig_doc(
self : TriGRecognizer,
token : LocatedTokenOrLineJump,
context : TriGRecognizerContext,
// results : Array[RdfOut],
) -> TriGRecognizer {
self.debug_logger.info("[Step 1] Entering TriGDoc with token: \{token}")
// self.debug_logger.info("Token stack: \{@debug.to_string(self.stack)}")
// self.debug_logger.info(
// "Subject length: \{self.cur_subject.length()}"
// )
// 重置当前图为默认图
self.cur_graph = GraphNameRef::DefaultGraph
self.stack.push(TriGState::TriGDoc)
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::PlainKeyword(k), _)
) if eq_ignore_ascii_case(k, "base") => {
self.stack.push(TriGState::BaseExpectIri)
return self
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::PlainKeyword(k), _)
) if eq_ignore_ascii_case(k, "prefix") => {
self.stack.push(TriGState::PrefixExpectPrefix)
return self
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::PlainKeyword(k), _)
) if eq_ignore_ascii_case(k, "version") => {
self.stack.push(TriGState::VersionExpectVersion)
return self
}
// 处理 @prefix, @base, @version 语法糖 (通过 LangTag 模拟)
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::LangTag(language="prefix", direction=None), _)
) => {
self.stack.push(TriGState::ExpectDot)
self.stack.push(TriGState::PrefixExpectPrefix)
return self
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::LangTag(language="base", direction=None), _)
) => {
self.stack.push(TriGState::ExpectDot)
self.stack.push(TriGState::BaseExpectIri)
return self
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::LangTag(language="version", direction=None), _)
) => {
self.stack.push(TriGState::ExpectDot)
self.stack.push(TriGState::VersionExpectVersion)
return self
}
// 处理 GRAPH 关键字
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::PlainKeyword(k), _)
) if eq_ignore_ascii_case(k, "graph") && context.with_graph_name => {
self.stack.push(TriGState::WrappedGraph)
self.stack.push(TriGState::GraphName)
return self
}
// 处理匿名图开始 {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("{"), _)
) if context.with_graph_name => {
self.stack.push(TriGState::WrappedGraph)
return self
}
// 默认情况:进入三元组或图解析
_ => {
// self.stack.push(TriGState::TriGDoc)
self.stack.push(TriGState::TriplesOrGraph)
self
// return self.handle_triples_or_graph(token, context, errors)
}
}
}
// 对应状态: TriGState::WrappedGraph
// 功能: 确认图块的开始 '{' 并进入图内容解析
///|
fn TriGRecognizer::handle_wrapped_graph(
self : TriGRecognizer,
token : LocatedTokenOrLineJump,
_context : TriGRecognizerContext,
_results : Array[RdfOut],
) -> TriGRecognizer {
self.debug_logger.info("Entering WrappedGraph with token: \{token}")
self.debug_logger.info("Token stack: \{@debug.to_string(self.stack)}")
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("{"), _)
) => {
self.stack.push(TriGState::WrappedGraphPossibleEnd)
self.stack.push(TriGState::Triples)
return self
}
_ =>
return self.error(
"The GRAPH keyword should be followed by a graph name and a value in '{'",
)
}
}
///|
fn TriGRecognizer::handle_in_collection(
self : TriGRecognizer,
) -> TriGRecognizer {
// 当遇到 '(' 时调用,初始化集合解析状态
// 此时不消耗 token,或者消耗 '(' 后进入 CollectionElement
// 这里假设 '(' 已经被 consume 或者由上层状态压入 InCollection/CollectionElement
// 如果当前是在 Object 位置遇到 '(',通常意味着开始一个新的集合对象
// 我们需要创建一个根 BlankNode 作为集合的头节点(如果是非空集合的第一个元素的前驱)
// 但根据 RDF 列表语义,(a b) 等价于 _:b1 rdf:first a; rdf:rest _:b2. _:b2 rdf:first b; rdf:rest rdf:nil.
// 注意:在 Moonbit/TriG 解析器中,通常由 ObjectsList 检测到 '(' 后压入 InCollection
// 我们保持 InCollection 作为标记,但让 recognize_next 立即转到 CollectionElement
return self
}
///|
fn TriGRecognizer::handle_collection_element(
self : TriGRecognizer,
token : LocatedTokenOrLineJump,
) -> TriGRecognizer {
self.debug_logger.info("Handling CollectionElement with token: \{token}")
match token {
// 1. 空集合: ()
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation(")"), _)
) => {
self.debug_logger.info("CollectionElement: empty collection")
// 空集合直接对应 rdf:nil
self.cur_object.push(TermRef::NamedNodeRef(lwNIL))
// 注意:空集合不需要 emit_quad,因为 nil 是直接作为对象使用的
let _ = self.stack.pop() // Pop CollectionElement
let _ = self.stack.pop() // Pop InCollection
// 回到上一个状态,通常是等待对象结束的状态
self.stack.push(TriGState::PredicateObjectListEnd)
// 或者更通用的:self.stack.push(TriGState::ObjectPostProcess) 如果有的话
return self
}
// 2. 嵌套集合: ( ... )
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("("), _)
) => {
self.debug_logger.info("CollectionElement: nested collection start")
// 嵌套集合本身是一个对象,它会产生一个 BlankNode 作为头节点
let head_bnode = BlankNode::default()
self.cur_subject.push(
NamedOrBlankNodeRef::BlankNodeRef(head_bnode.as_ref()),
)
self.cur_predicate.push(lwFIRST)
// 压入状态以解析内层集合
// 内层集合解析完后,会将结果放在 cur_object 中
// 然后回到当前状态?不,原代码是压入 InCollection + ObjectsList
self.stack.push(TriGState::CollectionEnd) // 处理当前外层节点的 rest
self.stack.push(TriGState::InCollection) // 标记进入内层集合上下文
self.stack.push(TriGState::ObjectsList) // 开始解析内层集合的元素
// 注意:这里需要确保内层集合解析出的头节点能被正确用作当前外层的 "Object"
// 原代码逻辑中,ObjectsList 最终会推到 Object 状态,Object 状态处理完 token 后会 emit_quad?
// 这是一个复杂的交互。
return self
}
// 3. 普通元素 (IRI, Integer, String, etc.)
_ => {
// 委托给 handle_object 来解析具体的 Token 为 Term
// 但我们需要先准备列表节点的结构
let list_node_bnode = BlankNode::default()
// 原代码逻辑:
// 1. Push list_node_bnode to cur_object? (原代码做法)
// 2. Emit Quad.
// 3. Push list_node_bnode to cur_subject.
// 4. Push lwFIRST to cur_predicate.
// 5. Push CollectionEnd.
// 6. Push Object (to parse the actual value).
// 这种顺序意味着:
// 当 Object 状态处理完实际值(如 IRI)后,它会 emit_quad。
// 此时 cur_subject=list_node_bnode, cur_predicate=rdf:first, cur_object=ActualValue.
// 这符合 RDF 语义。
self.cur_object.push(TermRef::BlankNodeRef(list_node_bnode.as_ref()))
let bnode_curr = BlankNode::default()
self.cur_subject.push(
NamedOrBlankNodeRef::BlankNodeRef(bnode_curr.as_ref()),
)
self.cur_predicate.push(lwFIRST)
self.stack.push(TriGState::CollectionEnd)
self.stack.push(TriGState::Object)
return self
}
}
}
///|
fn TriGRecognizer::handle_collection_end(
self : TriGRecognizer,
token : LocatedTokenOrLineJump,
results : Array[RdfOut],
) -> TriGRecognizer {
self.debug_logger.info("Handling CollectionEnd with token: \{token}")
match token {
// 集合结束: )
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation(")"), _)
) => {
self.debug_logger.info("CollectionEnd: closing collection")
// 弹出当前列表节点 (Subject)
let subject = match self.cur_subject.pop() {
Some(s) => s
None =>
return self.error(
"Internal error: subject stack empty in CollectionEnd",
)
}
// 清理 Predicate 和 Object (如果有的话,通常 Object 已被 Object 状态消费)
let _ = self.cur_predicate.pop()
let _ = self.cur_object.pop()
// 输出 rdf:rest rdf:nil
results.push(
RdfOut::Quad(
Quad::Quad(
subject.into_owned(),
lwREST.into_owned(),
lwNIL.as_term().into_owned(),
self.cur_graph.into_owned(),
),
),
)
// 弹出 CollectionEnd
let _ = self.stack.pop()
// 此时应该回到 InCollection 的上一个状态?
// 原代码注释说 "保留 InCollection 和 CollectionElement",但这不对,因为 CollectionElement 已经弹出了。
// 栈结构应该是: [..., InCollection, CollectionElement] -> CollectionElement pops itself and InCollection?
let _ = self.stack.pop() // Pop InCollection
// 现在栈顶是进入集合前的状态 (e.g., PredicateObjectListEnd or similar)
return self
}
// 下一个元素
_ => {
self.debug_logger.info("CollectionEnd: next element")
// 弹出当前列表节点 (Subject)
let subject = match self.cur_subject.pop() {
Some(s) => s
None =>
return self.error(
"Internal error: subject stack empty in CollectionEnd",
)
}
let _ = self.cur_predicate.pop()
let _ = self.cur_object.pop()
// 创建新的列表节点 bnode_next
let bnode_next = BlankNode::default()
// 输出 rdf:rest bnode_next
results.push(
RdfOut::Quad(
Quad::Quad(
subject.into_owned(),
lwREST.into_owned(),
bnode_next.as_ref().as_term().into_owned(),
self.cur_graph.into_owned(),
),
),
)
// 准备处理下一个元素:
// 新的当前节点是 bnode_next.
self.cur_subject.push(
NamedOrBlankNodeRef::BlankNodeRef(bnode_next.as_ref()),
)
self.cur_predicate.push(lwFIRST)
// 压入 CollectionEnd (用于处理 bnode_next 的 rest)
self.stack.push(TriGState::CollectionEnd)
// 压入 Object (用于解析下一个元素的值)
self.stack.push(TriGState::Object)
return self
}
}
}
// 8. 图内三元组解析
// 对应状态: TriGState::Triples
///|
fn TriGRecognizer::handle_triples(
self : TriGRecognizer,
token : LocatedTokenOrLineJump,
context : TriGRecognizerContext,
// results : Array[RdfOut],
) -> TriGRecognizer {
self.debug_logger.info("Entering Triples with token: \{token}")
self.debug_logger.info("Token stack: \{@debug.to_string(self.stack)}")
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("}"), _)
) => self
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("["), _)
) => {
self.cur_subject.push(
NamedOrBlankNodeRef::BlankNodeRef(BlankNode::default().as_ref()),
)
self.stack.push(TriGState::PredicateObjectList)
self
}
LocatedTokenOrLineJump::LocatedN3Token(LocatedN3Token(N3Token::Iri(iri), _)) => {
self.cur_subject.push(NamedNodeRef::new_unchecked(iri).as_enum())
self.stack.push(TriGState::PredicateObjectList)
self
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(
N3Token::PrefixedName(prefix~, localx~, might_be_invalid_iri~),
_
)
) =>
match
resolve_local_name(
prefix,
localx,
might_be_invalid_iri,
context.prefixes,
) {
Ok(t) => {
self.cur_subject.push(t.as_enum())
self.stack.push(TriGState::PredicateObjectList)
self
}
Err(e) => self.error(e)
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::BlankNodeLabel(label), _)
) => {
self.cur_subject.push(
NamedOrBlankNodeRef::BlankNodeRef(BlankNodeRef::new_unchecked(label)),
)
self.stack.push(TriGState::PredicateObjectList)
self
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("("), _)
) => {
self.stack.push(TriGState::PredicateObjectList)
self.stack.push(TriGState::SubjectCollectionBeginning)
self
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("<<"), _)
) => {
self.stack.push(TriGState::MaybePredicateObjectList)
self.stack.push(TriGState::SubjectReifiedTripleEnd)
self.stack.push(TriGState::EndOfReifiedTripleBeforeReifier)
self.stack.push(TriGState::ReifiedTripleSubject(is_reified=true))
self.stack.push(TriGState::Verb)
self.stack.push(TriGState::ReifiedTripleObject(is_reified=true))
self
}
_ => self.error("TOKEN is not a valid RDF subject")
}
}
// 9. 注解块处理
// 对应状态: TriGState::AnnotationBlock
///|
fn TriGRecognizer::handle_annotation_block(
self : TriGRecognizer,
with_reifier : Bool,
token : LocatedTokenOrLineJump,
// context : TriGRecognizerContext,
results : Array[RdfOut],
) -> TriGRecognizer {
self.debug_logger.info(
"Entering AnnotationBlock(with_reifier=\{with_reifier}) with token: \{token}",
)
self.debug_logger.info("Token stack: \{@debug.to_string(self.stack)}")
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation(","), _)
) => {
let _ = self.cur_object.pop()
if with_reifier {
let _ = self.cur_reifier.pop()
}
self.stack.push(TriGState::AnnotationBlock(with_reifier=false))
self.stack.push(TriGState::Object)
self
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("~"), _)
) => {
let cur_sub = match self.cur_subject.last() {
Some(s) => s
None => {
self.errors.push(
RuleRecognizerError::SyntaxError(
"Internal error: subject stack empty",
self.last_range,
),
)
return self
}
}
let cur_pred = match self.cur_predicate.last() {
Some(p) => p
None => {
self.errors.push(
RuleRecognizerError::SyntaxError(
"Internal error: predicate stack empty",
self.last_range,
),
)
return self
}
}
let cur_obj = match self.cur_object.last() {
Some(o) => o
None => {
self.errors.push(
RuleRecognizerError::SyntaxError(
"Internal error: object stack empty",
self.last_range,
),
)
return self
}
}
self.stack.push(TriGState::AnnotationBlock(with_reifier=true))
self.stack.push(
TriGState::Reifier(
triple=TripleRef::TripleRef(cur_sub, cur_pred, cur_obj).into_owned(),
),
)
self
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("{|"), _)
) => {
let cur_sub = match self.cur_subject.last() {
Some(s) => s
None => {
self.errors.push(
RuleRecognizerError::SyntaxError(
"Internal error: subject stack empty",
self.last_range,
),
)
return self
}
}
let cur_pred = match self.cur_predicate.last() {
Some(p) => p
None => {
self.errors.push(
RuleRecognizerError::SyntaxError(
"Internal error: predicate stack empty",
self.last_range,
),
)
return self
}
}
let cur_obj = match self.cur_object.last() {
Some(o) => o
None => {
self.errors.push(
RuleRecognizerError::SyntaxError(
"Internal error: object stack empty",
self.last_range,
),
)
return self
}
}
let reifier = if with_reifier {
match self.cur_reifier.last() {
Some(r) => r
None => {
self.errors.push(
RuleRecognizerError::SyntaxError(
"Internal error: reifier stack empty",
self.last_range,
),
)
return self
}
}
} else {
let reifier = BlankNode::default()
results.push(
RdfOut::Quad(
Quad::Quad(
reifier.as_enum(),
lwREIFIES.into_owned(),
TermRef::TripleRef(
TripleRef::TripleRef(cur_sub, cur_pred, cur_obj),
).into_owned(),
self.cur_graph.into_owned(),
),
),
)
reifier.as_enum().as_ref()
}
self.cur_subject.push(reifier)
self.stack.push(TriGState::AnnotationBlock(with_reifier~))
self.stack.push(TriGState::PredicateObjectList)
self
}
_ => {
let _ = self.cur_object.pop()
if with_reifier {
let _ = self.cur_reifier.pop()
}
self
}
}
}
// 10. 字面量后缀处理
// 对应状态: TriGState::LiteralPossibleSuffix
///|
fn TriGRecognizer::handle_literal_possible_suffix(
self : TriGRecognizer,
value : String,
emit : Bool,
token : LocatedTokenOrLineJump,
// context : TriGRecognizerContext,
results : Array[RdfOut],
) -> TriGRecognizer {
self.debug_logger.info(
"Entering LiteralPossibleSuffix(\{value}, emit=\{emit}) with token: \{token}",
)
self.debug_logger.info("Token stack: \{@debug.to_string(self.stack)}")
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::LangTag(language~, direction~), _)
) => {
self.cur_object.push(
if direction is Some(direction) {
let lang_tag = try
LanguageTag::from_str(language.to_lower()) |> Ok
catch {
e => Err(e)
}
let resolved_lang_tag = match lang_tag {
Ok(tag) => tag
Err(e) => {
self.errors.push(
RuleRecognizerError::SyntaxError(e.to_string(), self.last_range),
)
return self
}
}
TermRef::LiteralRef(
LiteralRef::new_directional_language_tagged_literal_unchecked(
value, resolved_lang_tag, direction,
),
)
} else {
TermRef::LiteralRef(
Literal::new_language_tagged_literal_unchecked(
value,
language.to_lower(),
).as_ref(),
)
},
)
if emit {
self.emit_quad(results)
self.stack.push(TriGState::PredicateObjectListEnd)
}
self
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("^^"), _)
) => {
self.stack.push(TriGState::LiteralPossibleSuffix(value~, emit~))
self
}
_ => {
self.cur_object.push(LiteralRef::new_simple_literal(value).as_term())
if emit {
self.emit_quad(results)
self.stack.push(TriGState::PredicateObjectListEnd)
}
self
}
}
}
// 11. 引用三元组对象结束
// 对应状态: TriGState::ObjectReifiedTripleEnd
///|
fn TriGRecognizer::handle_object_reified_triple_end(
self : TriGRecognizer,
emit : Bool,
token : LocatedTokenOrLineJump,
// context : TriGRecognizerContext,
results : Array[RdfOut],
) -> TriGRecognizer {
self.debug_logger.info(
"Entering ObjectReifiedTripleEnd(emit=\{emit}) with token: \{token}",
)
self.debug_logger.info("Token stack: \{@debug.to_string(self.stack)}")
let subject = match self.cur_subject.pop() {
Some(s) => s
None => {
self.errors.push(
RuleRecognizerError::SyntaxError(
"Internal error: subject stack is empty",
self.last_range,
),
)
return self
}
}
let blank_ref = match subject {
NamedOrBlankNodeRef::BlankNodeRef(b) => TermRef::BlankNodeRef(b)
_ => abort("Subject must be a blank node")
}
self.cur_object.push(blank_ref)
if emit {
self.emit_quad(results)
}
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation(">>"), _)
) => self
_ => self.error("Expecting '>>' to close a reified triple, found TOKEN")
}
}
// 12. 空节点属性列表结束 (对象)
// 对应状态: TriGState::ObjectBlankNodePropertyListEnd
///|
fn TriGRecognizer::handle_object_blank_node_property_list_end(
self : TriGRecognizer,
token : LocatedTokenOrLineJump,
// context : TriGRecognizerContext,
results : Array[RdfOut],
) -> TriGRecognizer {
self.debug_logger.info(
"Entering ObjectBlankNodePropertyListEnd with token: \{token}",
)
self.debug_logger.info("Token stack: \{@debug.to_string(self.stack)}")
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("]"), _)
) => {
let subject = match self.cur_subject.pop() {
Some(s) => s
None => {
self.errors.push(
RuleRecognizerError::SyntaxError(
"Internal error: subject stack is empty",
self.last_range,
),
)
return self
}
}
let blank_ref = match subject {
NamedOrBlankNodeRef::BlankNodeRef(b) => b
_ => abort("subject should be a blank node")
}
self.cur_object.push(TermRef::BlankNodeRef(blank_ref))
self.emit_quad(results)
self
}
_ => self.error("blank node property lists should end with a ']'")
}
}
// 13. 谓词列表可能继续
// 对应状态: TriGState::PredicateObjectListPossibleContinuation
///|
fn TriGRecognizer::handle_predicate_object_list_possible_continuation(
self : TriGRecognizer,
token : LocatedTokenOrLineJump,
// context : TriGRecognizerContext,
// results : Array[RdfOut],
// errors : Array[RuleRecognizerError],
) -> TriGRecognizer {
self.debug_logger.info(
"Entering PredicateObjectListPossibleContinuation with token: \{token}",
)
self.debug_logger.info("Token stack: \{@debug.to_string(self.stack)}")
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation(";"), _)
) => {
self.stack.push(TriGState::PredicateObjectListPossibleContinuation)
self
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("." | "}" | "]" | "|}"), _)
) => self
_ => {
self.stack.push(TriGState::PredicateObjectListEnd)
self.stack.push(TriGState::Object)
self.stack.push(TriGState::Verb)
self
}
}
}
// 14. 图结束处理
// 对应状态: TriGState::WrappedGraphPossibleEnd
///|
fn TriGRecognizer::handle_wrapped_graph_possible_end(
self : TriGRecognizer,
token : LocatedTokenOrLineJump,
) -> TriGRecognizer {
self.debug_logger.info(
"Entering WrappedGraphPossibleEnd with token: \{token}",
)
self.debug_logger.info("Token stack: \{@debug.to_string(self.stack)}")
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("}"), _)
) => self
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("."), _)
) => {
self.stack.push(TriGState::WrappedGraphPossibleEnd)
self.stack.push(TriGState::Triples)
self
}
_ => {
self.errors.push(RuleRecognizerError::TripleMissingDot)
self
}
}
}
///|
///|
fn TriGRecognizer::handle_verb(
self : TriGRecognizer,
token : LocatedTokenOrLineJump,
context : TriGRecognizerContext,
_results : Array[RdfOut],
) -> TriGRecognizer {
self.debug_logger.info("Verb: handling token: \{token}")
match token {
// 'a' 表示 rdf:type
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::PlainKeyword("a"), _)
) => {
self.debug_logger.info("Verb: 'a' predicate")
self.cur_predicate.push(lwTYPE)
self.stack.push(TriGState::ObjectsList)
self
}
// IRI 谓词
LocatedTokenOrLineJump::LocatedN3Token(LocatedN3Token(N3Token::Iri(iri), _)) => {
self.debug_logger.info("Verb: IRI predicate: \{iri}")
self.cur_predicate.push(NamedNodeRef::new_unchecked(iri))
// 修复:确保推入 ObjectsList 状态,以便接下来解析对象
self.stack.push(TriGState::ObjectsList)
self
}
// 前缀名谓词
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(
N3Token::PrefixedName(prefix~, localx~, might_be_invalid_iri~),
_
)
) =>
match
resolve_local_name(
prefix,
localx,
might_be_invalid_iri,
context.prefixes,
) {
Ok(t) => {
self.debug_logger.info("Verb: PrefixedName predicate: \{t}")
self.cur_predicate.push(t)
self.stack.push(TriGState::ObjectsList)
self
}
Err(e) => self.error(e)
}
// 其他情况 - 错误
_ => {
self.debug_logger.info("Verb: Invalid token: \{token}")
self.error(
"Expected a predicate (IRI or 'a'), found: \{token.to_string()}",
)
}
}
}