Skip to content

Commit

Permalink
Expand tilde in patterns.
Browse files Browse the repository at this point in the history
  • Loading branch information
andrasio committed Oct 27, 2019
1 parent 1b3a094 commit 540cc40
Show file tree
Hide file tree
Showing 12 changed files with 136 additions and 150 deletions.
8 changes: 4 additions & 4 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,10 @@ impl ShellError {
// pub fn string(title: impl Into<String>) -> ShellError {
// ProximateShellError::String(StringError::new(title.into(), String::new())).start()
// }
//
// pub(crate) fn unreachable(title: impl Into<String>) -> ShellError {
// ShellError::untagged_runtime_error(&format!("BUG: Unreachable: {}", title.into()))
// }

pub(crate) fn unimplemented(title: impl Into<String>) -> ShellError {
ShellError::untagged_runtime_error(&format!("Unimplemented: {}", title.into()))
Expand All @@ -375,10 +379,6 @@ impl ShellError {
pub(crate) fn unexpected(title: impl Into<String>) -> ShellError {
ShellError::untagged_runtime_error(&format!("Unexpected: {}", title.into()))
}

pub(crate) fn unreachable(title: impl Into<String>) -> ShellError {
ShellError::untagged_runtime_error(&format!("BUG: Unreachable: {}", title.into()))
}
}

#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Serialize, Deserialize)]
Expand Down
2 changes: 1 addition & 1 deletion src/evaluate/evaluator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ fn evaluate_literal(literal: Tagged<&hir::Literal>, source: &Text) -> Tagged<Val
hir::Literal::Number(int) => int.into(),
hir::Literal::Size(int, unit) => unit.compute(int),
hir::Literal::String(tag) => Value::string(tag.slice(source)),
hir::Literal::GlobPattern => Value::pattern(literal.tag().slice(source)),
hir::Literal::GlobPattern(pattern) => Value::pattern(pattern),
hir::Literal::Bare => Value::string(literal.tag().slice(source)),
};

Expand Down
12 changes: 6 additions & 6 deletions src/parser/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,8 @@ impl Expression {
RawExpression::Literal(Literal::Bare).spanned(span)
}

pub(crate) fn pattern(span: impl Into<Span>) -> Expression {
RawExpression::Literal(Literal::GlobPattern).spanned(span.into())
pub(crate) fn pattern(inner: impl Into<String>, outer: impl Into<Span>) -> Expression {
RawExpression::Literal(Literal::GlobPattern(inner.into())).spanned(outer.into())
}

pub(crate) fn variable(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
Expand Down Expand Up @@ -297,7 +297,7 @@ pub enum Literal {
Number(Number),
Size(Number, Unit),
String(Span),
GlobPattern,
GlobPattern(String),
Bare,
}

Expand All @@ -315,7 +315,7 @@ impl std::fmt::Display for Tagged<&Literal> {
Literal::Number(number) => write!(f, "{}", number),
Literal::Size(number, unit) => write!(f, "{}{}", number, unit.as_str()),
Literal::String(_) => write!(f, "String{{ {}..{} }}", span.start(), span.end()),
Literal::GlobPattern => write!(f, "Glob{{ {}..{} }}", span.start(), span.end()),
Literal::GlobPattern(_) => write!(f, "Glob{{ {}..{} }}", span.start(), span.end()),
Literal::Bare => write!(f, "Bare{{ {}..{} }}", span.start(), span.end()),
}
}
Expand All @@ -327,7 +327,7 @@ impl ToDebug for Spanned<&Literal> {
Literal::Number(number) => write!(f, "{:?}", number),
Literal::Size(number, unit) => write!(f, "{:?}{:?}", *number, unit),
Literal::String(tag) => write!(f, "{}", tag.slice(source)),
Literal::GlobPattern => write!(f, "{}", self.span.slice(source)),
Literal::GlobPattern(_) => write!(f, "{}", self.span.slice(source)),
Literal::Bare => write!(f, "{}", self.span.slice(source)),
}
}
Expand All @@ -340,7 +340,7 @@ impl Literal {
Literal::Size(..) => "size",
Literal::String(..) => "string",
Literal::Bare => "string",
Literal::GlobPattern => "pattern",
Literal::GlobPattern(_) => "pattern",
}
}
}
Expand Down
32 changes: 5 additions & 27 deletions src/parser/hir/baseline_parse/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::parser::hir::syntax_shape::*;
use crate::parser::hir::TokensIterator;
use crate::parser::parse::token_tree_builder::{CurriedToken, TokenTreeBuilder as b};
use crate::parser::TokenNode;
use crate::{Span, SpannedItem, Tag, Tagged, Text};
use crate::{Span, SpannedItem, Tag, Text};
use pretty_assertions::assert_eq;
use std::fmt::Debug;

