Skip to main content

nu_parser/
parse_keywords.rs

1use crate::{lite_parser::LiteCommand, parser::parse_call};
2use nu_protocol::{
3    Span, Type,
4    ast::{Expr, Expression, Pipeline},
5    engine::StateWorkingSet,
6};
7
8/// These parser keywords can be aliased
9pub const ALIASABLE_PARSER_KEYWORDS: &[&[u8]] = &[
10    b"if",
11    b"match",
12    b"try",
13    b"overlay",
14    b"overlay hide",
15    b"overlay new",
16    b"overlay use",
17];
18
19/// These parser keywords cannot be aliased (either not possible, or support not yet added)
20pub const UNALIASABLE_PARSER_KEYWORDS: &[&[u8]] = &[
21    b"alias",
22    b"const",
23    b"def",
24    b"extern",
25    b"module",
26    b"use",
27    b"export",
28    b"export alias",
29    b"export const",
30    b"export def",
31    b"export extern",
32    b"export module",
33    b"export use",
34    b"for",
35    b"loop",
36    b"while",
37    b"return",
38    b"break",
39    b"continue",
40    b"let",
41    b"mut",
42    b"hide",
43    b"export-env",
44    b"source-env",
45    b"source",
46    b"run",
47    b"where",
48    b"plugin use",
49];
50
51/// Check whether spans start with a parser keyword that can be aliased
52pub fn is_unaliasable_parser_keyword(working_set: &StateWorkingSet, spans: &[Span]) -> bool {
53    // try two words
54    if let (Some(&span1), Some(&span2)) = (spans.first(), spans.get(1)) {
55        let cmd_name = working_set.get_span_contents(Span::append(span1, span2));
56        return UNALIASABLE_PARSER_KEYWORDS.contains(&cmd_name);
57    }
58
59    // try one word
60    if let Some(&span1) = spans.first() {
61        let cmd_name = working_set.get_span_contents(span1);
62        UNALIASABLE_PARSER_KEYWORDS.contains(&cmd_name)
63    } else {
64        false
65    }
66}
67
68/// This is a new more compact method of calling parse_xxx() functions without repeating the
69/// parse_call() in each function. Remaining keywords can be moved here.
70pub fn parse_keyword(working_set: &mut StateWorkingSet, lite_command: &LiteCommand) -> Pipeline {
71    let orig_parse_errors_len = working_set.parse_errors.len();
72
73    let call_expr = parse_call(
74        working_set,
75        &lite_command.parts,
76        lite_command.parts[0],
77        None,
78    );
79
80    // If an error occurred, don't invoke the keyword-specific functionality
81    if working_set.parse_errors.len() > orig_parse_errors_len {
82        return Pipeline::from_vec(vec![call_expr]);
83    }
84
85    if let Expression {
86        expr: Expr::Call(call),
87        ..
88    } = call_expr.clone()
89    {
90        // Apply parse keyword side effects
91        let cmd = working_set.get_decl(call.decl_id);
92        // check help flag first.
93        if call.named_iter().any(|(flag, _, _)| flag.item == "help") {
94            let call_span = call.span();
95            return Pipeline::from_vec(vec![Expression::new(
96                working_set,
97                Expr::Call(call),
98                call_span,
99                Type::Any,
100            )]);
101        }
102
103        match cmd.name() {
104            "overlay hide" => crate::parse_module::parse_overlay_hide(working_set, call),
105            "overlay new" => crate::parse_module::parse_overlay_new(working_set, call),
106            "overlay use" => crate::parse_module::parse_overlay_use(working_set, call),
107            #[cfg(feature = "plugin")]
108            "plugin use" => crate::parse_source::parse_plugin_use(working_set, call),
109            _ => Pipeline::from_vec(vec![call_expr]),
110        }
111    } else {
112        Pipeline::from_vec(vec![call_expr])
113    }
114}
115
116// Re-exports
117pub use crate::parse_alias::parse_alias;
118pub use crate::parse_bindings::{parse_const, parse_let, parse_mut};
119pub use crate::parse_def::{
120    parse_attribute_block, parse_def, parse_def_predecl, parse_extern, parse_for,
121};
122pub use crate::parse_module::{
123    parse_export_env, parse_export_in_block, parse_export_in_module, parse_hide, parse_module,
124    parse_module_block, parse_module_file_or_dir, parse_overlay_hide, parse_overlay_new,
125    parse_overlay_use, parse_use,
126};
127pub use crate::parse_source::{
128    LIB_DIRS_VAR, find_dirs_var, find_in_dirs, find_main_block_id_in_script, parse_run,
129    parse_run_expr, parse_source, parse_where, parse_where_expr,
130};
131#[cfg(feature = "plugin")]
132pub use crate::parse_source::{PLUGIN_DIRS_VAR, parse_plugin_use};