///|
struct N3Recognizer {
  stack : Array[N3State]
  terms : Array[N3Term]
  predicates : Array[Predicate]
  contexts : Array[BlankNode]
  mut debug_logger : &DebugLogger
  mut last_range : Range
  errors : Array[RuleRecognizerError]
}

///|
struct N3RecognizerContext {
  lexer_options : LexerOptions
  prefixes : Map[String, Iri]
}

///|
pub fn N3RecognizerContext::as_ctx(self : N3RecognizerContext) -> RdfContext {
  RdfContext::N3RecognizerContext(self)
}

///|
pub impl RuleRecognizer for N3Recognizer with fn error_recovery_state(
  self : N3Recognizer,
) -> N3Recognizer {
  self.stack.clear()
  self.terms.clear()
  self.predicates.clear()
  self.contexts.clear()
  self
}

///|
pub impl RuleRecognizer for N3Recognizer with fn[DL : DebugLogger] debug_logger(
  self : N3Recognizer,
  logger : DL,
) {
  self.debug_logger = logger
}

///|
pub impl RuleRecognizer for N3Recognizer with fn recognize_end(
  self : N3Recognizer,
  _state : RdfContext,
  _results : Array[RdfOut],
) -> Unit {
  match self.stack {
    [] | [N3State::N3Doc] => ()
    _ =>
      self.errors.push(
        RuleRecognizerError::SyntaxError("Unexpected end", Range::default()),
      )
  }
}

///|
pub impl RuleRecognizer for N3Recognizer with fn lexer_options(
  context : RdfContext,
) -> LexerOptions? {
  match context {
    N3RecognizerContext(context) => Some(context.lexer_options)
    _ => None
  }
}

///|
pub fn N3Recognizer::new_parser(
  data : Array[Byte],
  is_ending : Bool,
  unchecked : Bool,
  base_iri : Iri?,
  prefixes : Map[String, Iri],
  debug_logger? : &DebugLogger = make_mute_logger(),
) -> Parser[RdfLexer, N3Recognizer] {
  Parser::Parser(
    Lexer::Lexer(
      RdfLexer::RdfLexer(RdfLexerMode::N3, unchecked),
      data,
      is_ending,
      MIN_BUFFER_SIZE,
      MAX_BUFFER_SIZE,
      Some(b"#"),
      0,
      0,
    ),
    {
      stack: [N3State::N3Doc],
      terms: [],
      predicates: [],
      contexts: [],
      debug_logger,
      last_range: Range::default(),
      errors: [],
    },
    // 修复点:使用 RdfContext ::N3RecognizerContext 包装记录
    RdfContext::N3RecognizerContext({ lexer_options: { base_iri, }, prefixes }),
  )
}

///|
fn N3Recognizer::error(self : N3Recognizer, msg : String) -> N3Recognizer {
  self.errors.push(RuleRecognizerError::SyntaxError(msg, self.last_range))
  self.stack.clear()

  self
}

///|
fn N3Recognizer::quad(
  self : N3Recognizer,
  subject : N3Term,
  predicate : N3Term,
  object : N3Term,
) -> N3Quad {
  {
    subject,
    predicate,
    object,
    graph_name: self.contexts
    .last()
    .map_or(GraphName::DefaultGraph, fn(g) { GraphName::BlankNode(g) }),
  }
}

///|
enum N3State {
  N3Doc
  N3DocExpectDot
  BaseExpectIri
  PrefixExpectPrefix
  PrefixExpectIri(name~ : String)
  Triples
  TriplesMiddle
  TriplesEnd
  PredicateObjectList
  PredicateObjectListEnd
  PredicateObjectListPossibleContinuation
  ObjectsList
  ObjectsListEnd
  Verb
  AfterRegularVerb
  AfterInvertedVerb
  AfterVerbIs
  Path
  PathFollowUp
  PathAfterIndicator(is_inverse~ : Bool)
  PathItem
  PropertyListMiddle
  PropertyListEnd
  IriPropertyList
  CollectionBeginning
  CollectionPossibleEnd
  LiteralPossibleSuffix(value~ : String)
  LiteralExpectDatatype(value~ : String)
  FormulaContent
  FormulaContentExpectDot
} derive(Debug, Eq, Hash)

///|
impl StateWrapper for N3State with fn as_state_enum(self : N3State) -> RdfState {
  RdfState::N3State(self)
}

///|
impl Show for N3State with fn output(self, logger : &Logger) -> Unit {
  match self {
    N3State::N3Doc => logger.write("N3Doc")
    N3State::N3DocExpectDot => logger.write("N3DocExpectDot")
    N3State::BaseExpectIri => logger.write("BaseExpectIri")
    N3State::PrefixExpectPrefix => logger.write("PrefixExpectPrefix")
    N3State::PrefixExpectIri(name~) => logger.write("PrefixExpectIri(\{name})")
    N3State::Triples => logger.write("Triples")
    N3State::TriplesMiddle => logger.write("TriplesMiddle")
    N3State::TriplesEnd => logger.write("TriplesEnd")
    N3State::PredicateObjectList => logger.write("PredicateObjectList")
    N3State::PredicateObjectListEnd => logger.write("PredicateObjectListEnd")
    N3State::PredicateObjectListPossibleContinuation =>
      logger.write("PredicateObjectListPossibleContinuation")
    N3State::ObjectsList => logger.write("ObjectsList")
    N3State::ObjectsListEnd => logger.write("ObjectsListEnd")
    N3State::Verb => logger.write("Verb")
    N3State::AfterRegularVerb => logger.write("AfterRegularVerb")
    N3State::AfterInvertedVerb => logger.write("AfterInvertedVerb")
    N3State::AfterVerbIs => logger.write("AfterVerbIs")
    N3State::Path => logger.write("Path")
    N3State::PathFollowUp => logger.write("PathFollowUp")
    N3State::PathAfterIndicator(is_inverse~) => {
      let desc = if is_inverse { "inverse" } else { "regular" }
      logger.write("Path After \{desc} Indicator")
    }
    N3State::PathItem => logger.write("PathItem")
    N3State::PropertyListMiddle => logger.write("PropertyListMiddle")
    N3State::PropertyListEnd => logger.write("PropertyListEnd")
    N3State::IriPropertyList => logger.write("IriPropertyList")
    N3State::CollectionBeginning => logger.write("CollectionBeginning")
    N3State::CollectionPossibleEnd => logger.write("CollectionPossibleEnd")
    N3State::LiteralPossibleSuffix(value~) =>
      logger.write("LiteralPossibleSuffix(\{value})")
    N3State::LiteralExpectDatatype(value~) =>
      logger.write("LiteralExpectDatatype(\{value})")
    N3State::FormulaContent => logger.write("FormulaContent")
    N3State::FormulaContentExpectDot => logger.write("FormulaContentExpectDot")
  }
}