mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-06-04 15:51:15 -03:00
committed by
Johannes Altmanninger
parent
7aec6c55f9
commit
20da9a2b51
98
src/ast.rs
98
src/ast.rs
@@ -591,11 +591,15 @@ fn accept_mut<V: NodeVisitorMut>(&mut self, visitor: &mut V) {
|
||||
}
|
||||
|
||||
/// Implement the acceptor trait for the given branch node.
|
||||
macro_rules! implement_acceptor_for_branch {
|
||||
macro_rules! Acceptor {
|
||||
(
|
||||
$name:ident
|
||||
$(, $field_name:ident )*
|
||||
$(,)?
|
||||
$(#[$_m:meta])*
|
||||
$_v:vis struct $name:ident {
|
||||
$(
|
||||
$(#[$_fm:meta])*
|
||||
$_fv:vis $field_name:ident : $_ft:ty
|
||||
),* $(,)?
|
||||
}
|
||||
) => {
|
||||
impl Acceptor for $name {
|
||||
#[allow(unused_variables)]
|
||||
@@ -621,17 +625,16 @@ fn accept_mut<V: NodeVisitorMut>(&mut self, visitor: &mut V) {
|
||||
visitor.did_visit_fields_of(self, flow);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// A redirection has an operator like > or 2>, and a target like /dev/null or &1.
|
||||
/// Note that pipes are not redirections.
|
||||
#[derive(Default, Debug, Node!)]
|
||||
#[derive(Default, Debug, Node!, Acceptor!)]
|
||||
pub struct Redirection {
|
||||
pub oper: TokenRedirection,
|
||||
pub target: String_,
|
||||
}
|
||||
implement_acceptor_for_branch!(Redirection, oper, target);
|
||||
|
||||
impl CheckParse for Redirection {
|
||||
fn can_be_parsed(pop: &mut Populator<'_>) -> bool {
|
||||
@@ -761,7 +764,7 @@ fn accept_mut<V: NodeVisitorMut>(&mut self, visitor: &mut V) {
|
||||
|
||||
/// A job is a non-empty list of statements, separated by pipes. (Non-empty is useful for cases
|
||||
/// like if statements, where we require a command).
|
||||
#[derive(Default, Debug, Node!)]
|
||||
#[derive(Default, Debug, Node!, Acceptor!)]
|
||||
pub struct JobPipeline {
|
||||
/// Maybe the time keyword.
|
||||
pub time: Option<KeywordTime>,
|
||||
@@ -774,10 +777,9 @@ pub struct JobPipeline {
|
||||
/// Maybe backgrounded.
|
||||
pub bg: Option<TokenBackground>,
|
||||
}
|
||||
implement_acceptor_for_branch!(JobPipeline, time, variables, statement, continuation, bg);
|
||||
|
||||
/// A job_conjunction is a job followed by a && or || continuations.
|
||||
#[derive(Default, Debug, Node!)]
|
||||
#[derive(Default, Debug, Node!, Acceptor!)]
|
||||
pub struct JobConjunction {
|
||||
/// The job conjunction decorator.
|
||||
pub decorator: Option<JobConjunctionDecorator>,
|
||||
@@ -790,7 +792,6 @@ pub struct JobConjunction {
|
||||
/// only fail to be present if we ran out of tokens.
|
||||
pub semi_nl: Option<SemiNl>,
|
||||
}
|
||||
implement_acceptor_for_branch!(JobConjunction, decorator, job, continuations, semi_nl);
|
||||
|
||||
impl CheckParse for JobConjunction {
|
||||
fn can_be_parsed(pop: &mut Populator<'_>) -> bool {
|
||||
@@ -805,7 +806,7 @@ fn can_be_parsed(pop: &mut Populator<'_>) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Node!)]
|
||||
#[derive(Default, Debug, Node!, Acceptor!)]
|
||||
pub struct ForHeader {
|
||||
/// 'for'
|
||||
pub kw_for: KeywordFor,
|
||||
@@ -818,18 +819,16 @@ pub struct ForHeader {
|
||||
/// newline or semicolon
|
||||
pub semi_nl: SemiNl,
|
||||
}
|
||||
implement_acceptor_for_branch!(ForHeader, kw_for, var_name, kw_in, args, semi_nl);
|
||||
|
||||
#[derive(Default, Debug, Node!)]
|
||||
#[derive(Default, Debug, Node!, Acceptor!)]
|
||||
pub struct WhileHeader {
|
||||
/// 'while'
|
||||
pub kw_while: KeywordWhile,
|
||||
pub condition: JobConjunction,
|
||||
pub andor_tail: AndorJobList,
|
||||
}
|
||||
implement_acceptor_for_branch!(WhileHeader, kw_while, condition, andor_tail);
|
||||
|
||||
#[derive(Default, Debug, Node!)]
|
||||
#[derive(Default, Debug, Node!, Acceptor!)]
|
||||
pub struct FunctionHeader {
|
||||
pub kw_function: KeywordFunction,
|
||||
/// functions require at least one argument.
|
||||
@@ -837,18 +836,16 @@ pub struct FunctionHeader {
|
||||
pub args: ArgumentList,
|
||||
pub semi_nl: SemiNl,
|
||||
}
|
||||
implement_acceptor_for_branch!(FunctionHeader, kw_function, first_arg, args, semi_nl);
|
||||
|
||||
#[derive(Default, Debug, Node!)]
|
||||
#[derive(Default, Debug, Node!, Acceptor!)]
|
||||
pub struct BeginHeader {
|
||||
pub kw_begin: KeywordBegin,
|
||||
/// Note that 'begin' does NOT require a semi or nl afterwards.
|
||||
/// This is valid: begin echo hi; end
|
||||
pub semi_nl: Option<SemiNl>,
|
||||
}
|
||||
implement_acceptor_for_branch!(BeginHeader, kw_begin, semi_nl);
|
||||
|
||||
#[derive(Default, Debug, Node!)]
|
||||
#[derive(Default, Debug, Node!, Acceptor!)]
|
||||
pub struct BlockStatement {
|
||||
/// A header like for, while, etc.
|
||||
pub header: BlockStatementHeader,
|
||||
@@ -859,9 +856,8 @@ pub struct BlockStatement {
|
||||
/// Arguments and redirections associated with the block.
|
||||
pub args_or_redirs: ArgumentOrRedirectionList,
|
||||
}
|
||||
implement_acceptor_for_branch!(BlockStatement, header, jobs, end, args_or_redirs);
|
||||
|
||||
#[derive(Default, Debug, Node!)]
|
||||
#[derive(Default, Debug, Node!, Acceptor!)]
|
||||
pub struct BraceStatement {
|
||||
/// The opening brace, in command position.
|
||||
pub left_brace: TokenLeftBrace,
|
||||
@@ -872,15 +868,8 @@ pub struct BraceStatement {
|
||||
/// Arguments and redirections associated with the block.
|
||||
pub args_or_redirs: ArgumentOrRedirectionList,
|
||||
}
|
||||
implement_acceptor_for_branch!(
|
||||
BraceStatement,
|
||||
left_brace,
|
||||
jobs,
|
||||
right_brace,
|
||||
args_or_redirs
|
||||
);
|
||||
|
||||
#[derive(Default, Debug, Node!)]
|
||||
#[derive(Default, Debug, Node!, Acceptor!)]
|
||||
pub struct IfClause {
|
||||
/// The 'if' keyword.
|
||||
pub kw_if: KeywordIf,
|
||||
@@ -891,16 +880,14 @@ pub struct IfClause {
|
||||
/// The body to execute if the condition is true.
|
||||
pub body: JobList,
|
||||
}
|
||||
implement_acceptor_for_branch!(IfClause, kw_if, condition, andor_tail, body);
|
||||
|
||||
#[derive(Default, Debug, Node!)]
|
||||
#[derive(Default, Debug, Node!, Acceptor!)]
|
||||
pub struct ElseifClause {
|
||||
/// The 'else' keyword.
|
||||
pub kw_else: KeywordElse,
|
||||
/// The 'if' clause following it.
|
||||
pub if_clause: IfClause,
|
||||
}
|
||||
implement_acceptor_for_branch!(ElseifClause, kw_else, if_clause);
|
||||
impl CheckParse for ElseifClause {
|
||||
fn can_be_parsed(pop: &mut Populator<'_>) -> bool {
|
||||
pop.peek_token(0).keyword == ParseKeyword::Else
|
||||
@@ -910,21 +897,20 @@ fn can_be_parsed(pop: &mut Populator<'_>) -> bool {
|
||||
|
||||
define_list_node!(ElseifClauseList, ElseifClause);
|
||||
|
||||
#[derive(Default, Debug, Node!)]
|
||||
#[derive(Default, Debug, Node!, Acceptor!)]
|
||||
pub struct ElseClause {
|
||||
/// else ; body
|
||||
pub kw_else: KeywordElse,
|
||||
pub semi_nl: Option<SemiNl>,
|
||||
pub body: JobList,
|
||||
}
|
||||
implement_acceptor_for_branch!(ElseClause, kw_else, semi_nl, body);
|
||||
impl CheckParse for ElseClause {
|
||||
fn can_be_parsed(pop: &mut Populator<'_>) -> bool {
|
||||
pop.peek_token(0).keyword == ParseKeyword::Else
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Node!)]
|
||||
#[derive(Default, Debug, Node!, Acceptor!)]
|
||||
pub struct IfStatement {
|
||||
/// if part
|
||||
pub if_clause: IfClause,
|
||||
@@ -937,16 +923,8 @@ pub struct IfStatement {
|
||||
/// block args / redirs
|
||||
pub args_or_redirs: ArgumentOrRedirectionList,
|
||||
}
|
||||
implement_acceptor_for_branch!(
|
||||
IfStatement,
|
||||
if_clause,
|
||||
elseif_clauses,
|
||||
else_clause,
|
||||
end,
|
||||
args_or_redirs
|
||||
);
|
||||
|
||||
#[derive(Default, Debug, Node!)]
|
||||
#[derive(Default, Debug, Node!, Acceptor!)]
|
||||
pub struct CaseItem {
|
||||
/// case \<arguments\> ; body
|
||||
pub kw_case: KeywordCase,
|
||||
@@ -954,14 +932,13 @@ pub struct CaseItem {
|
||||
pub semi_nl: SemiNl,
|
||||
pub body: JobList,
|
||||
}
|
||||
implement_acceptor_for_branch!(CaseItem, kw_case, arguments, semi_nl, body);
|
||||
impl CheckParse for CaseItem {
|
||||
fn can_be_parsed(pop: &mut Populator<'_>) -> bool {
|
||||
pop.peek_token(0).keyword == ParseKeyword::Case
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Node!)]
|
||||
#[derive(Default, Debug, Node!, Acceptor!)]
|
||||
pub struct SwitchStatement {
|
||||
/// switch \<argument\> ; body ; end args_redirs
|
||||
pub kw_switch: KeywordSwitch,
|
||||
@@ -971,19 +948,10 @@ pub struct SwitchStatement {
|
||||
pub end: KeywordEnd,
|
||||
pub args_or_redirs: ArgumentOrRedirectionList,
|
||||
}
|
||||
implement_acceptor_for_branch!(
|
||||
SwitchStatement,
|
||||
kw_switch,
|
||||
argument,
|
||||
semi_nl,
|
||||
cases,
|
||||
end,
|
||||
args_or_redirs
|
||||
);
|
||||
|
||||
/// A decorated_statement is a command with a list of arguments_or_redirections, possibly with
|
||||
/// "builtin" or "command" or "exec"
|
||||
#[derive(Default, Debug, Node!)]
|
||||
#[derive(Default, Debug, Node!, Acceptor!)]
|
||||
pub struct DecoratedStatement {
|
||||
/// An optional decoration (command, builtin, exec, etc).
|
||||
pub opt_decoration: Option<DecoratedStatementDecorator>,
|
||||
@@ -992,10 +960,9 @@ pub struct DecoratedStatement {
|
||||
/// Args and redirs
|
||||
pub args_or_redirs: ArgumentOrRedirectionList,
|
||||
}
|
||||
implement_acceptor_for_branch!(DecoratedStatement, opt_decoration, command, args_or_redirs);
|
||||
|
||||
/// A not statement like `not true` or `! true`
|
||||
#[derive(Default, Debug, Node!)]
|
||||
#[derive(Default, Debug, Node!, Acceptor!)]
|
||||
pub struct NotStatement {
|
||||
/// Keyword, either not or exclam.
|
||||
pub kw: KeywordNot,
|
||||
@@ -1003,16 +970,14 @@ pub struct NotStatement {
|
||||
pub variables: VariableAssignmentList,
|
||||
pub contents: Statement,
|
||||
}
|
||||
implement_acceptor_for_branch!(NotStatement, kw, time, variables, contents);
|
||||
|
||||
#[derive(Default, Debug, Node!)]
|
||||
#[derive(Default, Debug, Node!, Acceptor!)]
|
||||
pub struct JobContinuation {
|
||||
pub pipe: TokenPipe,
|
||||
pub newlines: MaybeNewlines,
|
||||
pub variables: VariableAssignmentList,
|
||||
pub statement: Statement,
|
||||
}
|
||||
implement_acceptor_for_branch!(JobContinuation, pipe, newlines, variables, statement);
|
||||
impl CheckParse for JobContinuation {
|
||||
fn can_be_parsed(pop: &mut Populator<'_>) -> bool {
|
||||
pop.peek_type(0) == ParseTokenType::pipe
|
||||
@@ -1021,7 +986,7 @@ fn can_be_parsed(pop: &mut Populator<'_>) -> bool {
|
||||
|
||||
define_list_node!(JobContinuationList, JobContinuation);
|
||||
|
||||
#[derive(Default, Debug, Node!)]
|
||||
#[derive(Default, Debug, Node!, Acceptor!)]
|
||||
pub struct JobConjunctionContinuation {
|
||||
/// The && or || token.
|
||||
pub conjunction: TokenConjunction,
|
||||
@@ -1029,7 +994,6 @@ pub struct JobConjunctionContinuation {
|
||||
/// The job itself.
|
||||
pub job: JobPipeline,
|
||||
}
|
||||
implement_acceptor_for_branch!(JobConjunctionContinuation, conjunction, newlines, job);
|
||||
impl CheckParse for JobConjunctionContinuation {
|
||||
fn can_be_parsed(pop: &mut Populator<'_>) -> bool {
|
||||
let typ = pop.peek_type(0);
|
||||
@@ -1040,11 +1004,10 @@ fn can_be_parsed(pop: &mut Populator<'_>) -> bool {
|
||||
/// An andor_job just wraps a job, but requires that the job have an 'and' or 'or' job_decorator.
|
||||
/// Note this is only used for andor_job_list; jobs that are not part of an andor_job_list are not
|
||||
/// instances of this.
|
||||
#[derive(Default, Debug, Node!)]
|
||||
#[derive(Default, Debug, Node!, Acceptor!)]
|
||||
pub struct AndorJob {
|
||||
pub job: JobConjunction,
|
||||
}
|
||||
implement_acceptor_for_branch!(AndorJob, job);
|
||||
impl CheckParse for AndorJob {
|
||||
fn can_be_parsed(pop: &mut Populator<'_>) -> bool {
|
||||
let keyword = pop.peek_token(0).keyword;
|
||||
@@ -1066,11 +1029,10 @@ fn can_be_parsed(pop: &mut Populator<'_>) -> bool {
|
||||
/// A freestanding_argument_list is equivalent to a normal argument list, except it may contain
|
||||
/// TOK_END (newlines, and even semicolons, for historical reasons).
|
||||
/// In practice the tok_ends are ignored by fish code so we do not bother to store them.
|
||||
#[derive(Default, Debug, Node!)]
|
||||
#[derive(Default, Debug, Node!, Acceptor!)]
|
||||
pub struct FreestandingArgumentList {
|
||||
pub arguments: ArgumentList,
|
||||
}
|
||||
implement_acceptor_for_branch!(FreestandingArgumentList, arguments);
|
||||
|
||||
define_list_node!(JobConjunctionContinuationList, JobConjunctionContinuation);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user