Skip to main content

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}