ass_core/tokenizer/
next_token.rs1use super::{AssTokenizer, Token, TokenContext, TokenType};
7use crate::Result;
8
9impl<'a> AssTokenizer<'a> {
10 pub fn next_token(&mut self) -> Result<Option<Token<'a>>> {
19 if self.context.allows_whitespace_skipping() {
20 self.scanner.navigator_mut().skip_whitespace();
21 }
22
23 if self.scanner.navigator().is_at_end() {
24 return Ok(None);
25 }
26
27 let start_pos = self.scanner.navigator().position();
28 let start_line = self.scanner.navigator().line();
29 let start_column = self.scanner.navigator().column();
30
31 let current_char = self.scanner.navigator_mut().peek_char()?;
32
33 let token_type = match (current_char, self.context) {
34 ('[', _) => {
35 self.context = TokenContext::SectionHeader;
36 self.scanner.scan_section_header()
37 }
38 (']', TokenContext::SectionHeader) => {
39 self.context = TokenContext::Document;
40 self.scanner.navigator_mut().advance_char()?;
41 Ok(TokenType::SectionClose)
42 }
43 (':', TokenContext::Document) => {
44 self.context = self.context.enter_field_value();
45 self.scanner.navigator_mut().advance_char()?;
46 Ok(TokenType::Colon)
47 }
48
49 ('{', _) => {
50 self.context = TokenContext::StyleOverride;
51 self.scanner.scan_style_override()
52 }
53 ('}', TokenContext::StyleOverride) => {
54 self.context = TokenContext::Document;
55 self.scanner.navigator_mut().advance_char()?;
56 Ok(TokenType::OverrideClose)
57 }
58 (',', _) => {
59 self.scanner.navigator_mut().advance_char()?;
60 Ok(TokenType::Comma)
61 }
62 ('\n' | '\r', _) => {
63 self.context = self.context.reset_to_document();
64 self.scanner.navigator_mut().advance_char()?;
65 if current_char == '\r' && self.scanner.navigator_mut().peek_char()? == '\n' {
66 self.scanner.navigator_mut().advance_char()?;
67 }
68 Ok(TokenType::Newline)
69 }
70 (';', TokenContext::Document) => self.scanner.scan_comment(),
71 ('!', TokenContext::Document) => {
72 if self.scanner.navigator().peek_next() == Ok(':') {
74 self.scanner.scan_comment()
75 } else {
76 self.scanner.scan_text(self.context)
77 }
78 }
79 ('}', _) => {
81 self.scanner.navigator_mut().advance_char()?;
83 Ok(TokenType::Text)
84 }
85 (']', _) => {
86 self.scanner.navigator_mut().advance_char()?;
88 Ok(TokenType::Text)
89 }
90 _ => {
91 if self.context == TokenContext::FieldValue {
93 self.scanner.scan_field_value()
94 } else {
95 self.scanner.scan_text(self.context)
96 }
97 }
98 }?;
99
100 let end_pos = self.scanner.navigator().position();
101 let span = &self.source[start_pos..end_pos];
102
103 if start_pos == end_pos && !self.scanner.navigator().is_at_end() {
105 return Err(crate::utils::CoreError::internal(
106 "Tokenizer position not advancing",
107 ));
108 }
109
110 Ok(Some(Token {
111 token_type,
112 span,
113 line: start_line,
114 column: start_column,
115 }))
116 }
117}