Merge branch 'main' into source-command

This commit is contained in:
Tanishq Kancharla
2021-10-03 14:25:00 -04:00
committed by GitHub
38 changed files with 1168 additions and 126 deletions

View File

@ -7,15 +7,15 @@ use crate::{
use nu_protocol::{
ast::{
Block, Call, Expr, Expression, FullCellPath, ImportPattern, ImportPatternMember, Operator,
PathMember, Pipeline, RangeInclusion, RangeOperator, Statement,
Block, Call, CellPath, Expr, Expression, FullCellPath, ImportPattern, ImportPatternMember,
Operator, PathMember, Pipeline, RangeInclusion, RangeOperator, Statement,
},
engine::StateWorkingSet,
span, Flag, PositionalArg, Signature, Span, SyntaxShape, Type, VarId,
};
use crate::parse_keywords::{
parse_alias, parse_def, parse_def_predecl, parse_let, parse_module, parse_use,
parse_alias, parse_def, parse_def_predecl, parse_hide, parse_let, parse_module, parse_use,
};
#[derive(Debug, Clone)]
@ -1158,6 +1158,62 @@ pub fn parse_variable_expr(
}
}
pub fn parse_cell_path(
working_set: &mut StateWorkingSet,
tokens: impl Iterator<Item = Token>,
mut expect_dot: bool,
span: Span,
) -> (Vec<PathMember>, Option<ParseError>) {
let mut error = None;
let mut tail = vec![];
for path_element in tokens {
let bytes = working_set.get_span_contents(path_element.span);
if expect_dot {
expect_dot = false;
if bytes.len() != 1 || bytes[0] != b'.' {
error = error.or_else(|| Some(ParseError::Expected('.'.into(), path_element.span)));
}
} else {
expect_dot = true;
match parse_int(bytes, path_element.span) {
(
Expression {
expr: Expr::Int(val),
span,
..
},
None,
) => tail.push(PathMember::Int {
val: val as usize,
span,
}),
_ => {
let (result, err) = parse_string(working_set, path_element.span);
error = error.or(err);
match result {
Expression {
expr: Expr::String(string),
span,
..
} => {
tail.push(PathMember::String { val: string, span });
}
_ => {
error =
error.or_else(|| Some(ParseError::Expected("string".into(), span)));
}
}
}
}
}
}
(tail, error)
}
pub fn parse_full_cell_path(
working_set: &mut StateWorkingSet,
implicit_head: Option<VarId>,
@ -1174,7 +1230,7 @@ pub fn parse_full_cell_path(
let mut tokens = tokens.into_iter().peekable();
if let Some(head) = tokens.peek() {
let bytes = working_set.get_span_contents(head.span);
let (head, mut expect_dot) = if bytes.starts_with(b"(") {
let (head, expect_dot) = if bytes.starts_with(b"(") {
let mut start = head.span.start;
let mut end = head.span.end;
@ -1248,52 +1304,8 @@ pub fn parse_full_cell_path(
);
};
let mut tail = vec![];
for path_element in tokens {
let bytes = working_set.get_span_contents(path_element.span);
if expect_dot {
expect_dot = false;
if bytes.len() != 1 || bytes[0] != b'.' {
error =
error.or_else(|| Some(ParseError::Expected('.'.into(), path_element.span)));
}
} else {
expect_dot = true;
match parse_int(bytes, path_element.span) {
(
Expression {
expr: Expr::Int(val),
span,
..
},
None,
) => tail.push(PathMember::Int {
val: val as usize,
span,
}),
_ => {
let (result, err) = parse_string(working_set, path_element.span);
error = error.or(err);
match result {
Expression {
expr: Expr::String(string),
span,
..
} => {
tail.push(PathMember::String { val: string, span });
}
_ => {
error = error
.or_else(|| Some(ParseError::Expected("string".into(), span)));
}
}
}
}
}
}
let (tail, err) = parse_cell_path(working_set, tokens, expect_dot, span);
error = error.or(err);
(
Expression {
@ -2352,6 +2364,28 @@ pub fn parse_value(
)
}
}
SyntaxShape::CellPath => {
let source = working_set.get_span_contents(span);
let mut error = None;
let (tokens, err) = lex(source, span.start, &[b'\n'], &[b'.']);
error = error.or(err);
let tokens = tokens.into_iter().peekable();
let (cell_path, err) = parse_cell_path(working_set, tokens, false, span);
error = error.or(err);
(
Expression {
expr: Expr::CellPath(CellPath { members: cell_path }),
span,
ty: Type::CellPath,
custom_completion: None,
},
error,
)
}
SyntaxShape::Any => {
if bytes.starts_with(b"[") {
parse_value(working_set, span, &SyntaxShape::Table)
@ -2587,6 +2621,11 @@ pub fn parse_statement(
b"module" => parse_module(working_set, spans),
b"use" => parse_use(working_set, spans),
b"source" => parse_source(working_set, spans),
b"export" => (
garbage_statement(spans),
Some(ParseError::UnexpectedKeyword("export".into(), spans[0])),
),
b"hide" => parse_hide(working_set, spans),
_ => {
let (expr, err) = parse_expression(working_set, spans);
(Statement::Pipeline(Pipeline::from_vec(vec![expr])), err)
@ -2603,16 +2642,18 @@ pub fn parse_block(
working_set.enter_scope();
}
let mut error = None;
// Pre-declare any definition so that definitions
// that share the same block can see each other
for pipeline in &lite_block.block {
if pipeline.commands.len() == 1 {
parse_def_predecl(working_set, &pipeline.commands[0].parts);
if let Some(err) = parse_def_predecl(working_set, &pipeline.commands[0].parts) {
error = error.or(Some(err));
}
}
}
let mut error = None;
let block: Block = lite_block
.block
.iter()