alba_shell/ast.rs
1//! The parser's output: a fully parsed program tree. Mirrors the token
2//! layer, except `WordPart::CmdSubst` is recursively parsed into its own
3//! `Program` instead of carrying raw source.
4
5use crate::token::Span;
6
7/// A sequence of and/or lists, one per `;` or newline separated item.
8#[derive(Debug, Clone, PartialEq)]
9pub struct Program {
10 pub items: Vec<AndOrList>,
11}
12
13/// A pipeline followed by zero or more `&&`/`||`-joined pipelines,
14/// left-associative and evaluated at equal precedence.
15#[derive(Debug, Clone, PartialEq)]
16pub struct AndOrList {
17 pub first: Pipeline,
18 pub rest: Vec<(AndOrOp, Pipeline)>,
19}
20
21/// The operator joining two pipelines in an `AndOrList`.
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub enum AndOrOp {
24 And,
25 Or,
26}
27
28/// One or more commands joined by `|`, optionally negated with a
29/// leading `!`.
30#[derive(Debug, Clone, PartialEq)]
31pub struct Pipeline {
32 pub negated: bool,
33 pub commands: Vec<Command>,
34}
35
36/// A single command: leading assignments, its words, and its
37/// redirections, in the order they appeared in the source.
38#[derive(Debug, Clone, PartialEq)]
39pub struct Command {
40 pub assignments: Vec<Assignment>,
41 pub words: Vec<Word>,
42 pub redirects: Vec<Redirect>,
43 pub span: Span,
44}
45
46/// A `NAME=value` prefix on a command, or the whole command when no
47/// words follow.
48#[derive(Debug, Clone, PartialEq)]
49pub struct Assignment {
50 pub name: String,
51 pub value: Word,
52}
53
54/// A parsed word: the same part shapes as the token layer, except
55/// command substitution is now a fully parsed `Program`.
56#[derive(Debug, Clone, PartialEq)]
57pub struct Word {
58 pub parts: Vec<WordPart>,
59 pub span: Span,
60}
61
62/// A single fragment of a `Word`, mirroring `token::WordPart` with
63/// `CmdSubst` fully parsed.
64#[derive(Debug, Clone, PartialEq)]
65pub enum WordPart {
66 Text(String),
67 /// One backslash-escaped character, kept distinct from `Text` so
68 /// expansion knows not to split or glob on it. See
69 /// `token::WordPart::Escaped`.
70 Escaped(char),
71 SingleQuoted(String),
72 DoubleQuoted(Vec<WordPart>),
73 Var(String),
74 /// `$?`: the exit code of the last completed command. See
75 /// `token::WordPart::LastExit`.
76 LastExit,
77 CmdSubst(Box<Program>),
78}
79
80/// A redirection attached to a command.
81#[derive(Debug, Clone, PartialEq)]
82pub enum Redirect {
83 Out {
84 stderr: bool,
85 append: bool,
86 target: Word,
87 },
88 In {
89 target: Word,
90 },
91 StderrToStdout,
92}