fish-shell/src/parser_keywords.rs
2025-01-19 18:57:13 +01:00

90 lines
2.4 KiB
Rust

//! Functions having to do with parser keywords, like testing if a function is a block command.
use crate::wchar::prelude::*;
struct ReservedWord {
text: &'static wstr,
is_reserved: bool,
is_super_command: bool,
}
macro_rules! rw {
( ( $text:literal ) ) => {
ReservedWord {
text: L!($text),
is_reserved: true,
is_super_command: false,
}
};
( ( $text:literal, [subcommand] ) ) => {
ReservedWord {
text: L!($text),
is_reserved: true,
is_super_command: true,
}
};
( ( $text:literal, [subcommand], not reserved ) ) => {
ReservedWord {
text: L!($text),
is_reserved: false,
is_super_command: true,
}
};
}
macro_rules! reserved_words {
( $( $reserved_word:tt , ) * ) => {
&[ $( rw!($reserved_word), )* ]
}
}
// Don't forget to add any new reserved keywords to the documentation
const RESERVED_WORDS: &[ReservedWord] = reserved_words!(
("!", [subcommand], not reserved),
("["),
("_"),
("and", [subcommand]),
("argparse"),
("begin", [subcommand]),
("break"),
("builtin", [subcommand]),
("case"),
("command", [subcommand]),
("continue"),
("else", [subcommand]),
("end"),
("eval"),
("exec", [subcommand]),
("for"),
("function"),
("if", [subcommand]),
("not", [subcommand]),
("or", [subcommand]),
("read"),
("return"),
("set"),
("status"),
("string"),
("switch"),
("test"),
("time", [subcommand]),
("while", [subcommand]),
);
fn reserved_word(cmd: &wstr) -> Option<&'static ReservedWord> {
RESERVED_WORDS
.iter()
.find(|reserved_word| reserved_word.text == cmd)
}
/// Tests if the specified command's parameters should be interpreted as another command.
pub fn parser_keywords_is_subcommand(cmd: &impl AsRef<wstr>) -> bool {
reserved_word(cmd.as_ref()).is_some_and(|reserved_word| reserved_word.is_super_command)
}
/// Tests if the specified command is a reserved word, i.e. if it is the name of one of the builtin
/// functions that change the block or command scope, like 'for', 'end' or 'command' or 'exec'.
/// These functions may not be overloaded, so their names are reserved.
pub fn parser_keywords_is_reserved(word: &wstr) -> bool {
reserved_word(word).is_some_and(|reserved_word| reserved_word.is_reserved)
}