From: Ben Pfaff Date: Mon, 8 Jul 2024 15:57:05 +0000 (-0700) Subject: testing X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2f6b6dc82b0edb3627a111262e09d9c467d0d040;p=pspp testing --- diff --git a/rust/src/lex/segment.rs b/rust/src/lex/segment.rs index de75bde568..94ead036b7 100644 --- a/rust/src/lex/segment.rs +++ b/rust/src/lex/segment.rs @@ -71,6 +71,7 @@ pub enum Type { Newline, CommentCommand, DoRepeatCommand, + DoRepeatOverflow, InlineData, MacroId, MacroName, @@ -168,6 +169,7 @@ impl Segmenter { } } State::DoRepeat3 => PromptStyle::DoRepeat, + State::DoRepeat4 => PromptStyle::DoRepeat, State::Define1 | State::Define2 | State::Define3 => { if self.start_of_command() { PromptStyle::First @@ -227,7 +229,7 @@ impl Segmenter { if self.start_of_line() { self.parse_start_of_line(input, eof) } else { - self.parse_mid_command(input, eof) + self.parse_mid_line(input, eof) } } State::Comment1 => self.parse_comment_1(input, eof), @@ -241,6 +243,7 @@ impl Segmenter { State::DoRepeat1 => self.parse_do_repeat_1(input, eof), State::DoRepeat2 => self.parse_do_repeat_2(input, eof), State::DoRepeat3 => self.parse_do_repeat_3(input, eof), + State::DoRepeat4 => self.parse_do_repeat_4(input), State::Define1 => self.parse_define_1_2(input, eof), State::Define2 => self.parse_define_1_2(input, eof), State::Define3 => self.parse_define_3(input, eof), @@ -270,6 +273,7 @@ enum State { DoRepeat1, DoRepeat2, DoRepeat3, + DoRepeat4, Define1, Define2, Define3, @@ -425,6 +429,7 @@ fn detect_command_name(input: &str, eof: bool) -> Result { for command in get_command_name_candidates(command_name) { if let Some(m) = command_match(command, string) { if m.missing_words <= 0 { + println!("{command}"); return Ok(true); } } @@ -495,9 +500,9 @@ impl Segmenter { } } self.state.1 = Substate::START_OF_COMMAND; - self.parse_mid_command(input, eof) + self.parse_mid_line(input, eof) } - fn parse_mid_command<'a>( + fn parse_mid_line<'a>( &mut self, input: &'a str, eof: bool, @@ -650,6 +655,7 @@ impl Segmenter { | Type::Punct | Type::CommentCommand | Type::DoRepeatCommand + | Type::DoRepeatOverflow | Type::InlineData | Type::MacroId | Type::MacroName @@ -1026,26 +1032,17 @@ impl Segmenter { input = take(input, eof).unwrap().1; } } - fn check_repeat_command<'a>(&mut self, input: &'a str, eof: bool) -> Result<(), Incomplete> { + fn check_repeat_command<'a>(&mut self, input: &'a str, eof: bool) -> Result { let input = input.strip_prefix(&['-', '+']).unwrap_or(input); let (id1, input) = self.next_id_in_command(input, eof)?; - let up = if id_match("DO", id1) { - true - } else if id_match("END", id1) { - false + if id_match("DO", id1) && id_match("REPEAT", self.next_id_in_command(input, eof)?.0) { + Ok(1) + } else if id_match("END", id1) && id_match("REPEAT", self.next_id_in_command(input, eof)?.0) + { + Ok(-1) } else { - return Ok(()); - }; - - let (id2, _) = self.next_id_in_command(input, eof)?; - if id_match("REPEAT", id2) { - if up { - self.nest += 1 - } else { - self.nest -= 1 - }; + Ok(0) } - Ok(()) } /// We are in the body of `DO REPEAT`, segmenting the lines of syntax that /// are to be repeated. Report each line of syntax as a single @@ -1063,18 +1060,33 @@ impl Segmenter { return Ok((rest, Type::Newline)); } let rest = self.parse_full_line(input, eof)?; - self.check_repeat_command(input, eof)?; - if self.nest == 0 { - // Nesting level dropped to 0, so we've finished reading the `DO - // REPEAT` body. - self.state = ( - State::General, - Substate::START_OF_COMMAND | Substate::START_OF_LINE, - ); - self.push(input, eof) - } else { - Ok((rest, Type::DoRepeatCommand)) + let direction = self.check_repeat_command(input, eof)?; + if direction > 0 { + if let Some(nest) = self.nest.checked_add(1) { + self.nest = nest; + } else { + self.state.0 = State::DoRepeat4; + } + } else if direction < 0 { + self.nest -= 1; + if self.nest == 0 { + // Nesting level dropped to 0, so we've finished reading the `DO + // REPEAT` body. + self.state = ( + State::General, + Substate::START_OF_COMMAND | Substate::START_OF_LINE, + ); + return self.push(input, eof) + } } + return Ok((rest, Type::DoRepeatCommand)) + } + fn parse_do_repeat_4<'a>( + &mut self, + input: &'a str, + ) -> Result<(&'a str, Type), Incomplete> { + self.state.0 = State::DoRepeat3; + Ok((input, Type::DoRepeatOverflow)) } /// We are segmenting a `DEFINE` command, which consists of: /// @@ -1326,10 +1338,13 @@ mod test { let (rest, type_) = segmenter.push(input, true).unwrap(); let len = input.len() - rest.len(); let token = &input[..len]; - println!("{type_:?} {token:?}"); - if type_ == Type::End { - break; + print!("{type_:?} {token:?}"); + match type_ { + Type::Newline => print!(" ({:?})", segmenter.prompt()), + Type::End => break, + _ => (), } + println!(); input = rest; } } @@ -1560,6 +1575,19 @@ end repeat. ); } + #[test] + fn test_do_repeat_overflow() { + let mut s = String::new(); + const N: usize = 257; + for i in 0..N { + s.push_str(&format!("do repeat v{i}={i} thru {}\n", i + 5)); + } + for i in (0..N).rev() { + s.push_str(&format!("end repeat. /* {i}\n")); + } + print_segmentation(&s); + } + #[test] fn test_define_simple() { print_segmentation( diff --git a/rust/src/prompt.rs b/rust/src/prompt.rs index 71a6b7ce2a..c02ca9b367 100644 --- a/rust/src/prompt.rs +++ b/rust/src/prompt.rs @@ -1,3 +1,4 @@ +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub enum PromptStyle { /// First line of command. First,