Skip to main content

oak_cmd/lexer/
mod.rs

1//! Lexer for Windows Command (CMD) language.
2
3/// Token types for command-line arguments.
4pub mod token_type;
5
6pub use token_type::CmdTokenType;
7
8use crate::language::CmdLanguage;
9use oak_core::{Lexer, LexerCache, LexerState, OakError, lexer::LexOutput, source::Source};
10
11pub(crate) type State<'a, S> = LexerState<'a, S, CmdLanguage>;
12
13/// Lexer for the CMD language.
14#[derive(Clone)]
15pub struct CmdLexer<'config> {
16    config: &'config CmdLanguage,
17}
18
19impl<'config> Lexer<CmdLanguage> for CmdLexer<'config> {
20    fn lex<'a, S: Source + ?Sized>(&self, source: &S, _edits: &[oak_core::source::TextEdit], cache: &'a mut impl LexerCache<CmdLanguage>) -> LexOutput<CmdLanguage> {
21        let mut state = LexerState::new_with_cache(source, 0, cache);
22        let result = self.run(&mut state);
23        if result.is_ok() {
24            state.add_eof()
25        }
26        state.finish_with_cache(result, cache)
27    }
28}
29
30impl<'config> CmdLexer<'config> {
31    /// Creates a new `CmdLexer` with the given configuration.
32    pub fn new(config: &'config CmdLanguage) -> Self {
33        Self { config }
34    }
35
36    fn run<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
37        while state.not_at_end() {
38            let start_pos = state.get_position();
39            if let Some(ch) = state.peek() {
40                state.advance(ch.len_utf8());
41                state.add_token(CmdTokenType::Text, start_pos, state.get_position())
42            }
43        }
44        Ok(())
45    }
46}