luau_parser/types/
traits.rs

1//! Module holding all trait definitions in this crate.
2
3use luau_lexer::prelude::{Lexer, ParseError, Token};
4
5use crate::types::Range;
6
7/// A trait to print the token as-is, while preserving all user spaces, comments
8/// and styling.
9pub trait Print {
10    /// Prints only the very final trivia. Used for the default implementation of
11    /// [`Print::print`], which just joins [`Print::print_without_final_trivia`]
12    /// and this function.
13    fn print_final_trivia(&self) -> String;
14
15    /// Prints the whole token including all surrounding trivia, excluding the
16    /// very last trailing trivia.
17    fn print_without_final_trivia(&self) -> String;
18
19    /// Prints the whole token including all surrounding trivia.
20    #[inline]
21    fn print(&self) -> String {
22        self.print_without_final_trivia() + &self.print_final_trivia()
23    }
24}
25
26/// A trait that to parse this struct from a [`lexer`](Lexer) and starting with
27/// a specific [`token`](Token).
28pub trait Parse<O = Self> {
29    /// Try parsing the current item, starting from the passed token.
30    fn parse(token: Token, lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<O>;
31}
32
33/// A wrapper trait for [`Parse`] where it would reset the lexer's state upon
34/// failure.
35pub(crate) trait TryParse<O = Self>
36where
37    O: Parse<O>,
38{
39    /// Try parsing and reset the lexer's state upon failure.
40    fn try_parse(lexer: &mut Lexer, errors: &mut Vec<ParseError>) -> Option<O> {
41        let state = lexer.save_state();
42
43        match O::parse(lexer.next_token(), lexer, errors) {
44            value @ Some(_) => value,
45            None => {
46                lexer.set_state(state);
47
48                None
49            }
50        }
51    }
52}
53
54/// A trait that to parse this struct from a [`lexer`](Lexer) and starting with
55/// a specific [`token`](Token) and with specific arguments.
56pub trait ParseWithArgs<T, O = Self> {
57    /// Try parsing the current item, starting from the passed token with the
58    /// passed arguments.
59    fn parse_with(
60        token: Token,
61        lexer: &mut Lexer,
62        errors: &mut Vec<ParseError>,
63        args: T,
64    ) -> Option<O>;
65}
66
67/// A wrapper trait for [`ParseWithArgs`] where it would reset the lexer's state
68/// upon failure.
69pub(crate) trait TryParseWithArgs<T, O = Self, O2 = O>
70where
71    O2: ParseWithArgs<T, O>,
72{
73    /// Try parsing and reset the lexer's state upon failure.
74    #[inline]
75    fn try_parse_with(lexer: &mut Lexer, errors: &mut Vec<ParseError>, args: T) -> Option<O> {
76        let state = lexer.save_state();
77
78        match O2::parse_with(lexer.next_token(), lexer, errors, args) {
79            value @ Some(_) => value,
80            None => {
81                lexer.set_state(state);
82
83                None
84            }
85        }
86    }
87}
88
89/// Errors that may occur during [`get_range`](GetRangeError). They should
90/// never happen if [`Cst.status`](crate::types::Cst::status) is
91/// [`AstStatus::Complete`](crate::types::AstStatus::Complete).
92#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
93#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
94pub enum GetRangeError {
95    /// This is an `ERROR` variant and thus spans no range in the source code.
96    ErrorVariant,
97
98    /// This is an empty list and thus spans no range in the source code.
99    EmptyList,
100
101    /// This is an empty block and thus spans no range in the source code.
102    EmptyBlock,
103
104    /// This is either
105    /// * [`TableKey::UndefinedString`](crate::types::TableKey::UndefinedString), or
106    /// * [`TableKey::UndefinedNumber`](crate::types::TableKey::UndefinedNumber)
107    ///
108    /// which don't actually exist in the source code and are added by the parser.
109    UndefinedKey,
110}
111
112/// A trait for getting the range for this specific item.
113pub trait GetRange {
114    /// Get the range of the node. This will only fail if
115    /// [`Cst.status`](crate::types::Cst::status) is
116    /// [`AstStatus::HasErrors`](crate::types::AstStatus::HasErrors).
117    fn get_range(&self) -> Result<Range, GetRangeError>;
118}