1use std::fmt;
2use std::{cell::RefCell, collections::HashMap, rc::Rc};
3
4use std::cmp::Ordering;
5
6use crate::error::PoolResult;
7
8use super::node::Node;
9use super::node_type::NodeType;
10use super::schema::Schema;
11#[derive(Clone, PartialEq, Eq, Debug)]
12pub struct MatchEdge {
13 pub node_type: NodeType,
14 pub next: ContentMatch,
15}
16
17#[derive(Clone, PartialEq, Eq, Debug, Default)]
18pub struct ContentMatch {
19 pub next: Vec<MatchEdge>,
20 pub wrap_cache: Vec<Option<NodeType>>,
21 pub valid_end: bool,
22}
23impl Ord for ContentMatch {
24 fn cmp(
25 &self,
26 other: &Self,
27 ) -> Ordering {
28 let _ = other;
29 Ordering::Equal
30 }
31}
32impl PartialOrd for ContentMatch {
33 fn partial_cmp(
34 &self,
35 other: &Self,
36 ) -> Option<Ordering> {
37 Some(self.cmp(other))
38 }
39}
40
41impl ContentMatch {
42 pub fn parse(
43 str: String,
44 nodes: &HashMap<String, NodeType>,
45 ) -> ContentMatch {
46 let mut stream = TokenStream::new(str, nodes.clone());
47 if stream.next().is_none() {
48 return ContentMatch::empty();
49 }
50 let expr = parse_expr(&mut stream);
51
52 let arr = nfa(expr);
53
54 dfa(arr)
55 }
56 pub fn empty() -> Self {
57 ContentMatch {
58 next: Vec::new(),
59 wrap_cache: Vec::new(),
60 valid_end: true,
61 }
62 }
63
64 pub fn match_type(
65 &self,
66 node_type: &NodeType,
67 ) -> Option<&ContentMatch> {
68 self.next
69 .iter()
70 .find(|edge| &edge.node_type == node_type)
71 .map(|edge| &edge.next)
72 }
73
74 pub fn match_fragment(
75 &self,
76 frag: &[Node],
77 schema: &Schema,
78 ) -> Option<&ContentMatch> {
79 let mut current: &ContentMatch = self;
80
81 for content in frag.iter() {
82 if let Some(next) =
83 current.match_type(schema.nodes.get(&content.r#type).unwrap())
84 {
85 current = next;
86 } else {
87 return None;
89 }
90 }
91 Some(current)
92 }
93
94 pub fn fill(
104 &self,
105 after: &Vec<Node>,
106 to_end: bool,
107 schema: &Schema,
108 ) -> Option<Vec<String>> {
109 let mut seen: Vec<ContentMatch> = Vec::new();
110 seen.push(self.clone());
111 fn search(
112 seen: &mut Vec<ContentMatch>,
113 to_end: bool,
114 after: &Vec<Node>,
115 match_: &ContentMatch,
116 types: &mut Vec<String>,
117 schema: &Schema,
118 ) -> Option<Vec<String>> {
119 if let Some(finished) = match_.match_fragment(after, schema) {
121 if finished.valid_end || !to_end {
122 return Some(types.clone());
123 }
124 } else if !after.is_empty() {
125 return None;
127 }
128
129 for edge in &match_.next {
131 if !seen.contains(&edge.next) {
132 seen.push(edge.next.clone());
133 types.push(edge.node_type.name.clone());
134 if let Some(found) =
135 search(seen, to_end, after, &edge.next, types, schema)
136 {
137 return Some(found);
138 }
139 types.pop();
140 }
141 }
142 None
143 }
144
145 search(&mut seen, to_end, after, self, &mut Vec::new(), schema)
146 }
147
148 pub fn default_type(&self) -> Option<&NodeType> {
149 self.next
150 .iter()
151 .find(|edge| !edge.node_type.has_required_attrs())
152 .map(|edge| &edge.node_type)
153 }
154
155 pub fn compatible(
156 &self,
157 other: &ContentMatch,
158 ) -> bool {
159 for edge1 in &self.next {
160 for edge2 in &other.next {
161 if edge1.node_type == edge2.node_type {
162 return true;
163 }
164 }
165 }
166 false
167 }
168
169 pub fn edge_count(&self) -> usize {
170 self.next.len()
171 }
172
173 pub fn edge(
174 &self,
175 n: usize,
176 ) -> PoolResult<&MatchEdge> {
178 if n >= self.next.len() {
179 Err(anyhow::anyhow!(format!("{} 超出了 {}", n, self.next.len())))
180 } else {
181 Ok(&self.next[n])
182 }
183 }
184}
185impl fmt::Display for ContentMatch {
186 fn fmt(
187 &self,
188 f: &mut fmt::Formatter<'_>,
189 ) -> fmt::Result {
190 let mut seen = Vec::new();
191 fn scan(
192 m: &ContentMatch,
193 seen: &mut Vec<ContentMatch>,
194 ) {
195 seen.push(m.clone());
196 for edge in &m.next {
197 if !seen.iter().any(|s| s == &edge.next) {
198 scan(&edge.next, seen);
199 }
200 }
201 }
202 scan(self, &mut seen);
203
204 let str = seen
205 .iter()
206 .enumerate()
207 .map(|(i, m)| {
208 let mut out =
209 format!("{} ", if m.valid_end { i + 1 } else { i });
210 for (j, edge) in m.next.iter().enumerate() {
211 if j > 0 {
212 out.push_str(", ");
213 }
214 out.push_str(&format!(
215 "{}->{}",
216 edge.node_type.name,
217 seen.iter().position(|s| s == &edge.next).unwrap() + 1
218 ));
219 }
220 out
221 })
222 .collect::<Vec<_>>()
223 .join("\n");
224
225 write!(f, "{str}")
226 }
227}
228
229#[derive(Clone, PartialEq, Eq, Debug)]
230pub struct TokenStream {
231 pos: usize,
232 tokens: Vec<String>,
233 node_types: HashMap<String, NodeType>,
234 string: String,
235}
236
237impl TokenStream {
238 pub fn new(
239 string: String,
240 node_types: HashMap<String, NodeType>,
241 ) -> Self {
242 let mut tokens = Vec::new();
243 let mut current_token = String::new();
244 for c in string.chars() {
245 if c.is_whitespace() {
246 if !current_token.is_empty() {
248 tokens.push(current_token.clone());
249 current_token.clear(); }
251 } else if !c.is_alphanumeric() && c != '_' {
252 if !current_token.is_empty() {
254 tokens.push(current_token.clone());
255 current_token.clear(); }
257 tokens.push(c.to_string());
259 } else {
260 current_token.push(c);
262 }
263 }
264
265 if !current_token.is_empty() {
267 tokens.push(current_token);
268 }
269 TokenStream { pos: 0, tokens, node_types, string }
270 }
271
272 pub fn next(&self) -> Option<&str> {
273 self.tokens.get(self.pos).map(|s| s.as_str())
274 }
275
276 pub fn eat(
277 &mut self,
278 tok: &str,
279 ) -> bool {
280 if self.next() == Some(tok) {
281 self.pos += 1;
282 true
283 } else {
284 false
285 }
286 }
287
288 pub fn err(
289 &self,
290 str: &str,
291 ) -> ! {
292 panic!("{} (约束必须是 '{}')", str, self.string);
293 }
294}
295
296#[derive(Debug, Clone)]
297enum Expr {
298 Choice { exprs: Vec<Expr> },
299 Seq { exprs: Vec<Expr> },
300 Plus { expr: Box<Expr> },
301 Star { expr: Box<Expr> },
302 Opt { expr: Box<Expr> },
303 Range { min: usize, max: isize, expr: Box<Expr> },
304 Name { value: Box<NodeType> },
305}
306fn parse_expr(stream: &mut TokenStream) -> Expr {
307 let mut exprs = Vec::new();
308
309 loop {
310 exprs.push(parse_expr_seq(stream));
311 if !stream.eat("|") {
312 break;
313 }
314 }
315 if exprs.len() == 1 { exprs.pop().unwrap() } else { Expr::Choice { exprs } }
316}
317fn parse_expr_seq(stream: &mut TokenStream) -> Expr {
318 let mut exprs = Vec::new();
319
320 while let Some(next) = stream.next() {
321 if next == ")" || next == "|" {
322 break;
323 }
324 exprs.push(parse_expr_subscript(stream));
325 }
326 if exprs.len() == 1 { exprs.pop().unwrap() } else { Expr::Seq { exprs } }
327}
328
329fn parse_expr_subscript(stream: &mut TokenStream) -> Expr {
330 let mut expr = parse_expr_atom(stream);
331 loop {
332 if stream.eat("+") {
333 expr = Expr::Plus { expr: Box::new(expr) };
334 } else if stream.eat("*") {
335 expr = Expr::Star { expr: Box::new(expr) };
336 } else if stream.eat("?") {
337 expr = Expr::Opt { expr: Box::new(expr) };
338 } else if stream.eat("{") {
339 expr = parse_expr_range(stream, expr);
340 } else {
341 break;
342 }
343 }
344 expr
345}
346
347fn parse_num(stream: &mut TokenStream) -> usize {
348 let next = stream.next().unwrap();
349 if !next.chars().all(|c| c.is_ascii_digit()) {
350 stream.err(&format!("Expected number, got '{next}'"));
351 }
352 let result = next.parse().unwrap();
353 stream.pos += 1;
354 result
355}
356fn parse_expr_range(
357 stream: &mut TokenStream,
358 expr: Expr,
359) -> Expr {
360 let min = parse_num(stream);
361 let max = if stream.eat(",") {
362 if stream.next() != Some("}") { parse_num(stream) as isize } else { -1 }
363 } else {
364 min as isize
365 };
366 if !stream.eat("}") {
367 stream.err("Unclosed braced range");
368 }
369 Expr::Range { min, max, expr: Box::new(expr) }
370}
371
372fn resolve_name(
373 stream: &TokenStream,
374 name: &str,
375) -> Vec<NodeType> {
376 let types = &stream.node_types;
377 if let Some(type_) = types.get(name) {
378 return vec![type_.clone()];
379 }
380 let mut result = Vec::new();
381
382 for type_ in types.values() {
383 if type_.groups.contains(&name.to_string()) {
384 result.push(type_.clone());
385 }
386 }
387 if result.is_empty() {
388 stream.err(&format!("没找到类型 '{name}'"));
389 }
390 result
391}
392
393fn parse_expr_atom(stream: &mut TokenStream) -> Expr {
394 if stream.eat("(") {
395 let expr = parse_expr(stream);
396 if !stream.eat(")") {
397 stream.err("Missing closing paren");
398 }
399 expr
400 } else if let Some(next) = stream.next() {
401 if next.chars().all(|c| c.is_alphanumeric() || c == '_') {
402 let exprs: Vec<Expr> = resolve_name(stream, next)
403 .into_iter()
404 .map(|type_| Expr::Name { value: Box::new(type_) })
405 .collect();
406 stream.pos += 1;
407 if exprs.len() == 1 {
408 exprs.into_iter().next().unwrap()
409 } else {
410 Expr::Choice { exprs }
411 }
412 } else {
413 stream.err(&format!("Unexpected token '{next}'"));
414 }
415 } else {
416 stream.err("Unexpected end of input");
417 }
418}
419#[derive(Debug, Clone)]
420pub struct Edge {
421 term: Option<NodeType>,
422 to: Option<usize>,
423}
424fn dfa(nfa: Vec<Vec<Rc<RefCell<Edge>>>>) -> ContentMatch {
425 let mut labeled: HashMap<String, ContentMatch> = HashMap::new();
426
427 fn explore(
428 states: Vec<usize>,
429 nfa: &Vec<Vec<Rc<RefCell<Edge>>>>,
430 labeled: &mut HashMap<String, ContentMatch>,
431 ) -> ContentMatch {
432 let mut out: Vec<(NodeType, Vec<usize>)> = Vec::new();
433 for &node in &states {
434 for edge in &nfa[node] {
435 if edge.borrow().term.is_none() {
436 continue;
437 }
438 let term = edge.borrow().term.clone().unwrap();
439 let mut set: Option<&mut Vec<usize>> = None;
440
441 for (t, s) in &mut out {
442 if *t == term {
443 set = Some(s);
444 break;
445 }
446 }
447
448 if set.is_none() {
449 out.push((term.clone(), Vec::new()));
450 set = Some(&mut out.last_mut().unwrap().1);
451 }
452 for &node in &null_from(nfa, edge.borrow().to.unwrap_or(0)) {
453 set.as_mut().unwrap().push(node);
454 }
455 }
456 }
457 let mut state = ContentMatch {
458 next: Vec::new(),
459 wrap_cache: vec![],
460 valid_end: states.contains(&(nfa.len() - 1)),
461 };
462
463 let state_key =
464 states.iter().map(|&x| x.to_string()).collect::<Vec<_>>().join(",");
465 labeled.insert(state_key.clone(), state.clone());
466
467 for (term, states) in out {
468 let states_key = states
469 .iter()
470 .map(|&x| x.to_string())
471 .collect::<Vec<_>>()
472 .join(",");
473 let next_state = labeled
474 .get(&states_key)
475 .cloned()
476 .unwrap_or_else(|| explore(states, nfa, labeled));
477 labeled.insert(states_key, next_state.clone());
478 state.next.push(MatchEdge { node_type: term, next: next_state });
479 }
480
481 state
482 }
483
484 explore(null_from(&nfa, 0), &nfa, &mut labeled)
485}
486
487pub fn null_from(
488 nfa: &[Vec<Rc<RefCell<Edge>>>],
489 node: usize,
490) -> Vec<usize> {
491 let mut result = Vec::new();
492 fn scan(
493 nfa: &[Vec<Rc<RefCell<Edge>>>],
494 node: usize,
495 result: &mut Vec<usize>,
496 ) {
497 let edges = &nfa[node];
498 if edges.len() == 1 && edges[0].borrow().term.is_none() {
499 if let Some(to) = edges[0].borrow().to {
500 scan(nfa, to, result);
501 }
502 return;
503 }
504 if !result.contains(&node) {
505 result.push(node);
506 }
507 for edge in edges {
508 if edge.borrow().term.is_none() {
509 if let Some(to) = edge.borrow().to {
510 if !result.contains(&to) {
511 scan(nfa, to, result);
512 }
513 }
514 }
515 }
516 }
517
518 scan(nfa, node, &mut result);
519 result.sort();
520 result
521}
522fn nfa(expr: Expr) -> Vec<Vec<Rc<RefCell<Edge>>>> {
523 let mut nfa: Vec<Vec<Rc<RefCell<Edge>>>> = vec![vec![]];
524 connect(&mut compile(expr, 0, &mut nfa), node(&mut nfa));
525 nfa
526}
527fn node(nfa: &mut Vec<Vec<Rc<RefCell<Edge>>>>) -> usize {
528 nfa.push(vec![]);
529 nfa.len() - 1
530}
531
532fn edge(
533 from: usize,
534 to: Option<usize>,
535 term: Option<NodeType>,
536 nfa: &mut [Vec<Rc<RefCell<Edge>>>],
537) -> Rc<RefCell<Edge>> {
538 let edge =
539 Rc::new(RefCell::new(Edge { term, to: Option::from(to.unwrap_or(0)) }));
540 nfa[from].push(edge.clone());
541 edge.clone()
542}
543fn connect(
544 edges: &mut [Rc<RefCell<Edge>>],
545 to: usize,
546) {
547 for edge in edges {
548 edge.borrow_mut().to = Some(to);
549 }
550}
551fn compile(
552 expr: Expr,
553 from: usize,
554 nfa: &mut Vec<Vec<Rc<RefCell<Edge>>>>,
555) -> Vec<Rc<RefCell<Edge>>> {
556 match expr {
557 Expr::Choice { exprs } => exprs
558 .into_iter()
559 .flat_map(|expr| compile(expr, from, nfa))
560 .collect(),
561 Expr::Seq { exprs } => {
562 let mut cur = from;
563 let mut last_edges = Vec::new();
564 let exprs_len = exprs.len();
565
566 for (i, expr) in exprs.into_iter().enumerate() {
567 let next = if i == exprs_len - 1 { cur } else { node(nfa) };
568
569 let mut edges = compile(expr, cur, nfa);
570 if i < exprs_len - 1 {
571 connect(&mut edges, next);
572 cur = next;
573 } else {
574 last_edges = edges;
575 }
576 }
577
578 if last_edges.is_empty() {
579 vec![edge(cur, None, None, nfa)]
580 } else {
581 last_edges
582 }
583 },
584 Expr::Star { expr } => {
585 let loop_node = node(nfa);
586 edge(from, Some(loop_node), None, nfa);
587 let mut compiled_expr = compile(*expr, loop_node, nfa);
588 connect(&mut compiled_expr, loop_node);
589 vec![edge(loop_node, None, None, nfa)]
590 },
591 Expr::Plus { expr } => {
592 let loop_node = node(nfa);
593 connect(&mut compile(*expr.clone(), from, nfa), loop_node);
594 let mut compiled_expr = compile(*expr, loop_node, nfa);
595 connect(&mut compiled_expr, loop_node);
596 vec![edge(loop_node, None, None, nfa)]
597 },
598 Expr::Opt { expr } => {
599 let mut edges = vec![edge(from, None, None, nfa)];
600 edges.extend(compile(*expr, from, nfa));
601 edges
602 },
603 Expr::Range { expr, min, max } => {
604 let mut cur = from;
605 for _ in 0..min {
606 let next = node(nfa);
607 connect(&mut compile(*expr.clone(), cur, nfa), next);
608 cur = next;
609 }
610 if max == -1 {
611 connect(&mut compile(*expr, cur, nfa), cur);
612 } else {
613 for _ in min..max as usize {
614 let next = node(nfa);
615 edge(cur, Some(next), None, nfa);
616 connect(&mut compile(*expr.clone(), cur, nfa), next);
617 cur = next;
618 }
619 }
620 vec![edge(cur, None, None, nfa)]
621 },
622 Expr::Name { value } => {
623 vec![edge(from, None, Some((*value).clone()), nfa)]
624 },
625 }
626}
627
628#[cfg(test)]
629mod tests {
630 use super::*;
631 use crate::schema::{Schema, SchemaSpec};
632 use crate::node_type::NodeSpec;
633 use std::collections::HashMap;
634
635 #[test]
636 fn test_tablerow_plus_fill() {
637 let mut nodes = HashMap::new();
639
640 nodes.insert(
642 "table".to_string(),
643 NodeSpec {
644 content: Some("tablerow+".to_string()),
645 marks: None,
646 group: None,
647 desc: Some("表格节点".to_string()),
648 attrs: None,
649 },
650 );
651
652 nodes.insert(
654 "tablerow".to_string(),
655 NodeSpec {
656 content: Some("tablecell+".to_string()),
657 marks: None,
658 group: None,
659 desc: Some("表格行节点".to_string()),
660 attrs: None,
661 },
662 );
663
664 nodes.insert(
666 "tablecell".to_string(),
667 NodeSpec {
668 content: Some("text*".to_string()),
669 marks: None,
670 group: None,
671 desc: Some("表格单元格节点".to_string()),
672 attrs: None,
673 },
674 );
675
676 nodes.insert(
678 "text".to_string(),
679 NodeSpec {
680 content: None,
681 marks: None,
682 group: None,
683 desc: Some("文本节点".to_string()),
684 attrs: None,
685 },
686 );
687
688 let schema_spec = SchemaSpec {
689 nodes,
690 marks: HashMap::new(),
691 top_node: Some("table".to_string()),
692 };
693
694 let schema = Schema::compile(schema_spec).unwrap();
695 let table_type = schema.nodes.get("table").unwrap();
696
697 if let Some(content_match) = &table_type.content_match {
699 println!("Table content match: {content_match}");
700
701 let empty_content: Vec<Node> = vec![];
703 let result = content_match.fill(&empty_content, true, &schema);
704
705 println!("Fill result for empty content: {result:?}");
706
707 if let Some(needed_types) = result {
708 println!("成功!需要的节点类型数量: {}", needed_types.len());
709 for (i, type_name) in needed_types.iter().enumerate() {
710 println!(" 第{}个需要的节点类型: {}", i + 1, type_name);
711 }
712 } else {
713 println!("填充返回了 None");
714 }
715 }
716 }
717
718 #[test]
719 fn test_table_create_and_fill() {
720 let mut nodes = HashMap::new();
722
723 nodes.insert(
725 "table".to_string(),
726 NodeSpec {
727 content: Some("tablerow+".to_string()),
728 marks: None,
729 group: None,
730 desc: Some("表格节点".to_string()),
731 attrs: None,
732 },
733 );
734
735 nodes.insert(
737 "tablerow".to_string(),
738 NodeSpec {
739 content: Some("tablecell+".to_string()),
740 marks: None,
741 group: None,
742 desc: Some("表格行节点".to_string()),
743 attrs: None,
744 },
745 );
746
747 nodes.insert(
749 "tablecell".to_string(),
750 NodeSpec {
751 content: Some("text*".to_string()),
752 marks: None,
753 group: None,
754 desc: Some("表格单元格节点".to_string()),
755 attrs: None,
756 },
757 );
758
759 nodes.insert(
761 "text".to_string(),
762 NodeSpec {
763 content: None,
764 marks: None,
765 group: None,
766 desc: Some("文本节点".to_string()),
767 attrs: None,
768 },
769 );
770
771 let schema_spec = SchemaSpec {
772 nodes,
773 marks: HashMap::new(),
774 top_node: Some("table".to_string()),
775 };
776
777 let schema = Schema::compile(schema_spec).unwrap();
778 let table_type = schema.nodes.get("table").unwrap();
779
780 println!("=== 测试 create_and_fill ===");
782 let empty_content: Vec<Node> = vec![];
783 let result = table_type.create_and_fill(
784 None, None, empty_content, None, &schema, );
790
791 let (main_node, child_nodes) = result.into_parts();
792 println!("Main node: {main_node:?}");
793 println!("Child nodes count: {}", child_nodes.len());
794
795 for (i, child) in child_nodes.iter().enumerate() {
796 let (child_node, grandchildren) = child.clone().into_parts();
797 println!(
798 " Child {}: type={}, id={}",
799 i + 1,
800 child_node.r#type,
801 child_node.id
802 );
803 println!(" Grandchildren count: {}", grandchildren.len());
804 }
805
806 if !child_nodes.is_empty() {
808 let (first_child, _) = child_nodes[0].clone().into_parts();
809 println!("第一个子节点类型: {}", first_child.r#type);
810 } else {
811 println!("警告:没有创建任何子节点!");
812 }
813 }
814
815 #[test]
816 fn test_edge_cases() {
817 use crate::node::Node;
818
819 let mut nodes = HashMap::new();
821 nodes.insert(
822 "table".to_string(),
823 NodeSpec {
824 content: Some("tablerow+".to_string()),
825 marks: None,
826 group: None,
827 desc: Some("表格节点".to_string()),
828 attrs: None,
829 },
830 );
831 nodes.insert(
832 "tablerow".to_string(),
833 NodeSpec {
834 content: Some("tablecell+".to_string()),
835 marks: None,
836 group: None,
837 desc: Some("表格行节点".to_string()),
838 attrs: None,
839 },
840 );
841 nodes.insert(
842 "tablecell".to_string(),
843 NodeSpec {
844 content: Some("text*".to_string()),
845 marks: None,
846 group: None,
847 desc: Some("表格单元格节点".to_string()),
848 attrs: None,
849 },
850 );
851 nodes.insert(
852 "text".to_string(),
853 NodeSpec {
854 content: None,
855 marks: None,
856 group: None,
857 desc: Some("文本节点".to_string()),
858 attrs: None,
859 },
860 );
861
862 let schema_spec = SchemaSpec {
863 nodes,
864 marks: HashMap::new(),
865 top_node: Some("table".to_string()),
866 };
867 let schema = Schema::compile(schema_spec).unwrap();
868 let table_type = schema.nodes.get("table").unwrap();
869
870 println!("=== 边界情况测试 ===");
871
872 if table_type.content_match.is_none() {
874 println!("警告:table_type.content_match 为 None");
875 return;
876 }
877 let content_match = table_type.content_match.as_ref().unwrap();
878
879 let empty_content: Vec<Node> = vec![];
881 let matched = content_match.match_fragment(&empty_content, &schema);
882 println!("match_fragment result: {:?}", matched.is_some());
883
884 if let Some(matched_state) = matched {
885 println!("matched state valid_end: {}", matched_state.valid_end);
886
887 let fill_result = matched_state.fill(&empty_content, true, &schema);
889 println!("fill result: {:?}", fill_result.is_some());
890
891 if let Some(needed_types) = fill_result {
892 println!("需要的类型数量: {}", needed_types.len());
893 for type_name in &needed_types {
894 println!(" 需要的类型: {type_name}");
895 }
896 }
897 }
898
899 if let Some(matched_state) = matched {
901 let fill_result_no_end =
902 matched_state.fill(&empty_content, false, &schema);
903 println!(
904 "fill result (to_end=false): {:?}",
905 fill_result_no_end.is_some()
906 );
907 }
908 }
909
910 #[test]
911 fn test_block_choice_problem() {
912 let mut nodes = HashMap::new();
914
915 nodes.insert(
917 "block".to_string(),
918 NodeSpec {
919 content: Some("table paragraph list heading".to_string()),
920 marks: None,
921 group: None,
922 desc: Some("块级节点".to_string()),
923 attrs: None,
924 },
925 );
926
927 nodes.insert(
929 "table".to_string(),
930 NodeSpec {
931 content: Some("tablerow+".to_string()),
932 marks: None,
933 group: None,
934 desc: Some("表格节点".to_string()),
935 attrs: None,
936 },
937 );
938 nodes.insert(
939 "paragraph".to_string(),
940 NodeSpec {
941 content: Some("text*".to_string()),
942 marks: None,
943 group: None,
944 desc: Some("段落节点".to_string()),
945 attrs: None,
946 },
947 );
948 nodes.insert(
949 "list".to_string(),
950 NodeSpec {
951 content: Some("listitem+".to_string()),
952 marks: None,
953 group: None,
954 desc: Some("列表节点".to_string()),
955 attrs: None,
956 },
957 );
958 nodes.insert(
959 "heading".to_string(),
960 NodeSpec {
961 content: Some("text*".to_string()),
962 marks: None,
963 group: None,
964 desc: Some("标题节点".to_string()),
965 attrs: None,
966 },
967 );
968 nodes.insert(
969 "tablerow".to_string(),
970 NodeSpec {
971 content: Some("tablecell+".to_string()),
972 marks: None,
973 group: None,
974 desc: Some("表格行节点".to_string()),
975 attrs: None,
976 },
977 );
978 nodes.insert(
979 "tablecell".to_string(),
980 NodeSpec {
981 content: Some("text*".to_string()),
982 marks: None,
983 group: None,
984 desc: Some("表格单元格节点".to_string()),
985 attrs: None,
986 },
987 );
988 nodes.insert(
989 "listitem".to_string(),
990 NodeSpec {
991 content: Some("paragraph".to_string()),
992 marks: None,
993 group: None,
994 desc: Some("列表项节点".to_string()),
995 attrs: None,
996 },
997 );
998 nodes.insert(
999 "text".to_string(),
1000 NodeSpec {
1001 content: None,
1002 marks: None,
1003 group: None,
1004 desc: Some("文本节点".to_string()),
1005 attrs: None,
1006 },
1007 );
1008
1009 let schema_spec = SchemaSpec {
1010 nodes,
1011 marks: HashMap::new(),
1012 top_node: Some("block".to_string()),
1013 };
1014
1015 let schema = Schema::compile(schema_spec).unwrap();
1016 let block_type = schema.nodes.get("block").unwrap();
1017
1018 println!("=== 测试 Block 选择问题 ===");
1019
1020 if let Some(content_match) = &block_type.content_match {
1021 println!("Block content match: {content_match}");
1022
1023 let default_type = content_match.default_type();
1025 if let Some(def_type) = default_type {
1026 println!("默认类型: {}", def_type.name);
1027 println!(
1028 "默认类型是否有必须属性: {}",
1029 def_type.has_required_attrs()
1030 );
1031 } else {
1032 println!("没有默认类型");
1033 }
1034
1035 let empty_content: Vec<Node> = vec![];
1037 let result = content_match.fill(&empty_content, true, &schema);
1038
1039 println!("Fill result: {:?}", result.is_some());
1040 if let Some(needed_types) = result {
1041 println!("需要的类型数量: {}", needed_types.len());
1042 for (i, type_name) in needed_types.iter().enumerate() {
1043 println!(" 第{}个需要的节点类型: {}", i + 1, type_name);
1044 }
1045 }
1046
1047 println!("=== 测试 Block create_and_fill ===");
1049 let result =
1050 block_type.create_and_fill(None, None, vec![], None, &schema);
1051
1052 let (main_node, child_nodes) = result.into_parts();
1053 println!("Main node type: {}", main_node.r#type);
1054 println!("Child nodes count: {}", child_nodes.len());
1055
1056 for (i, child) in child_nodes.iter().enumerate() {
1057 let (child_node, grandchildren) = child.clone().into_parts();
1058 println!(" Child {}: type={}", i + 1, child_node.r#type);
1059 if child_node.r#type == "table" {
1060 println!(
1061 " Table 的 grandchildren count: {}",
1062 grandchildren.len()
1063 );
1064 for (j, grandchild) in grandchildren.iter().enumerate() {
1065 let (gc_node, _) = grandchild.clone().into_parts();
1066 println!(
1067 " Grandchild {}: type={}",
1068 j + 1,
1069 gc_node.r#type
1070 );
1071 }
1072 }
1073 }
1074 }
1075 }
1076
1077 #[test]
1078 fn test_sequence_with_existing_nodes() {
1079 use crate::node::Node;
1080 use crate::attrs::Attrs;
1081
1082 let mut nodes = HashMap::new();
1084 nodes.insert(
1085 "block".to_string(),
1086 NodeSpec {
1087 content: Some("table paragraph".to_string()), marks: None,
1089 group: None,
1090 desc: Some("块级节点".to_string()),
1091 attrs: None,
1092 },
1093 );
1094 nodes.insert(
1095 "table".to_string(),
1096 NodeSpec {
1097 content: Some("tablerow+".to_string()),
1098 marks: None,
1099 group: None,
1100 desc: Some("表格节点".to_string()),
1101 attrs: None,
1102 },
1103 );
1104 nodes.insert(
1105 "paragraph".to_string(),
1106 NodeSpec {
1107 content: Some("text*".to_string()),
1108 marks: None,
1109 group: None,
1110 desc: Some("段落节点".to_string()),
1111 attrs: None,
1112 },
1113 );
1114 nodes.insert(
1115 "tablerow".to_string(),
1116 NodeSpec {
1117 content: Some("tablecell+".to_string()),
1118 marks: None,
1119 group: None,
1120 desc: Some("表格行节点".to_string()),
1121 attrs: None,
1122 },
1123 );
1124 nodes.insert(
1125 "tablecell".to_string(),
1126 NodeSpec {
1127 content: Some("text*".to_string()),
1128 marks: None,
1129 group: None,
1130 desc: Some("表格单元格节点".to_string()),
1131 attrs: None,
1132 },
1133 );
1134 nodes.insert(
1135 "text".to_string(),
1136 NodeSpec {
1137 content: None,
1138 marks: None,
1139 group: None,
1140 desc: Some("文本节点".to_string()),
1141 attrs: None,
1142 },
1143 );
1144
1145 let schema_spec = SchemaSpec {
1146 nodes,
1147 marks: HashMap::new(),
1148 top_node: Some("block".to_string()),
1149 };
1150 let schema = Schema::compile(schema_spec).unwrap();
1151 let block_type = schema.nodes.get("block").unwrap();
1152
1153 println!("=== 测试序列中已存在节点的情况 ===");
1154
1155 let existing_table = Node::new(
1157 "existing_table_123",
1158 "table".to_string(),
1159 Attrs::default(),
1160 vec!["existing_row_456".into()],
1161 vec![],
1162 );
1163
1164 let existing_paragraph = Node::new(
1166 "existing_para_789",
1167 "paragraph".to_string(),
1168 Attrs::default(),
1169 vec!["existing_text_000".into()],
1170 vec![],
1171 );
1172
1173 let existing_content = vec![existing_table, existing_paragraph];
1174
1175 println!("传入的现有内容:");
1176 for (i, node) in existing_content.iter().enumerate() {
1177 println!(
1178 " 第{}个现有节点: type={}, id={}, content={:?}",
1179 i + 1,
1180 node.r#type,
1181 node.id,
1182 node.content
1183 );
1184 }
1185
1186 let result = block_type.create_and_fill(
1188 None,
1189 None,
1190 existing_content,
1191 None,
1192 &schema,
1193 );
1194
1195 let (main_node, child_nodes) = result.into_parts();
1196 println!(
1197 "Main node: type={}, content={:?}",
1198 main_node.r#type, main_node.content
1199 );
1200 println!("Child nodes count: {}", child_nodes.len());
1201
1202 for (i, child) in child_nodes.iter().enumerate() {
1203 let (child_node, grandchildren) = child.clone().into_parts();
1204 println!(
1205 " Child {}: type={}, id={}",
1206 i + 1,
1207 child_node.r#type,
1208 child_node.id
1209 );
1210 println!(" Content: {:?}", child_node.content);
1211 println!(" Grandchildren count: {}", grandchildren.len());
1212
1213 for (j, grandchild) in grandchildren.iter().enumerate() {
1214 let (gc_node, _) = grandchild.clone().into_parts();
1215 println!(
1216 " Grandchild {}: type={}, id={}",
1217 j + 1,
1218 gc_node.r#type,
1219 gc_node.id
1220 );
1221 }
1222 }
1223 }
1224
1225 #[test]
1226 fn test_table_creation_step_by_step() {
1227 let mut nodes = HashMap::new();
1229
1230 nodes.insert(
1231 "table".to_string(),
1232 NodeSpec {
1233 content: Some("tablerow+".to_string()),
1234 marks: None,
1235 group: None,
1236 desc: Some("表格节点".to_string()),
1237 attrs: None,
1238 },
1239 );
1240 nodes.insert(
1241 "tablerow".to_string(),
1242 NodeSpec {
1243 content: Some("tablecell+".to_string()),
1244 marks: None,
1245 group: None,
1246 desc: Some("表格行节点".to_string()),
1247 attrs: None,
1248 },
1249 );
1250 nodes.insert(
1251 "tablecell".to_string(),
1252 NodeSpec {
1253 content: Some("text*".to_string()),
1254 marks: None,
1255 group: None,
1256 desc: Some("表格单元格节点".to_string()),
1257 attrs: None,
1258 },
1259 );
1260 nodes.insert(
1261 "text".to_string(),
1262 NodeSpec {
1263 content: None,
1264 marks: None,
1265 group: None,
1266 desc: Some("文本节点".to_string()),
1267 attrs: None,
1268 },
1269 );
1270
1271 let schema_spec = SchemaSpec {
1272 nodes,
1273 marks: HashMap::new(),
1274 top_node: Some("table".to_string()),
1275 };
1276 let schema = Schema::compile(schema_spec).unwrap();
1277 let table_type = schema.nodes.get("table").unwrap();
1278
1279 println!("=== 逐步诊断 Table 创建过程 ===");
1280
1281 println!("第1步:检查 table 的 content_match");
1283 if let Some(content_match) = &table_type.content_match {
1284 println!(" ✅ content_match 存在");
1285 println!(" content_match: {content_match}");
1286 } else {
1287 println!(" ❌ content_match 不存在");
1288 return;
1289 }
1290
1291 println!("第2步:测试 match_fragment");
1293 let empty_content: Vec<Node> = vec![];
1294 let content_match = table_type.content_match.as_ref().unwrap();
1295
1296 let matched = content_match.match_fragment(&empty_content, &schema);
1297 if let Some(matched_state) = matched {
1298 println!(" ✅ match_fragment 成功");
1299 println!(" matched state valid_end: {}", matched_state.valid_end);
1300 } else {
1301 println!(" ❌ match_fragment 返回 None");
1302 return;
1303 }
1304
1305 println!("第3步:测试 fill");
1307 let matched_state = matched.unwrap();
1308 let fill_result = matched_state.fill(&empty_content, true, &schema);
1309
1310 if let Some(needed_types) = fill_result {
1311 println!(" ✅ fill 成功,需要的类型数量: {}", needed_types.len());
1312 for (i, type_name) in needed_types.iter().enumerate() {
1313 println!(" 第{}个需要的类型: {}", i + 1, type_name);
1314 }
1315 } else {
1316 println!(" ❌ fill 返回 None");
1317 return;
1318 }
1319
1320 println!("第4步:测试完整的 create_and_fill");
1322 let result = table_type.create_and_fill(
1323 None,
1324 None,
1325 vec![], None,
1327 &schema,
1328 );
1329
1330 let (main_node, child_nodes) = result.into_parts();
1331 println!(" Main table node:");
1332 println!(" ID: {}", main_node.id);
1333 println!(" Content IDs: {:?}", main_node.content);
1334 println!(" Child nodes count: {}", child_nodes.len());
1335
1336 if child_nodes.is_empty() {
1337 println!(" ❌ 没有创建子节点!");
1338 } else {
1339 for (i, child) in child_nodes.iter().enumerate() {
1340 let (child_node, grandchildren) = child.clone().into_parts();
1341 println!(
1342 " Child {}: type={}, id={}",
1343 i + 1,
1344 child_node.r#type,
1345 child_node.id
1346 );
1347 println!(" Content IDs: {:?}", child_node.content);
1348 println!(" Grandchildren count: {}", grandchildren.len());
1349
1350 if child_node.r#type == "tablerow" && grandchildren.is_empty() {
1351 println!(" ❌ tablerow 没有创建 tablecell 子节点!");
1352 }
1353
1354 for (j, grandchild) in grandchildren.iter().enumerate() {
1355 let (gc_node, great_grandchildren) =
1356 grandchild.clone().into_parts();
1357 println!(
1358 " Grandchild {}: type={}, id={}",
1359 j + 1,
1360 gc_node.r#type,
1361 gc_node.id
1362 );
1363 println!(" Content IDs: {:?}", gc_node.content);
1364 println!(
1365 " Great-grandchildren count: {}",
1366 great_grandchildren.len()
1367 );
1368 }
1369 }
1370 }
1371
1372 println!("第5步:单独测试 tablerow 的创建");
1374 let tablerow_type = schema.nodes.get("tablerow").unwrap();
1375 let tablerow_result = tablerow_type.create_and_fill(
1376 None,
1377 None,
1378 vec![], None,
1380 &schema,
1381 );
1382
1383 let (tr_node, tr_children) = tablerow_result.into_parts();
1384 println!(" Tablerow node:");
1385 println!(" ID: {}", tr_node.id);
1386 println!(" Content IDs: {:?}", tr_node.content);
1387 println!(" Children count: {}", tr_children.len());
1388
1389 if tr_children.is_empty() {
1390 println!(" ❌ tablerow 没有创建 tablecell 子节点!");
1391 } else {
1392 for (i, child) in tr_children.iter().enumerate() {
1393 let (child_node, _) = child.clone().into_parts();
1394 println!(
1395 " Child {}: type={}, id={}",
1396 i + 1,
1397 child_node.r#type,
1398 child_node.id
1399 );
1400 }
1401 }
1402 }
1403
1404 #[test]
1405 fn test_sequence_table_problem() {
1406 let mut nodes = HashMap::new();
1408
1409 nodes.insert(
1411 "block".to_string(),
1412 NodeSpec {
1413 content: Some("table paragraph list heading".to_string()),
1414 marks: None,
1415 group: None,
1416 desc: Some("块级节点".to_string()),
1417 attrs: None,
1418 },
1419 );
1420
1421 nodes.insert(
1423 "table".to_string(),
1424 NodeSpec {
1425 content: Some("tablerow+".to_string()),
1426 marks: None,
1427 group: None,
1428 desc: Some("表格节点".to_string()),
1429 attrs: None,
1430 },
1431 );
1432 nodes.insert(
1433 "paragraph".to_string(),
1434 NodeSpec {
1435 content: Some("text*".to_string()),
1436 marks: None,
1437 group: None,
1438 desc: Some("段落节点".to_string()),
1439 attrs: None,
1440 },
1441 );
1442 nodes.insert(
1443 "list".to_string(),
1444 NodeSpec {
1445 content: Some("listitem+".to_string()),
1446 marks: None,
1447 group: None,
1448 desc: Some("列表节点".to_string()),
1449 attrs: None,
1450 },
1451 );
1452 nodes.insert(
1453 "heading".to_string(),
1454 NodeSpec {
1455 content: Some("text*".to_string()),
1456 marks: None,
1457 group: None,
1458 desc: Some("标题节点".to_string()),
1459 attrs: None,
1460 },
1461 );
1462 nodes.insert(
1463 "tablerow".to_string(),
1464 NodeSpec {
1465 content: Some("tablecell+".to_string()),
1466 marks: None,
1467 group: None,
1468 desc: Some("表格行节点".to_string()),
1469 attrs: None,
1470 },
1471 );
1472 nodes.insert(
1473 "tablecell".to_string(),
1474 NodeSpec {
1475 content: Some("text*".to_string()),
1476 marks: None,
1477 group: None,
1478 desc: Some("表格单元格节点".to_string()),
1479 attrs: None,
1480 },
1481 );
1482 nodes.insert(
1483 "listitem".to_string(),
1484 NodeSpec {
1485 content: Some("paragraph".to_string()),
1486 marks: None,
1487 group: None,
1488 desc: Some("列表项节点".to_string()),
1489 attrs: None,
1490 },
1491 );
1492 nodes.insert(
1493 "text".to_string(),
1494 NodeSpec {
1495 content: None,
1496 marks: None,
1497 group: None,
1498 desc: Some("文本节点".to_string()),
1499 attrs: None,
1500 },
1501 );
1502
1503 let schema_spec = SchemaSpec {
1504 nodes,
1505 marks: HashMap::new(),
1506 top_node: Some("block".to_string()),
1507 };
1508
1509 let schema = Schema::compile(schema_spec).unwrap();
1510 let block_type = schema.nodes.get("block").unwrap();
1511
1512 println!("=== 测试序列表达式中的 Table 问题 ===");
1513
1514 let result = block_type.create_and_fill(
1516 None,
1517 None,
1518 vec![], None,
1520 &schema,
1521 );
1522
1523 let (main_node, child_nodes) = result.into_parts();
1524 println!("Block 节点:");
1525 println!(" ID: {}", main_node.id);
1526 println!(" Content IDs: {:?}", main_node.content);
1527 println!(" 子节点数量: {}", child_nodes.len());
1528
1529 for (i, child) in child_nodes.iter().enumerate() {
1531 let (child_node, grandchildren) = child.clone().into_parts();
1532 println!(
1533 " 子节点 {}: type={}, id={}",
1534 i + 1,
1535 child_node.r#type,
1536 child_node.id
1537 );
1538 println!(" Content IDs: {:?}", child_node.content);
1539 println!(" 孙节点数量: {}", grandchildren.len());
1540
1541 if child_node.r#type == "table" {
1543 println!(" 📋 这是 Table 节点:");
1544
1545 if child_node.content.is_empty() {
1547 println!(" ❌ Table 节点的 content IDs 是空的!");
1548 } else {
1549 println!(
1550 " ✅ Table 节点包含 content IDs: {:?}",
1551 child_node.content
1552 );
1553 }
1554
1555 if grandchildren.is_empty() {
1557 println!(
1558 " ❌ Table 节点没有创建任何孙节点(tablerow)!"
1559 );
1560 } else {
1561 println!(
1562 " ✅ Table 节点创建了 {} 个孙节点:",
1563 grandchildren.len()
1564 );
1565 for (j, grandchild) in grandchildren.iter().enumerate() {
1566 let (gc_node, great_grandchildren) =
1567 grandchild.clone().into_parts();
1568 println!(
1569 " 孙节点 {}: type={}, id={}",
1570 j + 1,
1571 gc_node.r#type,
1572 gc_node.id
1573 );
1574 println!(
1575 " Content IDs: {:?}",
1576 gc_node.content
1577 );
1578
1579 if gc_node.r#type == "tablerow" {
1581 if great_grandchildren.is_empty() {
1582 println!(
1583 " ❌ tablerow 没有创建 tablecell 子节点!"
1584 );
1585
1586 println!(
1588 " 🔍 调试 tablerow 填充过程:"
1589 );
1590 let tablerow_type =
1591 schema.nodes.get("tablerow").unwrap();
1592 if let Some(tr_content_match) =
1593 &tablerow_type.content_match
1594 {
1595 println!(
1596 " tablerow content_match: {tr_content_match}"
1597 );
1598
1599 let empty_content: Vec<Node> = vec![];
1600 let tr_matched = tr_content_match
1601 .match_fragment(
1602 &empty_content,
1603 &schema,
1604 );
1605 if let Some(tr_matched_state) = tr_matched {
1606 println!(
1607 " tablerow match_fragment 成功"
1608 );
1609 println!(
1610 " tablerow matched state valid_end: {}",
1611 tr_matched_state.valid_end
1612 );
1613
1614 let tr_fill_result = tr_matched_state
1615 .fill(
1616 &empty_content,
1617 true,
1618 &schema,
1619 );
1620 if let Some(tr_needed_types) =
1621 tr_fill_result
1622 {
1623 println!(
1624 " tablerow 需要的类型数量: {}",
1625 tr_needed_types.len()
1626 );
1627 for (k, type_name) in
1628 tr_needed_types
1629 .iter()
1630 .enumerate()
1631 {
1632 println!(
1633 " 需要的类型 {}: {}",
1634 k + 1,
1635 type_name
1636 );
1637 }
1638 } else {
1639 println!(
1640 " ❌ tablerow fill 返回 None"
1641 );
1642 }
1643 } else {
1644 println!(
1645 " ❌ tablerow match_fragment 返回 None"
1646 );
1647 }
1648 } else {
1649 println!(
1650 " ❌ tablerow 没有 content_match"
1651 );
1652 }
1653 } else {
1654 println!(
1655 " ✅ tablerow 创建了 {} 个 tablecell",
1656 great_grandchildren.len()
1657 );
1658 for (k, ggc) in
1659 great_grandchildren.iter().enumerate()
1660 {
1661 let (ggc_node, _) =
1662 ggc.clone().into_parts();
1663 println!(
1664 " 曾孙节点 {}: type={}, id={}",
1665 k + 1,
1666 ggc_node.r#type,
1667 ggc_node.id
1668 );
1669 }
1670 }
1671 }
1672 }
1673 }
1674 }
1675 }
1676
1677 println!("\n=== 对比:单独创建 Table 节点 ===");
1679 let table_type = schema.nodes.get("table").unwrap();
1680 let standalone_table =
1681 table_type.create_and_fill(None, None, vec![], None, &schema);
1682
1683 let (st_node, st_children) = standalone_table.into_parts();
1684 println!("单独的 Table 节点:");
1685 println!(" ID: {}", st_node.id);
1686 println!(" Content IDs: {:?}", st_node.content);
1687 println!(" 子节点数量: {}", st_children.len());
1688
1689 for (i, child) in st_children.iter().enumerate() {
1690 let (child_node, grandchildren) = child.clone().into_parts();
1691 println!(
1692 " 子节点 {}: type={}, id={}",
1693 i + 1,
1694 child_node.r#type,
1695 child_node.id
1696 );
1697 println!(" 孙节点数量: {}", grandchildren.len());
1698 }
1699
1700 println!("\n=== 额外调试:单独创建 tablerow 节点 ===");
1702 let tablerow_type = schema.nodes.get("tablerow").unwrap();
1703 let standalone_tablerow =
1704 tablerow_type.create_and_fill(None, None, vec![], None, &schema);
1705
1706 let (str_node, str_children) = standalone_tablerow.into_parts();
1707 println!("单独的 tablerow 节点:");
1708 println!(" ID: {}", str_node.id);
1709 println!(" Content IDs: {:?}", str_node.content);
1710 println!(" 子节点数量: {}", str_children.len());
1711
1712 for (i, child) in str_children.iter().enumerate() {
1713 let (child_node, _) = child.clone().into_parts();
1714 println!(
1715 " 子节点 {}: type={}, id={}",
1716 i + 1,
1717 child_node.r#type,
1718 child_node.id
1719 );
1720 }
1721 }
1722}