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() {
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: 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()) {
402 let exprs: Vec<Expr> = resolve_name(stream, next)
403 .into_iter()
404 .map(|type_| Expr::Name { value: 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), nfa)]
624 },
625 }
626}
627
628#[cfg(test)]
629mod tests {
630 use super::*;
631 use crate::schema::{AttributeSpec, Schema, SchemaSpec};
632 use crate::node_type::NodeSpec;
633 use std::collections::HashMap;
634 use serde_json::Value;
635
636 #[test]
637 fn test_tablerow_plus_fill() {
638 let mut nodes = HashMap::new();
640
641 nodes.insert(
643 "table".to_string(),
644 NodeSpec {
645 content: Some("tablerow+".to_string()),
646 marks: None,
647 group: None,
648 desc: Some("表格节点".to_string()),
649 attrs: None,
650 },
651 );
652
653 nodes.insert(
655 "tablerow".to_string(),
656 NodeSpec {
657 content: Some("tablecell+".to_string()),
658 marks: None,
659 group: None,
660 desc: Some("表格行节点".to_string()),
661 attrs: None,
662 },
663 );
664
665 nodes.insert(
667 "tablecell".to_string(),
668 NodeSpec {
669 content: Some("text*".to_string()),
670 marks: None,
671 group: None,
672 desc: Some("表格单元格节点".to_string()),
673 attrs: None,
674 },
675 );
676
677 nodes.insert(
679 "text".to_string(),
680 NodeSpec {
681 content: None,
682 marks: None,
683 group: None,
684 desc: Some("文本节点".to_string()),
685 attrs: None,
686 },
687 );
688
689 let schema_spec = SchemaSpec {
690 nodes,
691 marks: HashMap::new(),
692 top_node: Some("table".to_string()),
693 };
694
695 let schema = Schema::compile(schema_spec).unwrap();
696 let table_type = schema.nodes.get("table").unwrap();
697
698 if let Some(content_match) = &table_type.content_match {
700 println!("Table content match: {}", content_match);
701
702 let empty_content: Vec<Node> = vec![];
704 let result = content_match.fill(&empty_content, true, &schema);
705
706 println!("Fill result for empty content: {:?}", result);
707
708 if let Some(needed_types) = result {
709 println!("成功!需要的节点类型数量: {}", needed_types.len());
710 for (i, type_name) in needed_types.iter().enumerate() {
711 println!(" 第{}个需要的节点类型: {}", i + 1, type_name);
712 }
713 } else {
714 println!("填充返回了 None");
715 }
716 }
717 }
718
719 #[test]
720 fn test_table_create_and_fill() {
721 use crate::node_type::NodeType;
722
723 let mut nodes = HashMap::new();
725
726 nodes.insert(
728 "table".to_string(),
729 NodeSpec {
730 content: Some("tablerow+".to_string()),
731 marks: None,
732 group: None,
733 desc: Some("表格节点".to_string()),
734 attrs: None,
735 },
736 );
737
738 nodes.insert(
740 "tablerow".to_string(),
741 NodeSpec {
742 content: Some("tablecell+".to_string()),
743 marks: None,
744 group: None,
745 desc: Some("表格行节点".to_string()),
746 attrs: None,
747 },
748 );
749
750 nodes.insert(
752 "tablecell".to_string(),
753 NodeSpec {
754 content: Some("text*".to_string()),
755 marks: None,
756 group: None,
757 desc: Some("表格单元格节点".to_string()),
758 attrs: None,
759 },
760 );
761
762 nodes.insert(
764 "text".to_string(),
765 NodeSpec {
766 content: None,
767 marks: None,
768 group: None,
769 desc: Some("文本节点".to_string()),
770 attrs: None,
771 },
772 );
773
774 let schema_spec = SchemaSpec {
775 nodes,
776 marks: HashMap::new(),
777 top_node: Some("table".to_string()),
778 };
779
780 let schema = Schema::compile(schema_spec).unwrap();
781 let table_type = schema.nodes.get("table").unwrap();
782
783 println!("=== 测试 create_and_fill ===");
785 let empty_content: Vec<Node> = vec![];
786 let result = table_type.create_and_fill(
787 None, None, empty_content, None, &schema, );
793
794 let (main_node, child_nodes) = result.into_parts();
795 println!("Main node: {:?}", main_node);
796 println!("Child nodes count: {}", child_nodes.len());
797
798 for (i, child) in child_nodes.iter().enumerate() {
799 let (child_node, grandchildren) = child.clone().into_parts();
800 println!(
801 " Child {}: type={}, id={}",
802 i + 1,
803 child_node.r#type,
804 child_node.id
805 );
806 println!(" Grandchildren count: {}", grandchildren.len());
807 }
808
809 if !child_nodes.is_empty() {
811 let (first_child, _) = child_nodes[0].clone().into_parts();
812 println!("第一个子节点类型: {}", first_child.r#type);
813 } else {
814 println!("警告:没有创建任何子节点!");
815 }
816 }
817
818 #[test]
819 fn test_edge_cases() {
820 use crate::node_type::NodeType;
821 use crate::node::Node;
822 use crate::attrs::Attrs;
823
824 let mut nodes = HashMap::new();
826 nodes.insert(
827 "table".to_string(),
828 NodeSpec {
829 content: Some("tablerow+".to_string()),
830 marks: None,
831 group: None,
832 desc: Some("表格节点".to_string()),
833 attrs: None,
834 },
835 );
836 nodes.insert(
837 "tablerow".to_string(),
838 NodeSpec {
839 content: Some("tablecell+".to_string()),
840 marks: None,
841 group: None,
842 desc: Some("表格行节点".to_string()),
843 attrs: None,
844 },
845 );
846 nodes.insert(
847 "tablecell".to_string(),
848 NodeSpec {
849 content: Some("text*".to_string()),
850 marks: None,
851 group: None,
852 desc: Some("表格单元格节点".to_string()),
853 attrs: None,
854 },
855 );
856 nodes.insert(
857 "text".to_string(),
858 NodeSpec {
859 content: None,
860 marks: None,
861 group: None,
862 desc: Some("文本节点".to_string()),
863 attrs: None,
864 },
865 );
866
867 let schema_spec = SchemaSpec {
868 nodes,
869 marks: HashMap::new(),
870 top_node: Some("table".to_string()),
871 };
872 let schema = Schema::compile(schema_spec).unwrap();
873 let table_type = schema.nodes.get("table").unwrap();
874
875 println!("=== 边界情况测试 ===");
876
877 if table_type.content_match.is_none() {
879 println!("警告:table_type.content_match 为 None");
880 return;
881 }
882 let content_match = table_type.content_match.as_ref().unwrap();
883
884 let empty_content: Vec<Node> = vec![];
886 let matched = content_match.match_fragment(&empty_content, &schema);
887 println!("match_fragment result: {:?}", matched.is_some());
888
889 if let Some(matched_state) = matched {
890 println!("matched state valid_end: {}", matched_state.valid_end);
891
892 let fill_result = matched_state.fill(&empty_content, true, &schema);
894 println!("fill result: {:?}", fill_result.is_some());
895
896 if let Some(needed_types) = fill_result {
897 println!("需要的类型数量: {}", needed_types.len());
898 for type_name in &needed_types {
899 println!(" 需要的类型: {}", type_name);
900 }
901 }
902 }
903
904 if let Some(matched_state) = matched {
906 let fill_result_no_end =
907 matched_state.fill(&empty_content, false, &schema);
908 println!(
909 "fill result (to_end=false): {:?}",
910 fill_result_no_end.is_some()
911 );
912 }
913 }
914
915 #[test]
916 fn test_block_choice_problem() {
917 use crate::node_type::NodeType;
918
919 let mut nodes = HashMap::new();
921
922 nodes.insert(
924 "block".to_string(),
925 NodeSpec {
926 content: Some("table paragraph list heading".to_string()),
927 marks: None,
928 group: None,
929 desc: Some("块级节点".to_string()),
930 attrs: None,
931 },
932 );
933
934 nodes.insert(
936 "table".to_string(),
937 NodeSpec {
938 content: Some("tablerow+".to_string()),
939 marks: None,
940 group: None,
941 desc: Some("表格节点".to_string()),
942 attrs: None,
943 },
944 );
945 nodes.insert(
946 "paragraph".to_string(),
947 NodeSpec {
948 content: Some("text*".to_string()),
949 marks: None,
950 group: None,
951 desc: Some("段落节点".to_string()),
952 attrs: None,
953 },
954 );
955 nodes.insert(
956 "list".to_string(),
957 NodeSpec {
958 content: Some("listitem+".to_string()),
959 marks: None,
960 group: None,
961 desc: Some("列表节点".to_string()),
962 attrs: None,
963 },
964 );
965 nodes.insert(
966 "heading".to_string(),
967 NodeSpec {
968 content: Some("text*".to_string()),
969 marks: None,
970 group: None,
971 desc: Some("标题节点".to_string()),
972 attrs: None,
973 },
974 );
975 nodes.insert(
976 "tablerow".to_string(),
977 NodeSpec {
978 content: Some("tablecell+".to_string()),
979 marks: None,
980 group: None,
981 desc: Some("表格行节点".to_string()),
982 attrs: None,
983 },
984 );
985 nodes.insert(
986 "tablecell".to_string(),
987 NodeSpec {
988 content: Some("text*".to_string()),
989 marks: None,
990 group: None,
991 desc: Some("表格单元格节点".to_string()),
992 attrs: None,
993 },
994 );
995 nodes.insert(
996 "listitem".to_string(),
997 NodeSpec {
998 content: Some("paragraph".to_string()),
999 marks: None,
1000 group: None,
1001 desc: Some("列表项节点".to_string()),
1002 attrs: None,
1003 },
1004 );
1005 nodes.insert(
1006 "text".to_string(),
1007 NodeSpec {
1008 content: None,
1009 marks: None,
1010 group: None,
1011 desc: Some("文本节点".to_string()),
1012 attrs: None,
1013 },
1014 );
1015
1016 let schema_spec = SchemaSpec {
1017 nodes,
1018 marks: HashMap::new(),
1019 top_node: Some("block".to_string()),
1020 };
1021
1022 let schema = Schema::compile(schema_spec).unwrap();
1023 let block_type = schema.nodes.get("block").unwrap();
1024
1025 println!("=== 测试 Block 选择问题 ===");
1026
1027 if let Some(content_match) = &block_type.content_match {
1028 println!("Block content match: {}", content_match);
1029
1030 let default_type = content_match.default_type();
1032 if let Some(def_type) = default_type {
1033 println!("默认类型: {}", def_type.name);
1034 println!(
1035 "默认类型是否有必须属性: {}",
1036 def_type.has_required_attrs()
1037 );
1038 } else {
1039 println!("没有默认类型");
1040 }
1041
1042 let empty_content: Vec<Node> = vec![];
1044 let result = content_match.fill(&empty_content, true, &schema);
1045
1046 println!("Fill result: {:?}", result.is_some());
1047 if let Some(needed_types) = result {
1048 println!("需要的类型数量: {}", needed_types.len());
1049 for (i, type_name) in needed_types.iter().enumerate() {
1050 println!(" 第{}个需要的节点类型: {}", i + 1, type_name);
1051 }
1052 }
1053
1054 println!("=== 测试 Block create_and_fill ===");
1056 let result =
1057 block_type.create_and_fill(None, None, vec![], None, &schema);
1058
1059 let (main_node, child_nodes) = result.into_parts();
1060 println!("Main node type: {}", main_node.r#type);
1061 println!("Child nodes count: {}", child_nodes.len());
1062
1063 for (i, child) in child_nodes.iter().enumerate() {
1064 let (child_node, grandchildren) = child.clone().into_parts();
1065 println!(" Child {}: type={}", i + 1, child_node.r#type);
1066 if child_node.r#type == "table" {
1067 println!(
1068 " Table 的 grandchildren count: {}",
1069 grandchildren.len()
1070 );
1071 for (j, grandchild) in grandchildren.iter().enumerate() {
1072 let (gc_node, _) = grandchild.clone().into_parts();
1073 println!(
1074 " Grandchild {}: type={}",
1075 j + 1,
1076 gc_node.r#type
1077 );
1078 }
1079 }
1080 }
1081 }
1082 }
1083
1084 #[test]
1085 fn test_sequence_with_existing_nodes() {
1086 use crate::node_type::NodeType;
1087 use crate::node::Node;
1088 use crate::attrs::Attrs;
1089
1090 let mut nodes = HashMap::new();
1092 nodes.insert(
1093 "block".to_string(),
1094 NodeSpec {
1095 content: Some("table paragraph".to_string()), marks: None,
1097 group: None,
1098 desc: Some("块级节点".to_string()),
1099 attrs: None,
1100 },
1101 );
1102 nodes.insert(
1103 "table".to_string(),
1104 NodeSpec {
1105 content: Some("tablerow+".to_string()),
1106 marks: None,
1107 group: None,
1108 desc: Some("表格节点".to_string()),
1109 attrs: None,
1110 },
1111 );
1112 nodes.insert(
1113 "paragraph".to_string(),
1114 NodeSpec {
1115 content: Some("text*".to_string()),
1116 marks: None,
1117 group: None,
1118 desc: Some("段落节点".to_string()),
1119 attrs: None,
1120 },
1121 );
1122 nodes.insert(
1123 "tablerow".to_string(),
1124 NodeSpec {
1125 content: Some("tablecell+".to_string()),
1126 marks: None,
1127 group: None,
1128 desc: Some("表格行节点".to_string()),
1129 attrs: None,
1130 },
1131 );
1132 nodes.insert(
1133 "tablecell".to_string(),
1134 NodeSpec {
1135 content: Some("text*".to_string()),
1136 marks: None,
1137 group: None,
1138 desc: Some("表格单元格节点".to_string()),
1139 attrs: None,
1140 },
1141 );
1142 nodes.insert(
1143 "text".to_string(),
1144 NodeSpec {
1145 content: None,
1146 marks: None,
1147 group: None,
1148 desc: Some("文本节点".to_string()),
1149 attrs: None,
1150 },
1151 );
1152
1153 let schema_spec = SchemaSpec {
1154 nodes,
1155 marks: HashMap::new(),
1156 top_node: Some("block".to_string()),
1157 };
1158 let schema = Schema::compile(schema_spec).unwrap();
1159 let block_type = schema.nodes.get("block").unwrap();
1160
1161 println!("=== 测试序列中已存在节点的情况 ===");
1162
1163 let existing_table = Node::new(
1165 "existing_table_123",
1166 "table".to_string(),
1167 Attrs::default(),
1168 vec!["existing_row_456".to_string()],
1169 vec![],
1170 );
1171
1172 let existing_paragraph = Node::new(
1174 "existing_para_789",
1175 "paragraph".to_string(),
1176 Attrs::default(),
1177 vec!["existing_text_000".to_string()],
1178 vec![],
1179 );
1180
1181 let existing_content = vec![existing_table, existing_paragraph];
1182
1183 println!("传入的现有内容:");
1184 for (i, node) in existing_content.iter().enumerate() {
1185 println!(
1186 " 第{}个现有节点: type={}, id={}, content={:?}",
1187 i + 1,
1188 node.r#type,
1189 node.id,
1190 node.content
1191 );
1192 }
1193
1194 let result = block_type.create_and_fill(
1196 None,
1197 None,
1198 existing_content,
1199 None,
1200 &schema,
1201 );
1202
1203 let (main_node, child_nodes) = result.into_parts();
1204 println!(
1205 "Main node: type={}, content={:?}",
1206 main_node.r#type, main_node.content
1207 );
1208 println!("Child nodes count: {}", child_nodes.len());
1209
1210 for (i, child) in child_nodes.iter().enumerate() {
1211 let (child_node, grandchildren) = child.clone().into_parts();
1212 println!(
1213 " Child {}: type={}, id={}",
1214 i + 1,
1215 child_node.r#type,
1216 child_node.id
1217 );
1218 println!(" Content: {:?}", child_node.content);
1219 println!(" Grandchildren count: {}", grandchildren.len());
1220
1221 for (j, grandchild) in grandchildren.iter().enumerate() {
1222 let (gc_node, _) = grandchild.clone().into_parts();
1223 println!(
1224 " Grandchild {}: type={}, id={}",
1225 j + 1,
1226 gc_node.r#type,
1227 gc_node.id
1228 );
1229 }
1230 }
1231 }
1232
1233 #[test]
1234 fn test_table_creation_step_by_step() {
1235 use crate::node_type::NodeType;
1236
1237 let mut nodes = HashMap::new();
1239
1240 nodes.insert(
1241 "table".to_string(),
1242 NodeSpec {
1243 content: Some("tablerow+".to_string()),
1244 marks: None,
1245 group: None,
1246 desc: Some("表格节点".to_string()),
1247 attrs: None,
1248 },
1249 );
1250 nodes.insert(
1251 "tablerow".to_string(),
1252 NodeSpec {
1253 content: Some("tablecell+".to_string()),
1254 marks: None,
1255 group: None,
1256 desc: Some("表格行节点".to_string()),
1257 attrs: None,
1258 },
1259 );
1260 nodes.insert(
1261 "tablecell".to_string(),
1262 NodeSpec {
1263 content: Some("text*".to_string()),
1264 marks: None,
1265 group: None,
1266 desc: Some("表格单元格节点".to_string()),
1267 attrs: None,
1268 },
1269 );
1270 nodes.insert(
1271 "text".to_string(),
1272 NodeSpec {
1273 content: None,
1274 marks: None,
1275 group: None,
1276 desc: Some("文本节点".to_string()),
1277 attrs: None,
1278 },
1279 );
1280
1281 let schema_spec = SchemaSpec {
1282 nodes,
1283 marks: HashMap::new(),
1284 top_node: Some("table".to_string()),
1285 };
1286 let schema = Schema::compile(schema_spec).unwrap();
1287 let table_type = schema.nodes.get("table").unwrap();
1288
1289 println!("=== 逐步诊断 Table 创建过程 ===");
1290
1291 println!("第1步:检查 table 的 content_match");
1293 if let Some(content_match) = &table_type.content_match {
1294 println!(" ✅ content_match 存在");
1295 println!(" content_match: {}", content_match);
1296 } else {
1297 println!(" ❌ content_match 不存在");
1298 return;
1299 }
1300
1301 println!("第2步:测试 match_fragment");
1303 let empty_content: Vec<Node> = vec![];
1304 let content_match = table_type.content_match.as_ref().unwrap();
1305
1306 let matched = content_match.match_fragment(&empty_content, &schema);
1307 if let Some(matched_state) = matched {
1308 println!(" ✅ match_fragment 成功");
1309 println!(" matched state valid_end: {}", matched_state.valid_end);
1310 } else {
1311 println!(" ❌ match_fragment 返回 None");
1312 return;
1313 }
1314
1315 println!("第3步:测试 fill");
1317 let matched_state = matched.unwrap();
1318 let fill_result = matched_state.fill(&empty_content, true, &schema);
1319
1320 if let Some(needed_types) = fill_result {
1321 println!(" ✅ fill 成功,需要的类型数量: {}", needed_types.len());
1322 for (i, type_name) in needed_types.iter().enumerate() {
1323 println!(" 第{}个需要的类型: {}", i + 1, type_name);
1324 }
1325 } else {
1326 println!(" ❌ fill 返回 None");
1327 return;
1328 }
1329
1330 println!("第4步:测试完整的 create_and_fill");
1332 let result = table_type.create_and_fill(
1333 None,
1334 None,
1335 vec![], None,
1337 &schema,
1338 );
1339
1340 let (main_node, child_nodes) = result.into_parts();
1341 println!(" Main table node:");
1342 println!(" ID: {}", main_node.id);
1343 println!(" Content IDs: {:?}", main_node.content);
1344 println!(" Child nodes count: {}", child_nodes.len());
1345
1346 if child_nodes.is_empty() {
1347 println!(" ❌ 没有创建子节点!");
1348 } else {
1349 for (i, child) in child_nodes.iter().enumerate() {
1350 let (child_node, grandchildren) = child.clone().into_parts();
1351 println!(
1352 " Child {}: type={}, id={}",
1353 i + 1,
1354 child_node.r#type,
1355 child_node.id
1356 );
1357 println!(" Content IDs: {:?}", child_node.content);
1358 println!(" Grandchildren count: {}", grandchildren.len());
1359
1360 if child_node.r#type == "tablerow" && grandchildren.is_empty() {
1361 println!(" ❌ tablerow 没有创建 tablecell 子节点!");
1362 }
1363
1364 for (j, grandchild) in grandchildren.iter().enumerate() {
1365 let (gc_node, great_grandchildren) =
1366 grandchild.clone().into_parts();
1367 println!(
1368 " Grandchild {}: type={}, id={}",
1369 j + 1,
1370 gc_node.r#type,
1371 gc_node.id
1372 );
1373 println!(" Content IDs: {:?}", gc_node.content);
1374 println!(
1375 " Great-grandchildren count: {}",
1376 great_grandchildren.len()
1377 );
1378 }
1379 }
1380 }
1381
1382 println!("第5步:单独测试 tablerow 的创建");
1384 let tablerow_type = schema.nodes.get("tablerow").unwrap();
1385 let tablerow_result = tablerow_type.create_and_fill(
1386 None,
1387 None,
1388 vec![], None,
1390 &schema,
1391 );
1392
1393 let (tr_node, tr_children) = tablerow_result.into_parts();
1394 println!(" Tablerow node:");
1395 println!(" ID: {}", tr_node.id);
1396 println!(" Content IDs: {:?}", tr_node.content);
1397 println!(" Children count: {}", tr_children.len());
1398
1399 if tr_children.is_empty() {
1400 println!(" ❌ tablerow 没有创建 tablecell 子节点!");
1401 } else {
1402 for (i, child) in tr_children.iter().enumerate() {
1403 let (child_node, _) = child.clone().into_parts();
1404 println!(
1405 " Child {}: type={}, id={}",
1406 i + 1,
1407 child_node.r#type,
1408 child_node.id
1409 );
1410 }
1411 }
1412 }
1413
1414 #[test]
1415 fn test_sequence_table_problem() {
1416 use crate::node_type::NodeType;
1417
1418 let mut nodes = HashMap::new();
1420
1421 nodes.insert(
1423 "block".to_string(),
1424 NodeSpec {
1425 content: Some("table paragraph list heading".to_string()),
1426 marks: None,
1427 group: None,
1428 desc: Some("块级节点".to_string()),
1429 attrs: None,
1430 },
1431 );
1432
1433 nodes.insert(
1435 "table".to_string(),
1436 NodeSpec {
1437 content: Some("tablerow+".to_string()),
1438 marks: None,
1439 group: None,
1440 desc: Some("表格节点".to_string()),
1441 attrs: None,
1442 },
1443 );
1444 nodes.insert(
1445 "paragraph".to_string(),
1446 NodeSpec {
1447 content: Some("text*".to_string()),
1448 marks: None,
1449 group: None,
1450 desc: Some("段落节点".to_string()),
1451 attrs: None,
1452 },
1453 );
1454 nodes.insert(
1455 "list".to_string(),
1456 NodeSpec {
1457 content: Some("listitem+".to_string()),
1458 marks: None,
1459 group: None,
1460 desc: Some("列表节点".to_string()),
1461 attrs: None,
1462 },
1463 );
1464 nodes.insert(
1465 "heading".to_string(),
1466 NodeSpec {
1467 content: Some("text*".to_string()),
1468 marks: None,
1469 group: None,
1470 desc: Some("标题节点".to_string()),
1471 attrs: None,
1472 },
1473 );
1474 nodes.insert(
1475 "tablerow".to_string(),
1476 NodeSpec {
1477 content: Some("tablecell+".to_string()),
1478 marks: None,
1479 group: None,
1480 desc: Some("表格行节点".to_string()),
1481 attrs: None,
1482 },
1483 );
1484 nodes.insert(
1485 "tablecell".to_string(),
1486 NodeSpec {
1487 content: Some("text*".to_string()),
1488 marks: None,
1489 group: None,
1490 desc: Some("表格单元格节点".to_string()),
1491 attrs: None,
1492 },
1493 );
1494 nodes.insert(
1495 "listitem".to_string(),
1496 NodeSpec {
1497 content: Some("paragraph".to_string()),
1498 marks: None,
1499 group: None,
1500 desc: Some("列表项节点".to_string()),
1501 attrs: None,
1502 },
1503 );
1504 nodes.insert(
1505 "text".to_string(),
1506 NodeSpec {
1507 content: None,
1508 marks: None,
1509 group: None,
1510 desc: Some("文本节点".to_string()),
1511 attrs: None,
1512 },
1513 );
1514
1515 let schema_spec = SchemaSpec {
1516 nodes,
1517 marks: HashMap::new(),
1518 top_node: Some("block".to_string()),
1519 };
1520
1521 let schema = Schema::compile(schema_spec).unwrap();
1522 let block_type = schema.nodes.get("block").unwrap();
1523
1524 println!("=== 测试序列表达式中的 Table 问题 ===");
1525
1526 let result = block_type.create_and_fill(
1528 None,
1529 None,
1530 vec![], None,
1532 &schema,
1533 );
1534
1535 let (main_node, child_nodes) = result.into_parts();
1536 println!("Block 节点:");
1537 println!(" ID: {}", main_node.id);
1538 println!(" Content IDs: {:?}", main_node.content);
1539 println!(" 子节点数量: {}", child_nodes.len());
1540
1541 for (i, child) in child_nodes.iter().enumerate() {
1543 let (child_node, grandchildren) = child.clone().into_parts();
1544 println!(
1545 " 子节点 {}: type={}, id={}",
1546 i + 1,
1547 child_node.r#type,
1548 child_node.id
1549 );
1550 println!(" Content IDs: {:?}", child_node.content);
1551 println!(" 孙节点数量: {}", grandchildren.len());
1552
1553 if child_node.r#type == "table" {
1555 println!(" 📋 这是 Table 节点:");
1556
1557 if child_node.content.is_empty() {
1559 println!(" ❌ Table 节点的 content IDs 是空的!");
1560 } else {
1561 println!(
1562 " ✅ Table 节点包含 content IDs: {:?}",
1563 child_node.content
1564 );
1565 }
1566
1567 if grandchildren.is_empty() {
1569 println!(
1570 " ❌ Table 节点没有创建任何孙节点(tablerow)!"
1571 );
1572 } else {
1573 println!(
1574 " ✅ Table 节点创建了 {} 个孙节点:",
1575 grandchildren.len()
1576 );
1577 for (j, grandchild) in grandchildren.iter().enumerate() {
1578 let (gc_node, great_grandchildren) =
1579 grandchild.clone().into_parts();
1580 println!(
1581 " 孙节点 {}: type={}, id={}",
1582 j + 1,
1583 gc_node.r#type,
1584 gc_node.id
1585 );
1586 println!(
1587 " Content IDs: {:?}",
1588 gc_node.content
1589 );
1590
1591 if gc_node.r#type == "tablerow" {
1593 if great_grandchildren.is_empty() {
1594 println!(
1595 " ❌ tablerow 没有创建 tablecell 子节点!"
1596 );
1597
1598 println!(
1600 " 🔍 调试 tablerow 填充过程:"
1601 );
1602 let tablerow_type =
1603 schema.nodes.get("tablerow").unwrap();
1604 if let Some(tr_content_match) =
1605 &tablerow_type.content_match
1606 {
1607 println!(
1608 " tablerow content_match: {}",
1609 tr_content_match
1610 );
1611
1612 let empty_content: Vec<Node> = vec![];
1613 let tr_matched = tr_content_match
1614 .match_fragment(
1615 &empty_content,
1616 &schema,
1617 );
1618 if let Some(tr_matched_state) = tr_matched {
1619 println!(
1620 " tablerow match_fragment 成功"
1621 );
1622 println!(
1623 " tablerow matched state valid_end: {}",
1624 tr_matched_state.valid_end
1625 );
1626
1627 let tr_fill_result = tr_matched_state
1628 .fill(
1629 &empty_content,
1630 true,
1631 &schema,
1632 );
1633 if let Some(tr_needed_types) =
1634 tr_fill_result
1635 {
1636 println!(
1637 " tablerow 需要的类型数量: {}",
1638 tr_needed_types.len()
1639 );
1640 for (k, type_name) in
1641 tr_needed_types
1642 .iter()
1643 .enumerate()
1644 {
1645 println!(
1646 " 需要的类型 {}: {}",
1647 k + 1,
1648 type_name
1649 );
1650 }
1651 } else {
1652 println!(
1653 " ❌ tablerow fill 返回 None"
1654 );
1655 }
1656 } else {
1657 println!(
1658 " ❌ tablerow match_fragment 返回 None"
1659 );
1660 }
1661 } else {
1662 println!(
1663 " ❌ tablerow 没有 content_match"
1664 );
1665 }
1666 } else {
1667 println!(
1668 " ✅ tablerow 创建了 {} 个 tablecell",
1669 great_grandchildren.len()
1670 );
1671 for (k, ggc) in
1672 great_grandchildren.iter().enumerate()
1673 {
1674 let (ggc_node, _) =
1675 ggc.clone().into_parts();
1676 println!(
1677 " 曾孙节点 {}: type={}, id={}",
1678 k + 1,
1679 ggc_node.r#type,
1680 ggc_node.id
1681 );
1682 }
1683 }
1684 }
1685 }
1686 }
1687 }
1688 }
1689
1690 println!("\n=== 对比:单独创建 Table 节点 ===");
1692 let table_type = schema.nodes.get("table").unwrap();
1693 let standalone_table =
1694 table_type.create_and_fill(None, None, vec![], None, &schema);
1695
1696 let (st_node, st_children) = standalone_table.into_parts();
1697 println!("单独的 Table 节点:");
1698 println!(" ID: {}", st_node.id);
1699 println!(" Content IDs: {:?}", st_node.content);
1700 println!(" 子节点数量: {}", st_children.len());
1701
1702 for (i, child) in st_children.iter().enumerate() {
1703 let (child_node, grandchildren) = child.clone().into_parts();
1704 println!(
1705 " 子节点 {}: type={}, id={}",
1706 i + 1,
1707 child_node.r#type,
1708 child_node.id
1709 );
1710 println!(" 孙节点数量: {}", grandchildren.len());
1711 }
1712
1713 println!("\n=== 额外调试:单独创建 tablerow 节点 ===");
1715 let tablerow_type = schema.nodes.get("tablerow").unwrap();
1716 let standalone_tablerow =
1717 tablerow_type.create_and_fill(None, None, vec![], None, &schema);
1718
1719 let (str_node, str_children) = standalone_tablerow.into_parts();
1720 println!("单独的 tablerow 节点:");
1721 println!(" ID: {}", str_node.id);
1722 println!(" Content IDs: {:?}", str_node.content);
1723 println!(" 子节点数量: {}", str_children.len());
1724
1725 for (i, child) in str_children.iter().enumerate() {
1726 let (child_node, _) = child.clone().into_parts();
1727 println!(
1728 " 子节点 {}: type={}, id={}",
1729 i + 1,
1730 child_node.r#type,
1731 child_node.id
1732 );
1733 }
1734 }
1735}