Merge pull request #73 from nushell/forgiving_def_parse

More forgiving def parse
This commit is contained in:
JT 2021-09-27 14:06:51 +13:00 committed by GitHub
commit 3b134a1ae2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -47,71 +47,107 @@ pub fn parse_def(
let mut error = None; let mut error = None;
let name = working_set.get_span_contents(spans[0]); let name = working_set.get_span_contents(spans[0]);
if name == b"def" && spans.len() >= 4 { if name == b"def" {
//FIXME: don't use expect here let def_decl_id = working_set
let (name_expr, err) = parse_string(working_set, spans[1]); .find_decl(b"def")
error = error.or(err); .expect("internal error: missing def command");
working_set.enter_scope(); let mut call = Box::new(Call {
let (sig, err) = parse_signature(working_set, spans[2]); head: spans[0],
error = error.or(err); decl_id: def_decl_id,
positional: vec![],
named: vec![],
});
let (block, err) = let call = if let Some(name_span) = spans.get(1) {
parse_block_expression(working_set, &SyntaxShape::Block(Some(vec![])), spans[3]); let (name_expr, err) = parse_string(working_set, *name_span);
error = error.or(err); error = error.or(err);
working_set.exit_scope();
if error.is_some() { let name = name_expr.as_string();
return ( call.positional.push(name_expr);
Statement::Pipeline(Pipeline::from_vec(vec![garbage(span(spans))])),
error,
);
}
let name = name_expr.as_string(); if let Some(sig_span) = spans.get(2) {
working_set.enter_scope();
let (sig, err) = parse_signature(working_set, *sig_span);
error = error.or(err);
let signature = sig.as_signature(); let signature = sig.as_signature();
let block_id = block.as_block(); call.positional.push(sig);
match (name, signature, block_id) { if let Some(block_span) = spans.get(3) {
(Some(name), Some(mut signature), Some(block_id)) => { let (block, err) = parse_block_expression(
let decl_id = working_set working_set,
.find_decl(name.as_bytes()) &SyntaxShape::Block(Some(vec![])),
.expect("internal error: predeclaration failed to add definition"); *block_span,
);
error = error.or(err);
let declaration = working_set.get_decl_mut(decl_id); let block_id = block.as_block();
signature.name = name; call.positional.push(block);
*declaration = signature.into_block_command(block_id); if let (Some(name), Some(mut signature), Some(block_id)) =
(name, signature, block_id)
{
let decl_id = working_set
.find_decl(name.as_bytes())
.expect("internal error: predeclaration failed to add definition");
let def_decl_id = working_set let declaration = working_set.get_decl_mut(decl_id);
.find_decl(b"def")
.expect("internal error: missing def command");
let call = Box::new(Call { signature.name = name;
head: spans[0],
decl_id: def_decl_id,
positional: vec![name_expr, sig, block],
named: vec![],
});
( *declaration = signature.into_block_command(block_id);
Statement::Pipeline(Pipeline::from_vec(vec![Expression { }
expr: Expr::Call(call), } else {
span: span(spans), let err_span = Span {
ty: Type::Unknown, start: sig_span.end,
custom_completion: None, end: sig_span.end,
}])), };
error,
) error = error
.or_else(|| Some(ParseError::MissingPositional("block".into(), err_span)));
}
working_set.exit_scope();
call
} else {
let err_span = Span {
start: name_span.end,
end: name_span.end,
};
error = error
.or_else(|| Some(ParseError::MissingPositional("parameters".into(), err_span)));
call
} }
_ => ( } else {
Statement::Pipeline(Pipeline::from_vec(vec![garbage(span(spans))])), let err_span = Span {
error, start: spans[0].end,
), end: spans[0].end,
} };
error = error.or_else(|| {
Some(ParseError::MissingPositional(
"definition name".into(),
err_span,
))
});
call
};
(
Statement::Pipeline(Pipeline::from_vec(vec![Expression {
expr: Expr::Call(call),
span: span(spans),
ty: Type::Unknown,
custom_completion: None,
}])),
error,
)
} else { } else {
( (
garbage_statement(spans), garbage_statement(spans),