Expand Down Expand Up @@ -63,7 +63,7 @@ fn test_parse_command() {
vec![b::bare("ls"), b::sp(), b::pattern("*.txt")],
|tokens| {
let bare = tokens[0].expect_bare();
let pat = tokens[2].span();
let pattern = tokens[2].expect_pattern();

ClassifiedCommand::Internal(InternalCommand::new(
"ls".to_string(),
Expand All @@ -73,7 +73,7 @@ fn test_parse_command() {
},
hir::Call {
head: Box::new(hir::RawExpression::Command(bare).spanned(bare)),
positional: Some(vec![hir::Expression::pattern(pat)]),
positional: Some(vec![hir::Expression::pattern("*.txt", pattern)]),
named: None,
},
))
Expand All @@ -84,41 +84,19 @@ fn test_parse_command() {
// )
},
);

parse_tokens(
VariablePathShape,
vec![
b::var("cpu"),
b::op("."),
b::bare("amount"),
b::op("."),
b::string("max ghz"),
],
|tokens| {
let (outer_var, inner_var) = tokens[0].expect_var();
let amount = tokens[2].expect_bare();
let (outer_max_ghz, _) = tokens[4].expect_string();

hir::Expression::path(
hir::Expression::variable(inner_var, outer_var),
vec!["amount".spanned(amount), "max ghz".spanned(outer_max_ghz)],
outer_var.until(outer_max_ghz),
)
},
);
}

