1use crate::lexer::Token;
2use crate::parser::ast::{ElementNode, SelectorNode};
3use crate::parser::error::ParseError;
4use super::Parser;
5
6pub fn parse_element(it: &mut Parser) -> Result<SelectorNode, ParseError> {
8 match &it.current_token {
9 Some((Token::Class, _, _)) => {
10 let element_node = parse_class_selector(it)?;
11 Ok(SelectorNode::ElementSelector(element_node))
12 }
13 Some((Token::Id, _, _)) => {
14 let element_node = parse_id_selector(it)?;
15 Ok(SelectorNode::ElementSelector(element_node))
16 }
17 Some((Token::Tag, _, _)) => {
18 let element_node = parse_tag_selector(it)?;
19 Ok(SelectorNode::ElementSelector(element_node))
20 }
21 Some((Token::Attr, _, _)) => {
22 let element_node = parse_attr_selector(it)?;
23 Ok(SelectorNode::ElementSelector(element_node))
24 }
25 _ => {
26 let (line, column) = it.get_current_position();
27 let current = it.get_current_token_str();
28 Err(ParseError::unexpected_token(
29 "class, id, tag, or attr",
30 ¤t,
31 line,
32 column,
33 ))
34 }
35 }
36}
37
38fn parse_class_selector(it: &mut Parser) -> Result<ElementNode, ParseError> {
40 it.consume_token(&Token::Class)?;
41
42 let (is_regex, value) = parse_selector_value(it)?;
43
44 if value.is_empty() {
45 let (line, column) = it.get_current_position();
46 return Err(ParseError::invalid_selector_value("empty value", line, column));
47 }
48
49 Ok(ElementNode::Class(value, is_regex))
50}
51
52fn parse_id_selector(it: &mut Parser) -> Result<ElementNode, ParseError> {
54
55 it.consume_token(&Token::Id)?;
56
57 let (is_regex, value) = parse_selector_value(it)?;
58
59 if value.is_empty() {
60 let (line, column) = it.get_current_position();
61 return Err(ParseError::invalid_selector_value("empty value", line, column));
62 }
63
64 Ok(ElementNode::Id(value, is_regex))
65}
66
67fn parse_tag_selector(it: &mut Parser) -> Result<ElementNode, ParseError> {
69
70 it.consume_token(&Token::Tag)?;
71
72 let (is_regex, value) = parse_selector_value(it)?;
73
74 if value.is_empty() {
75 let (line, column) = it.get_current_position();
76 return Err(ParseError::invalid_selector_value("empty value", line, column));
77 }
78
79 Ok(ElementNode::Tag(value, is_regex))
80}
81
82fn parse_attr_selector(it: &mut Parser) -> Result<ElementNode, ParseError> {
84
85 it.consume_token(&Token::Attr)?;
86
87 let (_, attr_name) = parse_selector_value(it)?;
88
89 if attr_name.is_empty() {
90 let (line, column) = it.get_current_position();
91 return Err(ParseError::invalid_selector_value("empty attribute name", line, column));
92 }
93
94 let (is_regex, attr_value) = match parse_selector_value(it) {
95 Ok((is_regex, attr_value)) => (is_regex, Some(attr_value)),
96 Err(_) => (false, None)
97 };
98
99 Ok(ElementNode::Attr(attr_name, attr_value, is_regex))
100}
101
102fn parse_selector_value(it: &mut Parser) -> Result<(bool, String), ParseError> {
104 let is_regex = if it.check_token(&Token::Tilde) {
105 it.consume_token(&Token::Tilde)?; true
107 } else {
108 false
109 };
110
111 match &it.current_token {
113 Some((Token::String(value), _, _)) => {
114 let value = value.clone();
115 it.read_token(); Ok((is_regex, value))
117 }
118 _ => {
119 let (line, column) = it.get_current_position();
120 let current = it.get_current_token_str();
121 Err(ParseError::unexpected_token(
122 "selector argument",
123 ¤t,
124 line,
125 column,
126 ))
127 }
128 }
129}