From 1aa70c50aa93ce0a197f32eb2dd954642be55ba4 Mon Sep 17 00:00:00 2001 From: JT Date: Fri, 9 Jul 2021 09:16:25 +1200 Subject: [PATCH] refactor positional arg parse --- src/parser.rs | 164 ++++++++++++++++++++++++++------------------------ 1 file changed, 84 insertions(+), 80 deletions(-) diff --git a/src/parser.rs b/src/parser.rs index 3b7e122beb..0eadf8604b 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -322,10 +322,10 @@ impl ParserWorkingSet { fn parse_long_flag( &mut self, spans: &[Span], - arg_offset: &mut usize, + spans_idx: &mut usize, sig: &Signature, ) -> (Option, Option, Option) { - let arg_span = spans[*arg_offset]; + let arg_span = spans[*spans_idx]; let arg_contents = self.get_span_contents(arg_span); if arg_contents.starts_with(&[b'-', b'-']) { @@ -342,10 +342,10 @@ impl ParserWorkingSet { let (arg, err) = self.parse_arg(span, arg_shape.clone()); (Some(long_name), Some(arg), err) - } else if let Some(arg) = spans.get(*arg_offset + 1) { + } else if let Some(arg) = spans.get(*spans_idx + 1) { let (arg, err) = self.parse_arg(*arg, arg_shape.clone()); - *arg_offset += 1; + *spans_idx += 1; (Some(long_name), Some(arg), err) } else { ( @@ -376,12 +376,12 @@ impl ParserWorkingSet { fn parse_short_flags( &mut self, spans: &[Span], - arg_offset: &mut usize, + spans_idx: &mut usize, positional_idx: usize, sig: &Signature, ) -> (Option>, Option) { let mut error = None; - let arg_span = spans[*arg_offset]; + let arg_span = spans[*spans_idx]; let arg_contents = self.get_span_contents(arg_span); @@ -440,6 +440,59 @@ impl ParserWorkingSet { } } + fn parse_multispan_value( + &mut self, + spans: &[Span], + spans_idx: &mut usize, + shape: SyntaxShape, + ) -> (Expression, Option) { + let mut error = None; + let arg_span = spans[*spans_idx]; + + match shape { + SyntaxShape::RowCondition => { + let (arg, err) = self.parse_row_condition(spans); + error = error.or(err); + *spans_idx = spans.len(); + + (arg, error) + } + SyntaxShape::Expression => { + let (arg, err) = self.parse_expression(spans); + error = error.or(err); + *spans_idx = spans.len(); + + (arg, error) + } + SyntaxShape::Literal(literal) => { + let arg_contents = self.get_span_contents(arg_span); + if arg_contents != literal { + // When keywords mismatch, this is a strong indicator of something going wrong. + // We won't often override the current error, but as this is a strong indicator + // go ahead and override the current error and tell the user about the missing + // keyword/literal. + error = Some(ParseError::Mismatch( + String::from_utf8_lossy(&literal).into(), + arg_span, + )) + } + ( + Expression { + expr: Expr::Literal(literal), + span: arg_span, + }, + error, + ) + } + _ => { + let (arg, err) = self.parse_arg(arg_span, shape); + error = error.or(err); + + (arg, error) + } + } + } + pub fn parse_internal_call( &mut self, spans: &[Span], @@ -455,34 +508,38 @@ impl ParserWorkingSet { .expect("internal error: bad DeclId") .clone(); + // The index into the positional parameter in the definition let mut positional_idx = 0; - let mut arg_offset = 1; - while arg_offset < spans.len() { - let arg_span = spans[arg_offset]; + // The index into the spans of argument data given to parse + // Starting at the first argument + let mut spans_idx = 1; - let (long_name, arg, err) = self.parse_long_flag(spans, &mut arg_offset, &sig); + while spans_idx < spans.len() { + let arg_span = spans[spans_idx]; + + let (long_name, arg, err) = self.parse_long_flag(spans, &mut spans_idx, &sig); if let Some(long_name) = long_name { // We found a long flag, like --bar error = error.or(err); call.named.push((long_name, arg)); - arg_offset += 1; + spans_idx += 1; continue; } let (short_flags, err) = - self.parse_short_flags(spans, &mut arg_offset, positional_idx, &sig); + self.parse_short_flags(spans, &mut spans_idx, positional_idx, &sig); if let Some(short_flags) = short_flags { error = error.or(err); for flag in short_flags { if let Some(arg_shape) = flag.arg { - if let Some(arg) = spans.get(arg_offset + 1) { + if let Some(arg) = spans.get(spans_idx + 1) { let (arg, err) = self.parse_arg(*arg, arg_shape.clone()); error = error.or(err); call.named.push((flag.long.clone(), Some(arg))); - arg_offset += 1; + spans_idx += 1; } else { error = error.or(Some(ParseError::MissingFlagParam(arg_span))) } @@ -490,81 +547,28 @@ impl ParserWorkingSet { call.named.push((flag.long.clone(), None)); } } - arg_offset += 1; + spans_idx += 1; continue; } if let Some(positional) = sig.get_positional(positional_idx) { - match positional.shape { - SyntaxShape::RowCondition => { - let remainder = sig.num_positionals() - positional_idx; + //Make sure we leave enough spans for the remaining positionals + let remainder = sig.num_positionals() - positional_idx; - if spans.len() < remainder { - error = error.or_else(|| { - Some(ParseError::MissingPositional( - "required args".into(), - arg_span, - )) - }); - } else { - let (arg, err) = self.parse_row_condition( - &spans[arg_offset..(spans.len() - remainder + 1)], - ); - error = error.or(err); - call.positional.push(arg); - - arg_offset = spans.len() - remainder; - } - } - SyntaxShape::Expression => { - let remainder = sig.num_positionals() - positional_idx; - - if spans.len() < remainder { - error = error.or_else(|| { - Some(ParseError::MissingPositional( - "required args".into(), - arg_span, - )) - }); - } else { - let (arg, err) = self.parse_expression( - &spans[arg_offset..(spans.len() - remainder + 1)], - ); - error = error.or(err); - call.positional.push(arg); - - arg_offset = spans.len() - remainder; - } - } - SyntaxShape::Literal(literal) => { - let arg_contents = self.get_span_contents(arg_span); - if arg_contents != literal { - // When keywords mismatch, this is a strong indicator of something going wrong. - // We won't often override the current error, but as this is a strong indicator - // go ahead and override the current error and tell the user about the missing - // keyword/literal. - error = Some(ParseError::Mismatch( - String::from_utf8_lossy(&literal).into(), - arg_span, - )) - } - call.positional.push(Expression { - expr: Expr::Literal(literal), - span: arg_span, - }); - } - _ => { - let (arg, err) = self.parse_arg(arg_span, positional.shape); - error = error.or(err); - - call.positional.push(arg); - } - } + let (arg, err) = self.parse_multispan_value( + &spans[..(spans.len() - remainder + 1)], + &mut spans_idx, + positional.shape, + ); + error = error.or(err); + call.positional.push(arg); positional_idx += 1; } else { error = error.or(Some(ParseError::ExtraPositional(arg_span))) } - arg_offset += 1; + + error = error.or(err); + spans_idx += 1; } let err = check_call(spans[0], &sig, &call);