alba_shell/token.rs
1//! The lexer's output: operators and words. A word is a sequence of
2//! parts because quoting decides, later, what expands and what globs:
3//! `a$B'c'` is one word of three parts.
4
5/// A byte range into the command source string.
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub struct Span {
8 pub start: usize,
9 pub end: usize,
10}
11
12#[derive(Debug, Clone, PartialEq)]
13pub struct Token {
14 pub kind: TokenKind,
15 pub span: Span,
16}
17
18#[derive(Debug, Clone, PartialEq)]
19pub enum TokenKind {
20 Word(Word),
21 AndAnd,
22 OrOr,
23 Pipe,
24 Semi,
25 /// `>`/`>>` (stderr: false) and `2>`/`2>>` (stderr: true). `1>` and
26 /// `1>>` lex as stderr: false: the digit names the fd POSIX-style.
27 RedirectOut {
28 stderr: bool,
29 append: bool,
30 },
31 RedirectIn,
32 /// `2>&1`.
33 StderrToStdout,
34}
35
36#[derive(Debug, Clone, PartialEq)]
37pub struct Word {
38 pub parts: Vec<WordPart>,
39 pub span: Span,
40}
41
42#[derive(Debug, Clone, PartialEq)]
43pub enum WordPart {
44 /// Unquoted text. Glob characters and `~` live here; expansion
45 /// decides what they mean.
46 Text(String),
47 /// One character that a backslash escaped outside of quotes (`\ `,
48 /// `\*`, `\\`). It is a separate part rather than folded into `Text`
49 /// precisely so expansion can still tell it apart: an escaped
50 /// character is literal, so it must neither field-split nor act as
51 /// glob syntax, exactly like a quoted one.
52 Escaped(char),
53 SingleQuoted(String),
54 /// `"..."`: only `Text`, `Var`, and `CmdSubst` appear inside.
55 DoubleQuoted(Vec<WordPart>),
56 /// `$NAME` or `${NAME}`.
57 Var(String),
58 /// `$?`: the exit code of the last completed command. The one special
59 /// parameter in the subset; the others (`$$`, `$!`, `$#`, `$*`, `$@`,
60 /// `$1`..`$9`) are rejected by the lexer.
61 LastExit,
62 /// `$(...)`: the raw inner source, parsed recursively by the parser.
63 /// The span covers the inner source in the outer string, so nested
64 /// diagnostics point at the right place.
65 CmdSubst {
66 source: String,
67 span: Span,
68 },
69}