// ===== State: N3Doc =====
///|
fn N3Recognizer::handle_n3_doc_m(
self : N3Recognizer,
token : LocatedTokenOrLineJump,
_context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info("Entering N3Doc with token: \{token}")
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::PlainKeyword(k), _)
) if eq_ignore_ascii_case(k, "base") =>
Ok((self, N3State::BaseExpectIri, None))
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::PlainKeyword(k), _)
) if eq_ignore_ascii_case(k, "prefix") =>
Ok((self, N3State::PrefixExpectPrefix, None))
// 处理特殊的 LangTag 作为关键字的情况 (如果 lexer 这样输出)
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::LangTag(language="prefix", direction=None), _)
) =>
// 这里可能需要一个中间状态来处理 prefix 后的 IRI,然后再处理 Dot
// 简化处理:直接进入 PrefixExpectPrefix,假设后续逻辑能处理 Dot 或依靠栈
Ok((self, N3State::PrefixExpectPrefix, None))
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::LangTag(language="base", direction=None), _)
) => Ok((self, N3State::BaseExpectIri, None))
_ => {
// 默认进入 Triples 解析,解析完后期望 Dot
// 我们将 N3DocExpectDot 压入栈,以便 Triples 结束后返回这里
let new_stack = self.stack
new_stack.push(N3State::N3DocExpectDot)
let new_self = { ..self, stack: new_stack }
Ok((new_self, N3State::Triples, None))
}
}
}
// ===== State: N3DocExpectDot =====
///|
fn N3Recognizer::handle_n3_doc_expect_dot_m(
self : N3Recognizer,
token : LocatedTokenOrLineJump,
_context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info("Entering N3DocExpectDot with token: \{token}")
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("."), _)
) =>
// 语句结束,回到 N3Doc 继续解析下一条
Ok((self, N3State::N3Doc, None))
_ => {
let err = RuleRecognizerError::SyntaxError(
"A dot is expected at the end of N3 statements",
self.last_range,
)
Err(err)
}
}
}
// ===== State: BaseExpectIri =====
///|
fn N3Recognizer::handle_base_expect_iri_m(
self : N3Recognizer,
token : LocatedTokenOrLineJump,
context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info("Entering BaseExpectIri with token: \{token}")
if token
is LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Iri(iri), _)
) {
match context {
RdfContext::N3RecognizerContext(ctx) => {
let new_options = { base_iri: Some(Iri::Iri(iri)) }
let _new_ctx = { ..ctx, lexer_options: new_options }
// 注意:context 通常是通过 StateMachine 的 set_context 更新的,或者存储在 self 中
// 这里假设我们需要更新 self 中的 context 或者返回新的 self 携带更新后的 context
// 由于 signature 限制,我们只能返回 self。通常 context 是外部传入的。
// 如果 context 是可变的且在 self 中,这里需要更新 self。
// 假设 context 更新由外层处理,或者我们只关注状态转移。
// BASE 语句后通常跟一个点
Ok((self, N3State::N3DocExpectDot, None))
}
_ =>
Err(
RuleRecognizerError::SyntaxError("Invalid context", self.last_range),
)
}
} else {
Err(
RuleRecognizerError::SyntaxError(
"The BASE keyword should be followed by an IRI",
self.last_range,
),
)
}
}
// ===== State: PrefixExpectPrefix =====
///|
fn N3Recognizer::handle_prefix_expect_prefix_m(
self : N3Recognizer,
token : LocatedTokenOrLineJump,
_context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info("Entering PrefixExpectPrefix with token: \{token}")
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::PrefixedName(prefix~, localx~, ..), _)
) if localx.is_empty() =>
// 转移到期待 IRI 的状态,并携带 prefix 名称
// 假设 N3State::PrefixExpectIri 可以携带参数,或者我们需要将 prefix 暂存到 self 中
// 这里假设 N3State 枚举定义为 PrefixExpectIri(String)
Ok((self, N3State::PrefixExpectIri(name=prefix), None))
_ =>
Err(
RuleRecognizerError::SyntaxError(
"The PREFIX keyword should be followed by a prefix like 'ex:'",
self.last_range,
),
)
}
}
// ===== State: PrefixExpectIri =====
///|
fn N3Recognizer::handle_prefix_expect_iri_m(
self : N3Recognizer,
name : String, // 从状态中提取的参数
token : LocatedTokenOrLineJump,
context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info(
"Entering PrefixExpectIri(\{name}) with token: \{token}",
)
if token
is LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Iri(iri), _)
) {
match context {
RdfContext::N3RecognizerContext(ctx) => {
ctx.prefixes.set(name, Iri::Iri(iri))
// let new_ctx = { ..ctx}
// 同样,context 的更新可能需要通过 set_context 或在 self 中维护
// 这里假设状态转移后,外层会处理 context 的持久化或 self 已包含 context
Ok((self, N3State::N3DocExpectDot, None))
}
_ =>
Err(
RuleRecognizerError::SyntaxError("Invalid context", self.last_range),
)
}
} else {
Err(
RuleRecognizerError::SyntaxError(
"The PREFIX declaration should be followed by a prefix and its value as an IRI",
self.last_range,
),
)
}
}
// ===== State: Triples =====
///|
fn N3Recognizer::handle_triples_m(
self : N3Recognizer,
token : LocatedTokenOrLineJump,
_context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info("Entering Triples with token: \{token}")
// Triples 开始,首先解析 Subject (Path)
// 原逻辑: push TriplesMiddle, push Path
// 新逻辑: 进入 Path 状态,并记录当 Path 结束后应进入 TriplesMiddle
let new_stack = self.stack
new_stack.push(N3State::TriplesMiddle)
let new_self = { ..self, stack: new_stack }
Ok((new_self, N3State::Path, None))
}
// ===== State: TriplesMiddle =====
///|
fn N3Recognizer::handle_triples_middle_m(
self : N3Recognizer,
token : LocatedTokenOrLineJump,
_context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info("Entering TriplesMiddle with token: \{token}")
// 如果遇到结束符,说明没有 PredicateObjectList,直接结束当前 Triples
if token
is LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("." | "]" | "}" | ")"), _)
) {
// 弹出 TriplesMiddle,回到上一层 (例如 N3DocExpectDot)
// 这里需要手动管理栈弹出,或者依靠上层状态处理
// 简单起见,如果栈顶是 TriplesMiddle,我们弹出它,并返回栈顶下一个状态
let new_stack = self.stack
if !new_stack.is_empty() && new_stack.last() == Some(N3State::TriplesMiddle) {
let _ = new_stack.pop()
}
let next_state = new_stack.last().unwrap_or(N3State::N3Doc)
let new_self = { ..self, stack: new_stack }
Ok((new_self, next_state, None))
} else {
// 否则,开始解析 PredicateObjectList
// 原逻辑: push TriplesEnd, push PredicateObjectList
let new_stack = self.stack
new_stack.push(N3State::TriplesEnd)
new_stack.push(N3State::PredicateObjectList)
let new_self = { ..self, stack: new_stack }
Ok((new_self, N3State::PredicateObjectList, None))
}
}
// ===== State: TriplesEnd =====
///|
fn N3Recognizer::handle_triples_end_m(
self : N3Recognizer,
token : LocatedTokenOrLineJump,
_context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info("Entering TriplesEnd with token: \{token}")
// 原逻辑: pop terms (subject)
let new_terms = self.terms
let _ = new_terms.pop()
let new_self = { ..self, terms: new_terms }
// 弹出 TriplesEnd,回到上一层
let new_stack = self.stack
if !new_stack.is_empty() && new_stack.last() == Some(N3State::TriplesEnd) {
let _ = new_stack.pop()
}
let next_state = new_stack.last().unwrap_or(N3State::N3Doc)
let final_self = { ..new_self, stack: new_stack }
Ok((final_self, next_state, None))
}
// ===== State: PredicateObjectList =====
///|
fn N3Recognizer::handle_predicate_object_list_m(
self : N3Recognizer,
token : LocatedTokenOrLineJump,
_context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info("Entering PredicateObjectList with token: \{token}")
// 原逻辑: push PredicateObjectListEnd, push ObjectsList, push Verb
let new_stack = self.stack
new_stack.push(N3State::PredicateObjectListEnd)
new_stack.push(N3State::ObjectsList)
new_stack.push(N3State::Verb)
let new_self = { ..self, stack: new_stack }
Ok((new_self, N3State::Verb, None))
}
// ===== State: PredicateObjectListEnd =====
///|
fn N3Recognizer::handle_predicate_object_list_end_m(
self : N3Recognizer,
token : LocatedTokenOrLineJump,
_context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info("Entering PredicateObjectListEnd with token: \{token}")
// 原逻辑: pop predicates
let new_predicates = self.predicates
let _ = new_predicates.pop()
let new_self = { ..self, predicates: new_predicates }
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation(";"), _)
) => {
// 分号表示同一个主语的新谓词对象对
// 原逻辑: push PredicateObjectListPossibleContinuation
let new_stack = new_self.stack
new_stack.push(N3State::PredicateObjectListPossibleContinuation)
let final_self = { ..new_self, stack: new_stack }
Ok((final_self, N3State::PredicateObjectListPossibleContinuation, None))
}
_ => {
// 没有分号,结束当前 PredicateObjectList
// 弹出 PredicateObjectListEnd,回到上一层 (通常是 TriplesMiddle 或 PropertyListEnd)
let new_stack = new_self.stack
if !new_stack.is_empty() &&
new_stack.last() == Some(N3State::PredicateObjectListEnd) {
let _ = new_stack.pop()
}
let next_state = new_stack.last().unwrap_or(N3State::N3Doc)
let final_self = { ..new_self, stack: new_stack }
Ok((final_self, next_state, None))
}
}
}
// ===== State: PredicateObjectListPossibleContinuation =====
///|
fn N3Recognizer::handle_predicate_object_list_possible_continuation_m(
self : N3Recognizer,
token : LocatedTokenOrLineJump,
_context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info(
"Entering PredicateObjectListPossibleContinuation with token: \{token}",
)
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation(";"), _)
) =>
// 多个分号,忽略,保持当前状态
Ok((self, N3State::PredicateObjectListPossibleContinuation, None))
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("." | "}" | "]" | ")"), _)
) => {
// 遇到结束符,弹出当前状态,回到上一层
let new_stack = self.stack
if !new_stack.is_empty() &&
new_stack.last() ==
Some(N3State::PredicateObjectListPossibleContinuation) {
let _ = new_stack.pop()
}
let next_state = new_stack.last().unwrap_or(N3State::N3Doc)
let new_self = { ..self, stack: new_stack }
Ok((new_self, next_state, None))
}
_ => {
// 新的谓词开始,重新进入 PredicateObjectList
// 原逻辑: push PredicateObjectListEnd, push ObjectsList, push Verb
let new_stack = self.stack
new_stack.push(N3State::PredicateObjectListEnd)
new_stack.push(N3State::ObjectsList)
new_stack.push(N3State::Verb)
let new_self = { ..self, stack: new_stack }
Ok((new_self, N3State::Verb, None))
}
}
}
// ===== State: ObjectsList =====
///|
fn N3Recognizer::handle_objects_list_m(
self : N3Recognizer,
token : LocatedTokenOrLineJump,
_context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info("Entering ObjectsList with token: \{token}")
// 原逻辑: push ObjectsListEnd, push Path
let new_stack = self.stack
new_stack.push(N3State::ObjectsListEnd)
new_stack.push(N3State::Path)
let new_self = { ..self, stack: new_stack }
Ok((new_self, N3State::Path, None))
}
// ===== State: ObjectsListEnd =====
///|
fn N3Recognizer::handle_objects_list_end_m(
self : N3Recognizer,
token : LocatedTokenOrLineJump,
_context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info("Entering ObjectsListEnd with token: \{token}")
let object = match self.terms.pop() {
Some(o) => o
None =>
return Err(
RuleRecognizerError::SyntaxError(
"Internal error: terms stack empty (object)",
self.last_range,
),
)
}
let subject = match self.terms.last() {
Some(s) => s
None =>
return Err(
RuleRecognizerError::SyntaxError(
"Internal error: terms stack empty (subject)",
self.last_range,
),
)
}
let predicate_opt = match self.predicates.last() {
Some(p) => p
None =>
return Err(
RuleRecognizerError::SyntaxError(
"Internal error: predicates stack empty",
self.last_range,
),
)
}
let quad = match predicate_opt {
Predicate::Regular(predicate) => self.quad(subject, predicate, object)
Predicate::Inverted(predicate) => self.quad(object, predicate, subject)
}
let output = Some(RdfOut::N3Quad(quad))
// let new_results = results // 注意:results 通常由外层收集,这里仅作为示例
// 在实际 StateMachine 中,output 会被外层收集
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation(","), _)
) => {
// 逗号表示同一个谓语的下一个对象
// 原逻辑: push ObjectsListEnd, push Path
let new_stack = self.stack
new_stack.push(N3State::ObjectsListEnd)
new_stack.push(N3State::Path)
let new_self = { ..self, stack: new_stack }
Ok((new_self, N3State::Path, output))
}
_ => {
// 结束对象列表
// 弹出 ObjectsListEnd,回到上一层 (通常是 PredicateObjectListEnd)
let new_stack = self.stack
if !new_stack.is_empty() &&
new_stack.last() == Some(N3State::ObjectsListEnd) {
let _ = new_stack.pop()
}
let next_state = new_stack.last().unwrap_or(N3State::N3Doc)
let new_self = { ..self, stack: new_stack }
Ok((new_self, next_state, output))
}
}
}
// ===== State: Verb =====
///|
fn N3Recognizer::handle_verb_m(
self : N3Recognizer,
token : LocatedTokenOrLineJump,
_context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info("Entering Verb with token: \{token}")
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::PlainKeyword("a"), _)
) => {
let new_predicates = self.predicates
new_predicates.push(Predicate::Regular(lwTYPE.as_n3term()))
let new_self = { ..self, predicates: new_predicates }
// Verb 处理完毕,回到调用者 (ObjectsList)
// 弹出 Verb,回到上一层
let new_stack = new_self.stack
if !new_stack.is_empty() && new_stack.last() == Some(N3State::Verb) {
let _ = new_stack.pop()
}
let next_state = new_stack.last().unwrap_or(N3State::N3Doc)
let final_self = { ..new_self, stack: new_stack }
Ok((final_self, next_state, None))
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::PlainKeyword("has"), _)
) => {
// has
// 原逻辑: push AfterRegularVerb, push Path
let new_stack = self.stack
new_stack.push(N3State::AfterRegularVerb)
new_stack.push(N3State::Path)
let new_self = { ..self, stack: new_stack }
Ok((new_self, N3State::Path, None))
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::PlainKeyword("is"), _)
) => {
// is of
// 原逻辑: push AfterVerbIs, push Path
let new_stack = self.stack
new_stack.push(N3State::AfterVerbIs)
new_stack.push(N3State::Path)
let new_self = { ..self, stack: new_stack }
Ok((new_self, N3State::Path, None))
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("="), _)
) => {
let new_predicates = self.predicates
new_predicates.push(
Predicate::Regular(
NamedNodeRef::new_unchecked("http://www.w3.org/2002/07/owl#sameAs").as_n3term(),
),
)
let new_self = { ..self, predicates: new_predicates }
let new_stack = new_self.stack
if !new_stack.is_empty() && new_stack.last() == Some(N3State::Verb) {
let _ = new_stack.pop()
}
let next_state = new_stack.last().unwrap_or(N3State::N3Doc)
let final_self = { ..new_self, stack: new_stack }
Ok((final_self, next_state, None))
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("=>"), _)
) => {
let new_predicates = self.predicates
new_predicates.push(
Predicate::Regular(
NamedNodeRef::new_unchecked(
"http://www.w3.org/2000/10/swap/log#implies",
).as_n3term(),
),
)
let new_self = { ..self, predicates: new_predicates }
let new_stack = new_self.stack
if !new_stack.is_empty() && new_stack.last() == Some(N3State::Verb) {
let _ = new_stack.pop()
}
let next_state = new_stack.last().unwrap_or(N3State::N3Doc)
let final_self = { ..new_self, stack: new_stack }
Ok((final_self, next_state, None))
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("<="), _)
) => {
let new_predicates = self.predicates
new_predicates.push(
Predicate::Inverted(
NamedNodeRef::new_unchecked(
"http://www.w3.org/2000/10/swap/log#implies",
).as_n3term(),
),
)
let new_self = { ..self, predicates: new_predicates }
let new_stack = new_self.stack
if !new_stack.is_empty() && new_stack.last() == Some(N3State::Verb) {
let _ = new_stack.pop()
}
let next_state = new_stack.last().unwrap_or(N3State::N3Doc)
let final_self = { ..new_self, stack: new_stack }
Ok((final_self, next_state, None))
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("<-"), _)
) => {
// <-
// 原逻辑: push AfterInvertedVerb, push Path
let new_stack = self.stack
new_stack.push(N3State::AfterInvertedVerb)
new_stack.push(N3State::Path)
let new_self = { ..self, stack: new_stack }
Ok((new_self, N3State::Path, None))
}
_ => {
// 默认视为 Regular Verb (IRI or Path)
// 原逻辑: push AfterRegularVerb, push Path
let new_stack = self.stack
new_stack.push(N3State::AfterRegularVerb)
new_stack.push(N3State::Path)
let new_self = { ..self, stack: new_stack }
Ok((new_self, N3State::Path, None))
}
}
}
// ===== State: AfterRegularVerb =====
///|
fn N3Recognizer::handle_after_regular_verb_m(
self : N3Recognizer,
token : LocatedTokenOrLineJump,
_context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info("Entering AfterRegularVerb with token: \{token}")
let term = match self.terms.pop() {
Some(t) => t
None =>
return Err(
RuleRecognizerError::SyntaxError(
"Internal error: terms stack empty in AfterRegularVerb",
self.last_range,
),
)
}
let new_predicates = self.predicates
new_predicates.push(Predicate::Regular(term))
let new_self = { ..self, predicates: new_predicates }
// 弹出 AfterRegularVerb,回到调用者
let new_stack = new_self.stack
if !new_stack.is_empty() &&
new_stack.last() == Some(N3State::AfterRegularVerb) {
let _ = new_stack.pop()
}
let next_state = new_stack.last().unwrap_or(N3State::N3Doc)
let final_self = { ..new_self, stack: new_stack }
Ok((final_self, next_state, None))
}
// ===== State: AfterInvertedVerb =====
///|
fn N3Recognizer::handle_after_inverted_verb_m(
self : N3Recognizer,
token : LocatedTokenOrLineJump,
_context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info("Entering AfterInvertedVerb with token: \{token}")
let term = match self.terms.pop() {
Some(t) => t
None =>
return Err(
RuleRecognizerError::SyntaxError(
"Internal error: terms stack empty in AfterInvertedVerb",
self.last_range,
),
)
}
let new_predicates = self.predicates
new_predicates.push(Predicate::Inverted(term))
let new_self = { ..self, predicates: new_predicates }
let new_stack = new_self.stack
if !new_stack.is_empty() &&
new_stack.last() == Some(N3State::AfterInvertedVerb) {
let _ = new_stack.pop()
}
let next_state = new_stack.last().unwrap_or(N3State::N3Doc)
let final_self = { ..new_self, stack: new_stack }
Ok((final_self, next_state, None))
}
// ===== State: AfterVerbIs =====
///|
fn N3Recognizer::handle_after_verb_is_m(
self : N3Recognizer,
token : LocatedTokenOrLineJump,
_context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info("Entering AfterVerbIs with token: \{token}")
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::PlainKeyword("of"), _)
) => {
let term = match self.terms.pop() {
Some(t) => t
None =>
return Err(
RuleRecognizerError::SyntaxError(
"Internal error: terms stack empty in AfterVerbIs",
self.last_range,
),
)
}
let new_predicates = self.predicates
new_predicates.push(Predicate::Inverted(term))
let new_self = { ..self, predicates: new_predicates }
let new_stack = new_self.stack
if !new_stack.is_empty() && new_stack.last() == Some(N3State::AfterVerbIs) {
let _ = new_stack.pop()
}
let next_state = new_stack.last().unwrap_or(N3State::N3Doc)
let final_self = { ..new_self, stack: new_stack }
Ok((final_self, next_state, None))
}
_ =>
Err(
RuleRecognizerError::SyntaxError(
"The keyword 'is' should be followed by a predicate then by the keyword 'of'",
self.last_range,
),
)
}
}
// ===== State: Path =====
///|
fn N3Recognizer::handle_path_m(
self : N3Recognizer,
token : LocatedTokenOrLineJump,
_context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info("Entering Path with token: \{token}")
// 原逻辑: push PathFollowUp, push PathItem
let new_stack = self.stack
new_stack.push(N3State::PathFollowUp)
new_stack.push(N3State::PathItem)
let new_self = { ..self, stack: new_stack }
Ok((new_self, N3State::PathItem, None))
}
// ===== State: PathFollowUp =====
///|
fn N3Recognizer::handle_path_follow_up_m(
self : N3Recognizer,
token : LocatedTokenOrLineJump,
_context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info("Entering PathFollowUp with token: \{token}")
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("!"), _)
) => {
// ! indicates inverse path in some contexts, or property path
// 原逻辑: push PathAfterIndicator(is_inverse=false), push PathItem
// 注意:N3 中 ! 通常用于 Negation 或 Property Path,这里假设是 Path Indicator
let new_stack = self.stack
new_stack.push(N3State::PathAfterIndicator(is_inverse=false))
new_stack.push(N3State::PathItem)
let new_self = { ..self, stack: new_stack }
Ok((new_self, N3State::PathItem, None))
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("^"), _)
) => {
// ^ indicates inverse path
let new_stack = self.stack
new_stack.push(N3State::PathAfterIndicator(is_inverse=false)) // 假设 ^ 也是某种 indicator
new_stack.push(N3State::PathItem)
let new_self = { ..self, stack: new_stack }
Ok((new_self, N3State::PathItem, None))
}
_ => {
// 没有 follow up,结束 Path
// 弹出 PathFollowUp,回到调用者
let new_stack = self.stack
if !new_stack.is_empty() &&
new_stack.last() == Some(N3State::PathFollowUp) {
let _ = new_stack.pop()
}
let next_state = new_stack.last().unwrap_or(N3State::N3Doc)
let new_self = { ..self, stack: new_stack }
Ok((new_self, next_state, None))
}
}
}
// ===== State: PathAfterIndicator =====
///|
fn N3Recognizer::handle_path_after_indicator_m(
self : N3Recognizer,
is_inverse : Bool,
token : LocatedTokenOrLineJump,
_context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info("Entering PathAfterIndicator with token: \{token}")
let predicate = match self.terms.pop() {
Some(p) => p
None =>
return Err(
RuleRecognizerError::SyntaxError(
"Internal error: terms stack empty (predicate) in PathAfterIndicator",
self.last_range,
),
)
}
let previous = match self.terms.pop() {
Some(prev) => prev
None =>
return Err(
RuleRecognizerError::SyntaxError(
"Internal error: terms stack empty (previous) in PathAfterIndicator",
self.last_range,
),
)
}
let current = BlankNode::default().as_n3term()
let quad = if is_inverse {
self.quad(current, predicate, previous)
} else {
self.quad(previous, predicate, current)
}
let output = Some(RdfOut::N3Quad(quad))
let new_terms = self.terms
new_terms.push(current)
let new_self = { ..self, terms: new_terms }
// 结束后,可能还有 FollowUp
let new_stack = new_self.stack
new_stack.push(N3State::PathFollowUp)
let final_self = { ..new_self, stack: new_stack }
Ok((final_self, N3State::PathFollowUp, output))
}
// ===== State: PathItem =====
///|
fn N3Recognizer::handle_path_item_m(
self : N3Recognizer,
token : LocatedTokenOrLineJump,
context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info("Entering PathItem with token: \{token}")
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("["), _)
) => Ok((self, N3State::PropertyListMiddle, None))
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("("), _)
) => Ok((self, N3State::CollectionBeginning, None))
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("{"), _)
) => {
// Formula
let new_contexts = self.contexts
new_contexts.push(BlankNode::default())
let new_self = { ..self, contexts: new_contexts }
Ok((new_self, N3State::FormulaContent, None))
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("}"), _)
) => {
if self.contexts.is_empty() {
return Err(
RuleRecognizerError::SyntaxError(
"Unexpected '}' outside of formula",
self.last_range,
),
)
}
// let ctx = self.contexts.last().unwrap() // peek
// 注意:这里不应该 pop contexts,应该由 FormulaContent 处理 pop
// 但如果是在 PathItem 中遇到 },说明公式作为项结束
// 原逻辑: pop contexts, push term, pop PathFollowUp
let new_contexts = self.contexts
let ctx = new_contexts.pop().unwrap()
let new_self = { ..self, contexts: new_contexts }
let new_terms = new_self.terms
new_terms.push(ctx.as_n3term())
let new_self = { ..new_self, terms: new_terms }
let new_stack = new_self.stack
if !new_stack.is_empty() &&
new_stack.last() == Some(N3State::PathFollowUp) {
let _ = new_stack.pop()
}
let next_state = new_stack.last().unwrap_or(N3State::N3Doc)
let final_self = { ..new_self, stack: new_stack }
Ok((final_self, next_state, None))
}
_ => {
// 普通 Term
// 调用 handle_term_token_m 的逻辑,但这里直接内联或调用
// 为了简化,我们假设 handle_term_token_m 返回的是 TransitionResult
// 但由于 handle_term_token_m 也需要符合签名,我们这里直接处理
let term_result = self.handle_term_token_internal(token, context)
match term_result {
Ok(new_self) => {
// Term 处理成功,结束 PathItem
let new_stack = new_self.stack
if !new_stack.is_empty() &&
new_stack.last() == Some(N3State::PathItem) {
let _ = new_stack.pop()
}
let next_state = new_stack.last().unwrap_or(N3State::N3Doc)
let final_self = { ..new_self, stack: new_stack }
Ok((final_self, next_state, None))
}
Err(e) => Err(e)
}
}
}
}
// 辅助内部函数,用于处理 Term 并返回新的 Self
///|
fn N3Recognizer::handle_term_token_internal(
self : N3Recognizer,
token : LocatedTokenOrLineJump,
_context : RdfContext,
) -> Result[N3Recognizer, RuleRecognizerError] {
match token {
LocatedTokenOrLineJump::LocatedN3Token(located) =>
match located {
LocatedN3Token(N3Token::Iri(iri), _) => {
let new_terms = self.terms
new_terms.push(NamedNodeRef::new_unchecked(iri).as_n3term())
Ok({ ..self, terms: new_terms })
}
// ... 其他 Token 类型处理类似,省略以节省空间 ...
_ =>
Err(
RuleRecognizerError::SyntaxError(
"TOKEN is not a valid RDF value",
self.last_range,
),
)
}
_ =>
Err(
RuleRecognizerError::SyntaxError(
"TOKEN is not a valid RDF value",
self.last_range,
),
)
}
}
// ===== State: PropertyListMiddle =====
///|
fn N3Recognizer::handle_property_list_middle_m(
self : N3Recognizer,
token : LocatedTokenOrLineJump,
_context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info("Entering PropertyListMiddle with token: \{token}")
self.debug_logger.info("Token stack: \{@debug.to_string(self.stack)}")
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("]"), _)
) => {
let new_terms = self.terms
new_terms.push(BlankNode::default().as_n3term())
let new_self = { ..self, terms: new_terms }
// 结束 BlankNode 属性列表,弹出 PropertyListMiddle,回到调用者 (通常是 PathItem 或 TriplesMiddle)
let new_stack = new_self.stack
if !new_stack.is_empty() &&
new_stack.last() == Some(N3State::PropertyListMiddle) {
let _ = new_stack.pop()
}
let next_state = new_stack.last().unwrap_or(N3State::N3Doc)
let final_self = { ..new_self, stack: new_stack }
Ok((final_self, next_state, None))
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::PlainKeyword("id"), _)
) =>
// 进入 [ id ... ] 模式
Ok((self, N3State::IriPropertyList, None))
_ => {
// 默认情况:匿名空白节点开始,后面跟谓词对象列表
let new_terms = self.terms
new_terms.push(BlankNode::default().as_n3term())
let new_self = { ..self, terms: new_terms }
let new_stack = new_self.stack
new_stack.push(N3State::PropertyListEnd)
new_stack.push(N3State::PredicateObjectList)
let final_self = { ..new_self, stack: new_stack }
Ok((final_self, N3State::PredicateObjectList, None))
}
}
}
// ===== State: PropertyListEnd =====
///|
fn N3Recognizer::handle_property_list_end_m(
self : N3Recognizer,
token : LocatedTokenOrLineJump,
_context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info("Entering PropertyListEnd with token: \{token}")
self.debug_logger.info("Token stack: \{@debug.to_string(self.stack)}")
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("]"), _)
) => {
// 正常结束,弹出 PropertyListEnd
let new_stack = self.stack
if !new_stack.is_empty() &&
new_stack.last() == Some(N3State::PropertyListEnd) {
let _ = new_stack.pop()
}
let next_state = new_stack.last().unwrap_or(N3State::N3Doc)
let new_self = { ..self, stack: new_stack }
Ok((new_self, next_state, None))
}
_ => {
let err = RuleRecognizerError::SyntaxError(
"blank node property lists should end with a ']'",
self.last_range,
)
Err(err)
}
}
}
// ===== State: IriPropertyList =====
///|
fn N3Recognizer::handle_iri_property_list_m(
self : N3Recognizer,
token : LocatedTokenOrLineJump,
context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info("Entering IriPropertyList with token: \{token}")
self.debug_logger.info("Token stack: \{@debug.to_string(self.stack)}")
match token {
LocatedTokenOrLineJump::LocatedN3Token(LocatedN3Token(N3Token::Iri(id), _)) => {
let new_terms = self.terms
new_terms.push(NamedNodeRef::new_unchecked(id).as_n3term())
let new_self = { ..self, terms: new_terms }
let new_stack = new_self.stack
new_stack.push(N3State::PropertyListEnd)
new_stack.push(N3State::PredicateObjectList)
let final_self = { ..new_self, stack: new_stack }
Ok((final_self, N3State::PredicateObjectList, None))
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(
N3Token::PrefixedName(prefix~, localx~, might_be_invalid_iri~),
_
)
) =>
match context {
RdfContext::N3RecognizerContext(ctx) =>
match
resolve_local_name(
prefix,
localx,
might_be_invalid_iri,
ctx.prefixes,
) {
Ok(t) => {
let new_terms = self.terms
new_terms.push(t.as_n3term())
let new_self = { ..self, terms: new_terms }
let new_stack = new_self.stack
new_stack.push(N3State::PropertyListEnd)
new_stack.push(N3State::PredicateObjectList)
let final_self = { ..new_self, stack: new_stack }
Ok((final_self, N3State::PredicateObjectList, None))
}
Err(e) => Err(RuleRecognizerError::SyntaxError(e, self.last_range))
}
_ =>
Err(
RuleRecognizerError::SyntaxError(
"Invalid context for prefix resolution",
self.last_range,
),
)
}
_ =>
Err(
RuleRecognizerError::SyntaxError(
"The '[ id' construction should be followed by an IRI",
self.last_range,
),
)
}
}
// ===== State: CollectionBeginning =====
///|
fn N3Recognizer::handle_collection_beginning_m(
self : N3Recognizer,
token : LocatedTokenOrLineJump,
_context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info("Entering CollectionBeginning with token: \{token}")
self.debug_logger.info("Token stack: \{@debug.to_string(self.stack)}")
if token
is LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation(")"), _)
) {
// 空列表 ()
let new_terms = self.terms
new_terms.push(lwNIL.as_n3term())
let new_self = { ..self, terms: new_terms }
// 弹出 CollectionBeginning,回到调用者
let new_stack = new_self.stack
if !new_stack.is_empty() &&
new_stack.last() == Some(N3State::CollectionBeginning) {
let _ = new_stack.pop()
}
let next_state = new_stack.last().unwrap_or(N3State::N3Doc)
let final_self = { ..new_self, stack: new_stack }
Ok((final_self, next_state, None))
} else {
// 非空列表,创建根节点
let root = BlankNode::default()
let new_terms = self.terms
new_terms.push(root.as_n3term()) // Current list node
new_terms.push(root.as_n3term()) // Previous list node (for linking)
let new_self = { ..self, terms: new_terms }
let new_stack = new_self.stack
new_stack.push(N3State::CollectionPossibleEnd)
new_stack.push(N3State::Path)
let final_self = { ..new_self, stack: new_stack }
Ok((final_self, N3State::Path, None))
}
}
// ===== State: CollectionPossibleEnd =====
///|
fn N3Recognizer::handle_collection_possible_end_m(
self : N3Recognizer,
token : LocatedTokenOrLineJump,
_context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info("Entering CollectionPossibleEnd with token: \{token}")
self.debug_logger.info("Token stack: \{@debug.to_string(self.stack)}")
let value = match self.terms.pop() {
Some(v) => v
None =>
return Err(
RuleRecognizerError::SyntaxError(
"Internal error: terms stack empty (value) in CollectionPossibleEnd",
self.last_range,
),
)
}
let old = match self.terms.pop() {
Some(o) => o
None =>
return Err(
RuleRecognizerError::SyntaxError(
"Internal error: terms stack empty (old) in CollectionPossibleEnd",
self.last_range,
),
)
}
let quad1 = self.quad(old, lwFIRST.as_n3term(), value)
let _output1 = Some(RdfOut::N3Quad(quad1))
if token
is LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation(")"), _)
) {
// 列表结束
let quad2 = self.quad(old, lwREST.as_n3term(), lwNIL.as_n3term())
let output2 = Some(RdfOut::N3Quad(quad2))
// 弹出 CollectionPossibleEnd
let new_stack = self.stack
if !new_stack.is_empty() &&
new_stack.last() == Some(N3State::CollectionPossibleEnd) {
let _ = new_stack.pop()
}
let next_state = new_stack.last().unwrap_or(N3State::N3Doc)
let new_self = { ..self, stack: new_stack }
// 注意:TransitionResult 只能返回一个 Output。如果有多个 Quad,通常由外层收集或合并。
// 这里返回最后一个,或者将第一个放入 results (如果 results 是可变引用,但这里是函数式风格)
// 假设外层会处理多个 outputs,或者我们只返回主要的。
// 为了简化,我们返回第二个 output,第一个可能需要通过其他方式记录,或者合并。
// 在此框架下,通常一次转换产生一个主要输出。
Ok((new_self, next_state, output2))
} else {
// 列表继续
let new_node = BlankNode::default()
let quad2 = self.quad(old, lwREST.as_n3term(), new_node.as_n3term())
let output2 = Some(RdfOut::N3Quad(quad2))
let new_terms = self.terms
new_terms.push(new_node.as_n3term()) // New current
new_terms.push(new_node.as_n3term()) // New previous (for next iteration)
let new_self = { ..self, terms: new_terms }
let new_stack = new_self.stack
new_stack.push(N3State::CollectionPossibleEnd)
new_stack.push(N3State::Path)
let final_self = { ..new_self, stack: new_stack }
Ok((final_self, N3State::Path, output2))
}
}
// ===== State: LiteralPossibleSuffix =====
///|
fn N3Recognizer::handle_literal_possible_suffix_m(
self : N3Recognizer,
value : String,
token : LocatedTokenOrLineJump,
_context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info(
"Entering LiteralPossibleSuffix(\{value}) with token: \{token}",
)
self.debug_logger.info("Token stack: \{@debug.to_string(self.stack)}")
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::LangTag(language~, direction~), _)
) => {
if direction is Some(_) {
return Err(
RuleRecognizerError::SyntaxError(
"rdf:dirLangString is not supported in N3",
self.last_range,
),
)
}
let literal = Literal::new_language_tagged_literal_unchecked(
value,
language.to_lower(),
)
let new_terms = self.terms
new_terms.push(literal.as_n3term())
let new_self = { ..self, terms: new_terms }
// 字面量处理完毕,弹出 LiteralPossibleSuffix,回到调用者
let new_stack = new_self.stack
if !new_stack.is_empty() &&
new_stack.last() == Some(N3State::LiteralPossibleSuffix(value~)) {
let _ = new_stack.pop()
}
let next_state = new_stack.last().unwrap_or(N3State::N3Doc)
let final_self = { ..new_self, stack: new_stack }
Ok((final_self, next_state, None))
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("^^"), _)
) =>
// 期待数据类型 IRI
Ok((self, N3State::LiteralExpectDatatype(value~), None))
_ => {
// 简单字面量
let literal = Literal::new_simple_literal(value)
let new_terms = self.terms
new_terms.push(literal.as_n3term())
let new_self = { ..self, terms: new_terms }
let new_stack = new_self.stack
if !new_stack.is_empty() &&
new_stack.last() == Some(N3State::LiteralPossibleSuffix(value~)) {
let _ = new_stack.pop()
}
let next_state = new_stack.last().unwrap_or(N3State::N3Doc)
let final_self = { ..new_self, stack: new_stack }
Ok((final_self, next_state, None))
}
}
}
// ===== State: LiteralExpectDatatype =====
///|
fn N3Recognizer::handle_literal_expect_datatype_m(
self : N3Recognizer,
value : String,
token : LocatedTokenOrLineJump,
context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info(
"Entering LiteralExpectDatatype(\{value}) with token: \{token}",
)
self.debug_logger.info("Token stack: \{@debug.to_string(self.stack)}")
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Iri(datatype), _)
) => {
let datatype_node = NamedNodeRef::new_unchecked(datatype)
let literal = LiteralRef::new_typed_literal(
datatype_node.into_datatype(value),
datatype_node,
)
let new_terms = self.terms
new_terms.push(literal.as_n3term())
let new_self = { ..self, terms: new_terms }
let new_stack = new_self.stack
if !new_stack.is_empty() &&
new_stack.last() == Some(N3State::LiteralExpectDatatype(value~)) {
let _ = new_stack.pop()
}
let next_state = new_stack.last().unwrap_or(N3State::N3Doc)
let final_self = { ..new_self, stack: new_stack }
Ok((final_self, next_state, None))
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(
N3Token::PrefixedName(prefix~, localx~, might_be_invalid_iri~),
_
)
) =>
match context {
RdfContext::N3RecognizerContext(ctx) =>
match
resolve_local_name(
prefix,
localx,
might_be_invalid_iri,
ctx.prefixes,
) {
Ok(datatype_node) => {
let literal = LiteralRef::new_typed_literal(
datatype_node.into_datatype(value),
datatype_node,
)
let new_terms = self.terms
new_terms.push(literal.as_n3term())
let new_self = { ..self, terms: new_terms }
let new_stack = new_self.stack
if !new_stack.is_empty() &&
new_stack.last() == Some(N3State::LiteralExpectDatatype(value~)) {
let _ = new_stack.pop()
}
let next_state = new_stack.last().unwrap_or(N3State::N3Doc)
let final_self = { ..new_self, stack: new_stack }
Ok((final_self, next_state, None))
}
Err(e) => Err(RuleRecognizerError::SyntaxError(e, self.last_range))
}
_ =>
Err(
RuleRecognizerError::SyntaxError(
"Invalid context for prefix resolution",
self.last_range,
),
)
}
_ =>
Err(
RuleRecognizerError::SyntaxError(
"Unexpected token in formula content",
self.last_range,
),
)
}
}
// ===== State: FormulaContent =====
///|
fn N3Recognizer::handle_formula_content_m(
self : N3Recognizer,
token : LocatedTokenOrLineJump,
_context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info("Entering FormulaContent with token: \{token}")
self.debug_logger.info("Token stack: \{@debug.to_string(self.stack)}")
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("}"), _)
) => {
// 公式结束
let ctx = match self.contexts.pop() {
Some(c) => c
None =>
return Err(
RuleRecognizerError::SyntaxError(
"Internal error: contexts stack empty in finish_formula",
self.last_range,
),
)
}
let new_terms = self.terms
new_terms.push(ctx.as_n3term())
let new_self = { ..self, terms: new_terms, contexts: self.contexts } // contexts already popped
// 清理栈:弹出 PathFollowUp 和 FormulaContentExpectDot (如果存在)
let new_stack = new_self.stack
if !new_stack.is_empty() &&
new_stack.last() == Some(N3State::PathFollowUp) {
let _ = new_stack.pop()
}
if !new_stack.is_empty() &&
new_stack.last() == Some(N3State::FormulaContentExpectDot) {
let _ = new_stack.pop()
}
// 弹出 FormulaContent 本身
if !new_stack.is_empty() &&
new_stack.last() == Some(N3State::FormulaContent) {
let _ = new_stack.pop()
}
let next_state = new_stack.last().unwrap_or(N3State::N3Doc)
let final_self = { ..new_self, stack: new_stack }
Ok((final_self, next_state, None))
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::PlainKeyword(k), _)
) if eq_ignore_ascii_case(k, "base") => {
let new_stack = self.stack
new_stack.push(N3State::FormulaContent)
new_stack.push(N3State::BaseExpectIri)
let new_self = { ..self, stack: new_stack }
Ok((new_self, N3State::BaseExpectIri, None))
}
_ => {
// 普通语句
let new_stack = self.stack
new_stack.push(N3State::FormulaContentExpectDot)
new_stack.push(N3State::Triples)
let new_self = { ..self, stack: new_stack }
Ok((new_self, N3State::Triples, None))
}
}
}
// ===== State: FormulaContentExpectDot =====
///|
fn N3Recognizer::handle_formula_content_expect_dot_m(
self : N3Recognizer,
token : LocatedTokenOrLineJump,
_context : RdfContext,
) -> TransitionResult[N3Recognizer, N3State, RdfOut] {
self.debug_logger.info(
"Entering FormulaContentExpectDot with token: \{token}",
)
self.debug_logger.info("Token stack: \{@debug.to_string(self.stack)}")
match token {
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("}"), _)
) => {
// 公式直接结束,没有点
let ctx = match self.contexts.pop() {
Some(c) => c
None =>
return Err(
RuleRecognizerError::SyntaxError(
"Internal error: contexts stack empty in finish_formula",
self.last_range,
),
)
}
let new_terms = self.terms
new_terms.push(ctx.as_n3term())
let new_self = { ..self, terms: new_terms, contexts: self.contexts }
let new_stack = new_self.stack
if !new_stack.is_empty() &&
new_stack.last() == Some(N3State::PathFollowUp) {
let _ = new_stack.pop()
}
if !new_stack.is_empty() &&
new_stack.last() == Some(N3State::FormulaContentExpectDot) {
let _ = new_stack.pop()
}
if !new_stack.is_empty() &&
new_stack.last() == Some(N3State::FormulaContent) {
let _ = new_stack.pop()
}
let next_state = new_stack.last().unwrap_or(N3State::N3Doc)
let final_self = { ..new_self, stack: new_stack }
Ok((final_self, next_state, None))
}
LocatedTokenOrLineJump::LocatedN3Token(
LocatedN3Token(N3Token::Punctuation("."), _)
) => {
// 语句结束,回到 FormulaContent
let new_stack = self.stack
if !new_stack.is_empty() &&
new_stack.last() == Some(N3State::FormulaContentExpectDot) {
let _ = new_stack.pop()
}
let next_state = new_stack.last().unwrap_or(N3State::N3Doc)
let new_self = { ..self, stack: new_stack }
Ok((new_self, next_state, None))
}
_ => {
let err = RuleRecognizerError::SyntaxError(
"A dot or '}' is expected at the end of N3 statements inside formula",
self.last_range,
)
Err(err)
}
}
}