1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
use std::io::{prelude::*, BufReader, BufWriter};
use std::marker::PhantomData;
use socarel::{Forest, NodeContent, RawNode};
use crate::stack::*;
use crate::parser::*;
use crate::error::*;

/// Document interaction model.
pub struct Model<T: NodeContent = RawNode>(PhantomData<T>);

impl<T: NodeContent> Model<T> {
    /// Parse TREF document.
    /// 
    /// # Arguments
    /// 
    /// * `reader` - BufReader to read the document.
    /// 
    /// # Return
    /// 
    /// * A [`Result`] with a [`Forest`] or a [`ParseTreeError`].
    ///
    pub fn parse(reader: BufReader<impl Read>) -> Result<Forest<T>, ParseTreeError> {
        let parser = TreeParser::new();
        let mut stack = NodeStack::new();
        let mut prev_level = 0;
        let mut current_tree_id = String::new();
        let mut forest = Forest::<T>::new();

        for (i, l) in reader.lines().enumerate() {
            if let Ok(line) = l {
                let statement = parser.parse_statement(&line);
                match statement {
                    TreeStatement::Invalid => {
                        return Result::Err(ParseTreeError::new("Invalid statement", i))
                    },
                    TreeStatement::TreeID(tree_id) => {
                        stack.flush();
                        // Create new tree
                        forest.new_tree(&tree_id);
                        current_tree_id = tree_id;
                    }
                    TreeStatement::Node(content, level) => {
                        if level > prev_level + 1 {
                            return Result::Err(ParseTreeError::new("Invalid node level", i));
                        }
    
                        // Root node
                        if level == 1 {
                            if let Some(_) = stack.top() {
                                return Result::Err(ParseTreeError::new("Multiple root nodes in the same tree", i));
                            }

                            if let Some(tree) = forest.get_mut_tree(&current_tree_id) {
                                // Create root node
                                if let None = tree.set_root(&content) {
                                    return Result::Err(ParseTreeError::new("Failed parsing root node", i));
                                }
                                // Push root node reference to stack
                                stack.push_new(1, 0);
                            }
                            else {
                                return Result::Err(ParseTreeError::new("Found root node without previous tree ID", i));
                            }
                        }
                        // Somebody's child node
                        else {
                            if let Some(parent_node_ref) = stack.pop_parent(level) {
                                if let Some(tree) = forest.get_mut_tree(&current_tree_id) {
                                    if let Some(new_node) = tree.link_node(&content, parent_node_ref.tree_position) {
                                        // Push back parent node reference to stack
                                        stack.push(parent_node_ref);
                                        // Push new node reference to stack
                                        stack.push_new(level, new_node);
                                    }
                                    else {
                                        return Result::Err(ParseTreeError::new("Failed parsing node", i));
                                    }
                                }
                                else {
                                    return Result::Err(ParseTreeError::new("Couldn't find tree", i));
                                }
                            }
                            else {
                                return Result::Err(ParseTreeError::new("Couldn't find a parent ref", i));
                            }
                        }
    
                        prev_level = level;
                    },
                    _ => {}
                }
            }
            else {
                return Result::Err(ParseTreeError::new("Could not read line", i));
            }
        }

        Result::Ok(forest)
    }

    /// Convert a Forest structure into a TREF document.
    /// 
    /// # Arguments
    /// 
    /// * `forest` - Reference to a `Forest`.
    /// * `writer` - BufWriter where to write the TREF.
    ///
    /// # Return
    /// 
    /// * A [`Result`] with a number of lines writen or a [`SerializeTreeError`].
    /// 
    pub fn serialize(forest: &Forest<T>, writer: &mut BufWriter<impl Write>) -> Result<usize, SerializeTreeError> {
        let parser = TreeParser::new();
        let mut num_lines_writen = 0;
        for (tree_id, _) in forest.iter() {
            // write tree id statement
            let tree_id_statement = format!("[{}]", tree_id);
            if let TreeStatement::TreeID(_) = parser.parse_statement(&tree_id_statement) {
                if let Err(_) = writer.write(&format!("{}\n",tree_id_statement).as_bytes()) {
                    return Result::Err(SerializeTreeError::new("Could not write Tree ID", num_lines_writen, Some(tree_id_statement)));
                }
                num_lines_writen += 1;
            }
            else {
                return Result::Err(SerializeTreeError::new("Could not parse Tree ID", num_lines_writen, Some(tree_id_statement)));
            }
            // iter all nodes and generate statements
            if let Some(tree) = forest.get_tree(tree_id) {
                for (n, _) in tree.iterators().pre_dfs() {
                    let mut node_statement = String::new();
                    for _ in 0..n.get_level() {
                        node_statement.push_str("+ ");
                    }
                    node_statement.push_str(&format!("{}", n.get_content_ref().gen_content()));
                    // write node
                    if let TreeStatement::Node(_,_) = parser.parse_statement(&node_statement) {
                        if let Err(_) = writer.write(format!("{}\n", node_statement).as_bytes()) {
                            return Result::Err(SerializeTreeError::new("Could nod write node", num_lines_writen, Some(node_statement)));
                        }
                        num_lines_writen += 1;
                    }
                    else {
                        return Result::Err(SerializeTreeError::new("Could not parse node", num_lines_writen, Some(node_statement)));
                    }
                }
            }
            else {
                return Result::Err(SerializeTreeError::new("Could nod get tree from forest", num_lines_writen, Some(String::from(tree_id))));
            }
        }

        if let Err(_) = writer.flush() {
            Result::Err(SerializeTreeError::new("Writer flush failed", num_lines_writen, None))
        }
        else {
            Ok(num_lines_writen)
        }
    }
}