mod fmt;
use super::SourcePos;
use crate::symbol::Symbol;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Keyword {
Let,
If,
Then,
Else,
End,
For,
In,
Do,
While,
Function,
Return,
Break,
Self_,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Literal {
Nil,
True,
False,
Int(i64),
Float(f64),
Byte(u8),
String(Box<[u8]>),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Operator {
Plus, Minus, Times, Div, Mod,
Equals, NotEquals, Greater, GreaterEquals, Lower, LowerEquals,
Not, And, Or,
Concat, Dot,
Assign,
Try, }
impl Operator {
pub fn is_equality(&self) -> bool {
matches!(self, Self::Equals | Self::NotEquals)
}
pub fn is_comparison(&self) -> bool {
matches!(
self,
Self::Lower | Self::LowerEquals | Self::Greater | Self::GreaterEquals
)
}
pub fn is_term(&self) -> bool {
matches!(self, Self::Plus | Self::Minus)
}
pub fn is_factor(&self) -> bool {
matches!(self, Self::Times | Self::Div | Self::Mod)
}
pub fn is_prefix(&self) -> bool {
matches!(self, Self::Not | Self::Minus)
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum ArgUnit {
Literal(Box<[u8]>),
Dollar { symbol: Symbol,
pos: SourcePos,
}
}
impl ArgUnit {
pub fn is_number(&self) -> bool {
matches!(
self,
Self::Literal(lit) if lit.iter().all(u8::is_ascii_digit)
)
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum ArgExpansion {
Home, Range(i64, i64), Collection(Box<[ArgUnit]>),
Star, Percent, CharClass(Box<[u8]>), }
#[derive(Debug, Clone, PartialEq)]
pub enum ArgPart {
Unquoted(ArgUnit),
SingleQuoted(Box<[u8]>),
DoubleQuoted(Box<[ArgUnit]>),
Expansion(ArgExpansion),
EnvAssign,
}
impl ArgPart {
pub fn is_unquoted_number(&self) -> bool {
matches!(
self,
Self::Unquoted(unit) if unit.is_number()
)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum CommandOperator {
Output { append: bool }, Input { literal: bool }, Try, }
impl CommandOperator {
pub fn is_redirection(&self) -> bool {
matches!(
self,
Self::Output { .. } | Self::Input { .. }
)
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum TokenKind {
Identifier(Symbol),
Keyword(Keyword),
Operator(Operator),
Literal(Literal),
Colon, Comma,
OpenParens, CloseParens,
OpenBracket, OpenDict, CloseBracket,
Command, AsyncCommand, CaptureCommand, CloseCommand,
Argument(Box<[ArgPart]>),
CmdOperator(CommandOperator),
Semicolon, Pipe, }
impl TokenKind {
pub fn is_block_terminator(&self) -> bool {
matches!(
self,
TokenKind::Keyword(Keyword::End) | TokenKind::Keyword(Keyword::Else)
)
}
pub fn is_command_block_starter(&self) -> bool {
matches!(
self,
TokenKind::Command | TokenKind::AsyncCommand | TokenKind::CaptureCommand
)
}
pub fn is_basic_command_terminator(&self) -> bool {
matches!(
self,
TokenKind::Semicolon | TokenKind::Pipe | TokenKind::CloseCommand
)
}
}
#[derive(Debug, Clone)]
pub struct Token {
pub kind: TokenKind,
pub pos: SourcePos,
}