mirror of
https://github.com/nushell/nushell
synced 2024-12-28 14:03:09 +00:00
Speed up the parser and nuon parser a bit more (#4626)
This commit is contained in:
parent
c3979ef1cf
commit
308ab91aff
2 changed files with 96 additions and 42 deletions
|
@ -89,7 +89,7 @@ impl Command for FromNuon {
|
||||||
let (lite_block, err) = nu_parser::lite_parse(&lexed);
|
let (lite_block, err) = nu_parser::lite_parse(&lexed);
|
||||||
error = error.or(err);
|
error = error.or(err);
|
||||||
|
|
||||||
let (block, err) = nu_parser::parse_block(&mut working_set, &lite_block, true);
|
let (mut block, err) = nu_parser::parse_block(&mut working_set, &lite_block, true);
|
||||||
error = error.or(err);
|
error = error.or(err);
|
||||||
|
|
||||||
if let Some(pipeline) = block.pipelines.get(1) {
|
if let Some(pipeline) = block.pipelines.get(1) {
|
||||||
|
@ -119,7 +119,16 @@ impl Command for FromNuon {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let expr = if let Some(pipeline) = block.pipelines.get(0) {
|
let expr = if block.pipelines.is_empty() {
|
||||||
|
Expression {
|
||||||
|
expr: Expr::Nothing,
|
||||||
|
span: head,
|
||||||
|
custom_completion: None,
|
||||||
|
ty: Type::Nothing,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let mut pipeline = block.pipelines.remove(0);
|
||||||
|
|
||||||
if let Some(expr) = pipeline.expressions.get(1) {
|
if let Some(expr) = pipeline.expressions.get(1) {
|
||||||
return Err(ShellError::SpannedLabeledErrorRelated(
|
return Err(ShellError::SpannedLabeledErrorRelated(
|
||||||
"error when loading nuon text".into(),
|
"error when loading nuon text".into(),
|
||||||
|
@ -134,22 +143,15 @@ impl Command for FromNuon {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(expr) = pipeline.expressions.get(0) {
|
if pipeline.expressions.is_empty() {
|
||||||
expr.clone()
|
|
||||||
} else {
|
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Nothing,
|
expr: Expr::Nothing,
|
||||||
span: head,
|
span: head,
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
ty: Type::Nothing,
|
ty: Type::Nothing,
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
} else {
|
pipeline.expressions.remove(0)
|
||||||
Expression {
|
|
||||||
expr: Expr::Nothing,
|
|
||||||
span: head,
|
|
||||||
custom_completion: None,
|
|
||||||
ty: Type::Nothing,
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1091,12 +1091,23 @@ pub fn parse_range(
|
||||||
// looks like parent directory)
|
// looks like parent directory)
|
||||||
|
|
||||||
let contents = working_set.get_span_contents(span);
|
let contents = working_set.get_span_contents(span);
|
||||||
|
|
||||||
let token = if let Ok(s) = String::from_utf8(contents.into()) {
|
let token = if let Ok(s) = String::from_utf8(contents.into()) {
|
||||||
s
|
s
|
||||||
} else {
|
} else {
|
||||||
return (garbage(span), Some(ParseError::NonUtf8(span)));
|
return (garbage(span), Some(ParseError::NonUtf8(span)));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if !token.contains("..") {
|
||||||
|
return (
|
||||||
|
garbage(span),
|
||||||
|
Some(ParseError::Expected(
|
||||||
|
"at least one range bound set".into(),
|
||||||
|
span,
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// First, figure out what exact operators are used and determine their positions
|
// First, figure out what exact operators are used and determine their positions
|
||||||
let dotdot_pos: Vec<_> = token.match_indices("..").map(|(pos, _)| pos).collect();
|
let dotdot_pos: Vec<_> = token.match_indices("..").map(|(pos, _)| pos).collect();
|
||||||
|
|
||||||
|
@ -1224,6 +1235,7 @@ pub(crate) fn parse_dollar_expr(
|
||||||
working_set: &mut StateWorkingSet,
|
working_set: &mut StateWorkingSet,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> (Expression, Option<ParseError>) {
|
) -> (Expression, Option<ParseError>) {
|
||||||
|
trace!("parsing: dollar expression");
|
||||||
let contents = working_set.get_span_contents(span);
|
let contents = working_set.get_span_contents(span);
|
||||||
|
|
||||||
if contents.starts_with(b"$\"") || contents.starts_with(b"$'") {
|
if contents.starts_with(b"$\"") || contents.starts_with(b"$'") {
|
||||||
|
@ -1712,6 +1724,18 @@ pub fn parse_datetime(
|
||||||
trace!("parsing: datetime");
|
trace!("parsing: datetime");
|
||||||
|
|
||||||
let bytes = working_set.get_span_contents(span);
|
let bytes = working_set.get_span_contents(span);
|
||||||
|
|
||||||
|
if bytes.is_empty() || !bytes[0].is_ascii_digit() {
|
||||||
|
return (
|
||||||
|
garbage(span),
|
||||||
|
Some(ParseError::Mismatch(
|
||||||
|
"datetime".into(),
|
||||||
|
"non-datetime".into(),
|
||||||
|
span,
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let token = String::from_utf8_lossy(bytes).to_string();
|
let token = String::from_utf8_lossy(bytes).to_string();
|
||||||
|
|
||||||
if let Ok(datetime) = chrono::DateTime::parse_from_rfc3339(&token) {
|
if let Ok(datetime) = chrono::DateTime::parse_from_rfc3339(&token) {
|
||||||
|
@ -1727,8 +1751,8 @@ pub fn parse_datetime(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Just the date
|
// Just the date
|
||||||
if let Ok(datetime) = chrono::DateTime::parse_from_rfc3339(&format!("{}T00:00:00+00:00", token))
|
let just_date = token.clone() + "T00:00:00+00:00";
|
||||||
{
|
if let Ok(datetime) = chrono::DateTime::parse_from_rfc3339(&just_date) {
|
||||||
return (
|
return (
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::DateTime(datetime),
|
expr: Expr::DateTime(datetime),
|
||||||
|
@ -1741,7 +1765,8 @@ pub fn parse_datetime(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Date and time, assume UTC
|
// Date and time, assume UTC
|
||||||
if let Ok(datetime) = chrono::DateTime::parse_from_rfc3339(&format!("{}+00:00", token)) {
|
let datetime = token + "+00:00";
|
||||||
|
if let Ok(datetime) = chrono::DateTime::parse_from_rfc3339(&datetime) {
|
||||||
return (
|
return (
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::DateTime(datetime),
|
expr: Expr::DateTime(datetime),
|
||||||
|
@ -1779,6 +1804,18 @@ pub fn parse_duration(
|
||||||
}
|
}
|
||||||
|
|
||||||
let bytes = working_set.get_span_contents(span);
|
let bytes = working_set.get_span_contents(span);
|
||||||
|
|
||||||
|
if bytes.is_empty() || (!bytes[0].is_ascii_digit() && bytes[0] != b'-') {
|
||||||
|
return (
|
||||||
|
garbage(span),
|
||||||
|
Some(ParseError::Mismatch(
|
||||||
|
"duration".into(),
|
||||||
|
"non-duration unit".into(),
|
||||||
|
span,
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let token = String::from_utf8_lossy(bytes).to_string();
|
let token = String::from_utf8_lossy(bytes).to_string();
|
||||||
|
|
||||||
let upper = token.to_uppercase();
|
let upper = token.to_uppercase();
|
||||||
|
@ -1874,6 +1911,18 @@ pub fn parse_filesize(
|
||||||
}
|
}
|
||||||
|
|
||||||
let bytes = working_set.get_span_contents(span);
|
let bytes = working_set.get_span_contents(span);
|
||||||
|
|
||||||
|
if bytes.is_empty() || (!bytes[0].is_ascii_digit() && bytes[0] != b'-') {
|
||||||
|
return (
|
||||||
|
garbage(span),
|
||||||
|
Some(ParseError::Mismatch(
|
||||||
|
"filesize".into(),
|
||||||
|
"non-filesize unit".into(),
|
||||||
|
span,
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let token = String::from_utf8_lossy(bytes).to_string();
|
let token = String::from_utf8_lossy(bytes).to_string();
|
||||||
|
|
||||||
let upper = token.to_uppercase();
|
let upper = token.to_uppercase();
|
||||||
|
@ -3111,6 +3160,10 @@ pub fn parse_value(
|
||||||
) -> (Expression, Option<ParseError>) {
|
) -> (Expression, Option<ParseError>) {
|
||||||
let bytes = working_set.get_span_contents(span);
|
let bytes = working_set.get_span_contents(span);
|
||||||
|
|
||||||
|
if bytes.is_empty() {
|
||||||
|
return (garbage(span), Some(ParseError::IncompleteParser(span)));
|
||||||
|
}
|
||||||
|
|
||||||
// First, check the special-cases. These will likely represent specific values as expressions
|
// First, check the special-cases. These will likely represent specific values as expressions
|
||||||
// and may fit a variety of shapes.
|
// and may fit a variety of shapes.
|
||||||
//
|
//
|
||||||
|
@ -3121,37 +3174,35 @@ pub fn parse_value(
|
||||||
trace!("parsing: variable");
|
trace!("parsing: variable");
|
||||||
|
|
||||||
return parse_variable_expr(working_set, span);
|
return parse_variable_expr(working_set, span);
|
||||||
} else if bytes.starts_with(b"$") {
|
}
|
||||||
trace!("parsing: dollar expression");
|
|
||||||
|
|
||||||
return parse_dollar_expr(working_set, span);
|
match bytes[0] {
|
||||||
} else if bytes.starts_with(b"(") {
|
b'$' => return parse_dollar_expr(working_set, span),
|
||||||
trace!("parsing: range or full path");
|
b'(' => {
|
||||||
|
if let (expr, None) = parse_range(working_set, span) {
|
||||||
if let (expr, None) = parse_range(working_set, span) {
|
|
||||||
return (expr, None);
|
|
||||||
} else {
|
|
||||||
return parse_full_cell_path(working_set, None, span);
|
|
||||||
}
|
|
||||||
} else if bytes.starts_with(b"{") {
|
|
||||||
trace!("parsing: block or full path");
|
|
||||||
if !matches!(shape, SyntaxShape::Block(..)) {
|
|
||||||
if let (expr, None) = parse_full_cell_path(working_set, None, span) {
|
|
||||||
return (expr, None);
|
return (expr, None);
|
||||||
|
} else {
|
||||||
|
return parse_full_cell_path(working_set, None, span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if matches!(shape, SyntaxShape::Block(_)) || matches!(shape, SyntaxShape::Any) {
|
b'{' => {
|
||||||
return parse_block_expression(working_set, shape, span);
|
if !matches!(shape, SyntaxShape::Block(..)) {
|
||||||
} else if matches!(shape, SyntaxShape::Record) {
|
if let (expr, None) = parse_full_cell_path(working_set, None, span) {
|
||||||
return parse_record(working_set, span);
|
return (expr, None);
|
||||||
} else {
|
}
|
||||||
return (
|
}
|
||||||
Expression::garbage(span),
|
if matches!(shape, SyntaxShape::Block(_)) || matches!(shape, SyntaxShape::Any) {
|
||||||
Some(ParseError::Expected("non-block value".into(), span)),
|
return parse_block_expression(working_set, shape, span);
|
||||||
);
|
} else if matches!(shape, SyntaxShape::Record) {
|
||||||
|
return parse_record(working_set, span);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
Expression::garbage(span),
|
||||||
|
Some(ParseError::Expected("non-block value".into(), span)),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if bytes.starts_with(b"[") {
|
b'[' => match shape {
|
||||||
match shape {
|
|
||||||
SyntaxShape::Any
|
SyntaxShape::Any
|
||||||
| SyntaxShape::List(_)
|
| SyntaxShape::List(_)
|
||||||
| SyntaxShape::Table
|
| SyntaxShape::Table
|
||||||
|
@ -3162,7 +3213,8 @@ pub fn parse_value(
|
||||||
Some(ParseError::Expected("non-[] value".into(), span)),
|
Some(ParseError::Expected("non-[] value".into(), span)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
match shape {
|
match shape {
|
||||||
|
|
Loading…
Reference in a new issue