fn parse_tokens<T: Eq + Debug>(
shape: impl ExpandSyntax<Output = T>,
tokens: Vec<CurriedToken>,
expected: impl FnOnce(Tagged<&[TokenNode]>) -> T,
expected: impl FnOnce(&[TokenNode]) -> T,
) {
let tokens = b::token_list(tokens);
let (tokens, source) = b::build(tokens);

ExpandContext::with_empty(&Text::from(source), |context| {
let tokens = tokens.expect_list();
let mut iterator = TokensIterator::all(tokens.item, *context.span());
let mut iterator = TokensIterator::all(tokens, *context.span());

let expr = expand_syntax(&shape, &mut iterator, &context);

Expand Down
14 changes: 5 additions & 9 deletions src/parser/hir/syntax_shape.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,18 +497,18 @@ pub(crate) fn expand_expr<'a, 'b, T: ExpandExpression>(
token_nodes: &'b mut TokensIterator<'a>,
context: &ExpandContext,
) -> Result<hir::Expression, ShellError> {
trace!(target: "nu::expand_syntax", "before {} :: {:?}", std::any::type_name::<T>(), debug_tokens(token_nodes.state(), context.source));
trace!(target: "nu::expand_expression", "before {} :: {:?}", std::any::type_name::<T>(), debug_tokens(token_nodes.state(), context.source));

let result = shape.expand_syntax(token_nodes, context);
let result = shape.expand_expr(token_nodes, context);

match result {
Err(err) => {
trace!(target: "nu::expand_syntax", "error :: {} :: {:?}", err, debug_tokens(token_nodes.state(), context.source));
trace!(target: "nu::expand_expression", "error :: {} :: {:?}", err, debug_tokens(token_nodes.state(), context.source));
Err(err)
}

Ok(result) => {
trace!(target: "nu::expand_syntax", "ok :: {:?} :: {:?}", result, debug_tokens(token_nodes.state(), context.source));
trace!(target: "nu::expand_expression", "ok :: {:?} :: {:?}", result, debug_tokens(token_nodes.state(), context.source));
Ok(result)
}
}
Expand Down Expand Up @@ -719,11 +719,7 @@ impl TestSyntax for BareShape {
let peeked = token_nodes.peek_any();

match peeked.node {
Some(TokenNode::Token(token)) => match token.item {
RawToken::Bare => Some(peeked),
_ => None,
},

Some(token) if token.is_bare() => Some(peeked),
_ => None,
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/parser/hir/syntax_shape/expression/atom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,10 @@ impl<'tokens> SpannedAtomicToken<'tokens> {
Expression::external_command(*command, self.span)
}
AtomicToken::ExternalWord { text } => Expression::string(*text, self.span),
AtomicToken::GlobPattern { pattern } => Expression::pattern(*pattern),
AtomicToken::GlobPattern { pattern } => Expression::pattern(
expand_file_path(pattern.slice(context.source), context).to_string_lossy(),
self.span,
),
AtomicToken::Word { text } => Expression::string(*text, *text),
AtomicToken::SquareDelimited { .. } => unimplemented!("into_hir"),
AtomicToken::ParenDelimited { .. } => unimplemented!("into_hir"),
Expand Down
49 changes: 11 additions & 38 deletions src/parser/hir/syntax_shape/expression/pattern.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use crate::parser::hir::syntax_shape::{
expand_atom, expand_bare, expand_syntax, expression::expand_file_path, parse_single_node,
AtomicToken, ExpandContext, ExpandExpression, ExpandSyntax, ExpansionRule, FallibleColorSyntax,
FlatShape,
expand_atom, expand_bare, expression::expand_file_path, AtomicToken, ExpandContext,
ExpandExpression, ExpandSyntax, ExpansionRule, FallibleColorSyntax, FlatShape,
};
use crate::parser::{hir, hir::TokensIterator, Operator, RawToken, TokenNode};
use crate::prelude::*;
Expand Down Expand Up @@ -72,43 +71,17 @@ impl ExpandExpression for PatternShape {
token_nodes: &mut TokensIterator<'_>,
context: &ExpandContext,
) -> Result<hir::Expression, ShellError> {
let pattern = expand_syntax(&BarePatternShape, token_nodes, context);

match pattern {
Ok(tag) => {
return Ok(hir::Expression::pattern(tag));
let atom = expand_atom(token_nodes, "pattern", context, ExpansionRule::new())?;

match atom.item {
AtomicToken::Word { text: body }
| AtomicToken::String { body }
| AtomicToken::GlobPattern { pattern: body } => {
let path = expand_file_path(body.slice(context.source), context);
return Ok(hir::Expression::pattern(path.to_string_lossy(), atom.span));
}
Err(_) => {}
_ => return atom.into_hir(context, "pattern"),
}

parse_single_node(token_nodes, "Pattern", |token, token_tag, _| {
Ok(match token {
RawToken::GlobPattern => {
return Err(ShellError::unreachable(
"glob pattern after glob already returned",
))
}
RawToken::Operator(..) => {
return Err(ShellError::unreachable("dot after glob already returned"))
}
RawToken::Bare => {
return Err(ShellError::unreachable("bare after glob already returned"))
}

RawToken::Variable(tag) if tag.slice(context.source) == "it" => {
hir::Expression::it_variable(tag, token_tag)
}
RawToken::Variable(tag) => hir::Expression::variable(tag, token_tag),
RawToken::ExternalCommand(tag) => hir::Expression::external_command(tag, token_tag),
RawToken::ExternalWord => return Err(ShellError::invalid_external_word(token_tag)),
RawToken::Number(_) => hir::Expression::bare(token_tag),

RawToken::String(tag) => hir::Expression::file_path(
expand_file_path(tag.slice(context.source), context),
token_tag,
),
})
})
}
}

Expand Down
8 changes: 2 additions & 6 deletions src/parser/hir/syntax_shape/expression/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::parser::hir::syntax_shape::{
ExpansionRule, FallibleColorSyntax, FlatShape, TestSyntax,
};
use crate::parser::hir::tokens_iterator::Peeked;
use crate::parser::{hir, hir::TokensIterator, RawToken, TokenNode};
use crate::parser::{hir, hir::TokensIterator, RawToken};
use crate::prelude::*;

#[derive(Debug, Copy, Clone)]
Expand Down Expand Up @@ -118,11 +118,7 @@ impl TestSyntax for StringShape {
let peeked = token_nodes.peek_any();

match peeked.node {
Some(TokenNode::Token(token)) => match token.item {
RawToken::String(_) => Some(peeked),
_ => None,
},

Some(token) if token.is_string() => Some(peeked),
_ => None,
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/parser/hir/syntax_shape/expression/variable_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -821,7 +821,7 @@ impl ExpandSyntax for MemberShape {

if let Some(peeked) = string {
let node = peeked.not_eof("column")?.commit();
let (outer, inner) = node.expect_string();
let (outer, inner) = node.as_string().unwrap();

return Ok(Member::String(outer, inner));
}
Expand Down
2 changes: 1 addition & 1 deletion src/parser/hir/tokens_iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ impl<'content> TokensIterator<'content> {
impl<'content> Iterator for TokensIterator<'content> {
type Item = &'content TokenNode;

fn next(&mut self) -> Option<&'content TokenNode> {
fn next(&mut self) -> Option<Self::Item> {
next(self, self.state.skip_ws)
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/parser/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -666,7 +666,7 @@ fn is_glob_specific_char(c: char) -> bool {
}

fn is_start_glob_char(c: char) -> bool {
is_start_bare_char(c) || is_glob_specific_char(c)
is_start_bare_char(c) || is_glob_specific_char(c) || c == '.'
}

fn is_glob_char(c: char) -> bool {
Expand Down Expand Up @@ -1147,7 +1147,7 @@ mod tests {
fn test_patterns() {
equal_tokens! {
<pipeline>
"cp ../formats/*" -> b::pipeline(vec![vec![b::bare("cp"), b::sp(), b::op("."), b::op("."), b::pattern("/formats/*")]])
"cp ../formats/*" -> b::pipeline(vec![vec![b::bare("cp"), b::sp(), b::pattern("../formats/*")]])
}

equal_tokens! {
Expand Down

0 comments on commit 540cc40

Please sign in to comment.