1use crate::parser::ast::{
2 ElementNode, FunctionNode, IndexNode, Node, SelectorNode, SetOperationNode,
3 TextNode, Visitor, Visitable,
4};
5use crate::parser::error::ParseError;
6
7#[derive(Debug, Clone)]
9struct ValidationState {
10 has_text_selector: bool,
12
13 text_selector_pos: Option<(usize, usize)>,
15
16 current_pos: (usize, usize),
18}
19
20impl ValidationState {
21 fn new() -> Self {
23 ValidationState {
24 has_text_selector: false,
25 text_selector_pos: None,
26 current_pos: (0, 0),
27 }
28 }
29
30 fn set_position(&mut self, line: usize, column: usize) {
32 self.current_pos = (line, column);
33 }
34
35 fn mark_text_selector(&mut self) {
37 self.has_text_selector = true;
38 self.text_selector_pos = Some(self.current_pos);
39 }
40
41 fn can_add_element_selector(&self) -> bool {
43 !self.has_text_selector
44 }
45
46}
47
48pub struct SyntaxValidator {
50 state: ValidationState,
52}
53
54impl SyntaxValidator {
55
56 pub fn new() -> Self {
57 SyntaxValidator {
58 state: ValidationState::new(),
59 }
60 }
61
62 pub fn validate(&mut self, node: &Node) -> Result<(), ParseError> {
64 node.accept(self)
66 }
67
68 #[allow(dead_code)]
70 pub fn set_position(&mut self, line: usize, column: usize) {
71 self.state.set_position(line, column);
72 }
73}
74
75impl Visitor<Result<(), ParseError>> for SyntaxValidator {
76 fn visit_node(&mut self, node: &Node) -> Result<(), ParseError> {
77 match node {
78 Node::Selector(selector) => self.visit_selector(selector),
79 Node::Pipeline(left, right) => self.visit_pipeline(left, right),
80 Node::SetOperation(op) => self.visit_set_operation(op),
81 Node::IndexSelection(inner, idx) => {
82 self.visit_node(inner)?;
83 self.visit_index(idx)
84 }
85 Node::FunctionCall(inner, func) => {
86 self.visit_node(inner)?;
87 self.visit_function(func)
88 }
89 }
90 }
91
92 fn visit_selector(&mut self, node: &SelectorNode) -> Result<(), ParseError> {
93 match node {
94 SelectorNode::ElementSelector(elem) => self.visit_element(elem),
95 SelectorNode::TextSelector(text) => self.visit_text(text),
96 }
97 }
98
99 fn visit_element(&mut self, _node: &ElementNode) -> Result<(), ParseError> {
100 if !self.state.can_add_element_selector() {
102 let (line, column) = self.state.current_pos;
103 return Err(ParseError::element_after_text_selector(line, column));
104 }
105
106 Ok(())
107 }
108
109 fn visit_text(&mut self, _node: &TextNode) -> Result<(), ParseError> {
110 if self.state.has_text_selector {
112 let (line, column) = self.state.current_pos;
113 return Err(ParseError::multiple_text_selectors(line, column));
114 }
115
116 self.state.mark_text_selector();
118
119 Ok(())
120 }
121
122 fn visit_pipeline(&mut self, left: &Node, right: &Node) -> Result<(), ParseError> {
123 self.visit_node(left)?;
126 self.visit_node(right)
127 }
128
129
130 fn visit_set_operation(&mut self, node: &SetOperationNode) -> Result<(), ParseError> {
131 match node {
132 SetOperationNode::Union(left, right)
133 | SetOperationNode::Intersection(left, right)
134 | SetOperationNode::Difference(left, right) => {
135
136 let original_state = self.state.clone();
137
138 self.visit_node(left)?;
139
140 self.state = original_state;
141 self.visit_node(right)?;
142
143 self.state = ValidationState::new();
146
147 Ok(())
148 }
149 }
150 }
151
152 fn visit_index(&mut self, _node: &IndexNode) -> Result<(), ParseError> {
153 Ok(())
155 }
156
157 fn visit_function(&mut self, _node: &FunctionNode) -> Result<(), ParseError> {
158 Ok(())
160 }
161}