2019-06-22 03:36:57 +02:00
|
|
|
use crate::errors::ShellError;
|
2019-08-01 03:58:42 +02:00
|
|
|
use crate::parser::parse::{call_node::*, flag::*, operator::*, pipeline::*, tokens::*};
|
|
|
|
use crate::{Span, Tagged, Text};
|
2019-06-12 19:44:45 +02:00
|
|
|
use derive_new::new;
|
|
|
|
use enum_utils::FromStr;
|
2019-06-29 10:55:42 +02:00
|
|
|
use getset::Getters;
|
|
|
|
use std::fmt;
|
2019-06-11 07:53:04 +02:00
|
|
|
|
2019-06-12 19:44:45 +02:00
|
|
|
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
2019-06-11 07:53:04 +02:00
|
|
|
pub enum TokenNode {
|
|
|
|
Token(Token),
|
2019-06-22 03:36:57 +02:00
|
|
|
#[allow(unused)]
|
2019-08-01 03:58:42 +02:00
|
|
|
Call(Tagged<CallNode>),
|
|
|
|
Delimited(Tagged<DelimitedNode>),
|
|
|
|
Pipeline(Tagged<Pipeline>),
|
|
|
|
Operator(Tagged<Operator>),
|
|
|
|
Flag(Tagged<Flag>),
|
2019-07-15 23:16:27 +02:00
|
|
|
Member(Span),
|
2019-06-22 03:36:57 +02:00
|
|
|
Whitespace(Span),
|
|
|
|
#[allow(unused)]
|
2019-08-01 03:58:42 +02:00
|
|
|
Error(Tagged<Box<ShellError>>),
|
|
|
|
Path(Tagged<PathNode>),
|
2019-06-12 19:44:45 +02:00
|
|
|
}
|
|
|
|
|
2019-06-29 10:55:42 +02:00
|
|
|
pub struct DebugTokenNode<'a> {
|
|
|
|
node: &'a TokenNode,
|
|
|
|
source: &'a Text,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Debug for DebugTokenNode<'a> {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
match self.node {
|
|
|
|
TokenNode::Token(t) => write!(f, "{:?}", t.debug(self.source)),
|
|
|
|
TokenNode::Call(s) => {
|
|
|
|
write!(f, "(")?;
|
|
|
|
|
|
|
|
write!(f, "{:?}", s.head().debug(self.source))?;
|
|
|
|
|
|
|
|
if let Some(children) = s.children() {
|
|
|
|
for child in children {
|
|
|
|
write!(f, "{:?}", child.debug(self.source))?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(f, ")")
|
|
|
|
}
|
|
|
|
|
|
|
|
TokenNode::Delimited(d) => {
|
|
|
|
write!(
|
|
|
|
f,
|
|
|
|
"{}",
|
|
|
|
match d.delimiter {
|
|
|
|
Delimiter::Brace => "{",
|
|
|
|
Delimiter::Paren => "(",
|
|
|
|
Delimiter::Square => "[",
|
|
|
|
}
|
|
|
|
)?;
|
|
|
|
|
|
|
|
for child in d.children() {
|
|
|
|
write!(f, "{:?}", child.debug(self.source))?;
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(
|
|
|
|
f,
|
|
|
|
"{}",
|
|
|
|
match d.delimiter {
|
|
|
|
Delimiter::Brace => "}",
|
|
|
|
Delimiter::Paren => ")",
|
|
|
|
Delimiter::Square => "]",
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
2019-06-29 18:32:58 +02:00
|
|
|
TokenNode::Pipeline(_) => write!(f, "<todo:pipeline>"),
|
2019-06-29 10:55:42 +02:00
|
|
|
TokenNode::Error(s) => write!(f, "<error> for {:?}", s.span().slice(self.source)),
|
|
|
|
rest => write!(f, "{}", rest.span().slice(self.source)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<&TokenNode> for Span {
|
|
|
|
fn from(token: &TokenNode) -> Span {
|
|
|
|
token.span()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-15 04:59:35 +02:00
|
|
|
impl TokenNode {
|
|
|
|
pub fn span(&self) -> Span {
|
|
|
|
match self {
|
2019-08-01 03:58:42 +02:00
|
|
|
TokenNode::Token(t) => t.span(),
|
|
|
|
TokenNode::Call(s) => s.span(),
|
|
|
|
TokenNode::Delimited(s) => s.span(),
|
|
|
|
TokenNode::Pipeline(s) => s.span(),
|
|
|
|
TokenNode::Operator(s) => s.span(),
|
|
|
|
TokenNode::Flag(s) => s.span(),
|
2019-07-15 23:16:27 +02:00
|
|
|
TokenNode::Member(s) => *s,
|
2019-06-22 03:36:57 +02:00
|
|
|
TokenNode::Whitespace(s) => *s,
|
2019-08-01 03:58:42 +02:00
|
|
|
TokenNode::Error(s) => s.span(),
|
|
|
|
TokenNode::Path(s) => s.span(),
|
2019-06-15 04:59:35 +02:00
|
|
|
}
|
|
|
|
}
|
2019-06-22 03:36:57 +02:00
|
|
|
|
2019-07-15 23:16:27 +02:00
|
|
|
pub fn type_name(&self) -> String {
|
|
|
|
match self {
|
|
|
|
TokenNode::Token(t) => t.type_name(),
|
2019-07-16 09:08:35 +02:00
|
|
|
TokenNode::Call(_) => "command",
|
2019-07-15 23:16:27 +02:00
|
|
|
TokenNode::Delimited(d) => d.type_name(),
|
2019-07-16 09:08:35 +02:00
|
|
|
TokenNode::Pipeline(_) => "pipeline",
|
|
|
|
TokenNode::Operator(_) => "operator",
|
|
|
|
TokenNode::Flag(_) => "flag",
|
|
|
|
TokenNode::Member(_) => "member",
|
|
|
|
TokenNode::Whitespace(_) => "whitespace",
|
|
|
|
TokenNode::Error(_) => "error",
|
|
|
|
TokenNode::Path(_) => "path",
|
2019-07-15 23:16:27 +02:00
|
|
|
}
|
|
|
|
.to_string()
|
|
|
|
}
|
|
|
|
|
2019-06-29 10:55:42 +02:00
|
|
|
pub fn debug(&'a self, source: &'a Text) -> DebugTokenNode<'a> {
|
|
|
|
DebugTokenNode { node: self, source }
|
|
|
|
}
|
|
|
|
|
2019-06-22 22:46:16 +02:00
|
|
|
pub fn as_external_arg(&self, source: &Text) -> String {
|
2019-06-22 03:36:57 +02:00
|
|
|
self.span().slice(source).to_string()
|
|
|
|
}
|
|
|
|
|
2019-06-22 22:46:16 +02:00
|
|
|
pub fn source(&self, source: &'a Text) -> &'a str {
|
2019-06-22 03:36:57 +02:00
|
|
|
self.span().slice(source)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_bare(&self) -> bool {
|
|
|
|
match self {
|
2019-08-01 03:58:42 +02:00
|
|
|
TokenNode::Token(Tagged {
|
2019-06-22 03:36:57 +02:00
|
|
|
item: RawToken::Bare,
|
|
|
|
..
|
|
|
|
}) => true,
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-01 03:58:42 +02:00
|
|
|
crate fn as_flag(&self, value: &str, source: &Text) -> Option<Tagged<Flag>> {
|
2019-06-22 03:36:57 +02:00
|
|
|
match self {
|
|
|
|
TokenNode::Flag(
|
2019-08-01 03:58:42 +02:00
|
|
|
flag @ Tagged {
|
2019-06-22 03:36:57 +02:00
|
|
|
item: Flag { .. }, ..
|
|
|
|
},
|
|
|
|
) if value == flag.name().slice(source) => Some(*flag),
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-23 19:35:43 +02:00
|
|
|
pub fn as_pipeline(&self) -> Result<Pipeline, ShellError> {
|
2019-06-22 03:36:57 +02:00
|
|
|
match self {
|
2019-08-01 03:58:42 +02:00
|
|
|
TokenNode::Pipeline(Tagged { item, .. }) => Ok(item.clone()),
|
2019-06-22 03:36:57 +02:00
|
|
|
_ => Err(ShellError::string("unimplemented")),
|
|
|
|
}
|
|
|
|
}
|
2019-06-15 04:59:35 +02:00
|
|
|
}
|
|
|
|
|
2019-06-29 10:55:42 +02:00
|
|
|
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Getters, new)]
|
|
|
|
#[get = "crate"]
|
2019-06-12 19:44:45 +02:00
|
|
|
pub struct DelimitedNode {
|
|
|
|
delimiter: Delimiter,
|
|
|
|
children: Vec<TokenNode>,
|
|
|
|
}
|
|
|
|
|
2019-07-15 23:16:27 +02:00
|
|
|
impl DelimitedNode {
|
|
|
|
pub fn type_name(&self) -> &'static str {
|
|
|
|
match self.delimiter {
|
|
|
|
Delimiter::Brace => "braced expression",
|
|
|
|
Delimiter::Paren => "parenthesized expression",
|
|
|
|
Delimiter::Square => "array literal or index operator",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-12 19:44:45 +02:00
|
|
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, FromStr)]
|
|
|
|
pub enum Delimiter {
|
|
|
|
Paren,
|
|
|
|
Brace,
|
|
|
|
Square,
|
2019-06-11 07:53:04 +02:00
|
|
|
}
|
2019-06-13 07:33:38 +02:00
|
|
|
|
2019-06-29 10:55:42 +02:00
|
|
|
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Getters, new)]
|
|
|
|
#[get = "crate"]
|
2019-06-13 07:33:38 +02:00
|
|
|
pub struct PathNode {
|
|
|
|
head: Box<TokenNode>,
|
2019-06-14 22:55:05 +02:00
|
|
|
tail: Vec<TokenNode>,
|
2019-06-13 07:33:38 +02:00
|
|
|
}
|