work
authorBen Pfaff <blp@cs.stanford.edu>
Tue, 20 Aug 2024 02:30:19 +0000 (19:30 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Tue, 20 Aug 2024 02:30:19 +0000 (19:30 -0700)
rust/src/command.rs
rust/src/engine.rs
rust/src/lex/lexer.rs

index 4a5b24d10fb7f1131b9d3df1b86baab22f760ba3..d337d1823a0fa86ed4171466b412e20bde2f5c25 100644 (file)
@@ -40,7 +40,7 @@ struct Command {
     testing_only: bool,
     no_abbrev: bool,
     name: &'static str,
-    run: Box<dyn Fn(&Context) -> Result<(), Failure> + Send + Sync>,
+    run: Box<dyn Fn(&Context) + Send + Sync>,
 }
 
 fn commands() -> &'static [Command] {
@@ -53,7 +53,6 @@ fn commands() -> &'static [Command] {
             name: "ECHO",
             run: Box::new(|_context| {
                 println!("hi");
-                Ok(())
             }),
         }]
     }
@@ -137,14 +136,7 @@ pub enum Success {
     Finish,
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub enum Failure {
-    Failure,
-    NotImplemented,
-    CascadingFailure,
-}
-
-pub fn end_of_command(context: &Context) -> Result<Success, Failure> {
+pub fn end_of_command(context: &Context) -> Result<Success, ()> {
     match context.lexer.token() {
         Token::EndCommand | Token::End => Ok(Success::Success),
         _ => {
@@ -153,61 +145,37 @@ pub fn end_of_command(context: &Context) -> Result<Success, Failure> {
                     .lexer
                     .error("Syntax error expecting end of command."),
             );
-            Err(Failure::Failure)
+            Err(())
         }
     }
 }
 
-fn _parse_in_state(
-    lexer: &mut Lexer,
-    error: &Box<dyn Fn(Diagnostic)>,
-    _state: State,
-) -> Result<Success, Failure> {
+fn parse_in_state(lexer: &mut Lexer, error: &Box<dyn Fn(Diagnostic)>, _state: State) {
     match lexer.token() {
-        Token::End => Ok(Success::Eof),
-        Token::EndCommand => Ok(Success::Success),
+        Token::End | Token::EndCommand => (),
         _ => {
-            let (command, n_tokens) =
-                parse_command_name(lexer, error).map_err(|_| Failure::Failure)?;
-            for _ in 0..n_tokens {
-                lexer.get();
-            }
-            let context = Context {
-                error,
-                lexer,
-                command_name: Some(command.name),
-            };
-            match (command.run)(&context) {
-                Ok(()) => end_of_command(&context),
-                Err(error) => Err(error)
+            if let Ok((command, n_tokens)) = parse_command_name(lexer, error) {
+                for _ in 0..n_tokens {
+                    lexer.get();
+                }
+                let context = Context {
+                    error,
+                    lexer,
+                    command_name: Some(command.name),
+                };
+                (command.run)(&context);
+                end_of_command(&context);
             }
+            lexer.interactive_reset();
+            lexer.discard_rest_of_command();
         }
     }
-}
-
-fn parse_in_state(
-    lexer: &mut Lexer,
-    error: &Box<dyn Fn(Diagnostic)>,
-    state: State,
-) -> Result<Success, Failure> {
-    let result = _parse_in_state(lexer, error, state);
-    if result.is_err() {
-        lexer.interactive_reset();
+    while let Token::EndCommand = lexer.token() {
+        lexer.get();
     }
-    lexer.discard_rest_of_command();
-
-    match result {
-        Ok(Success::Eof) | Ok(Success::Finish) => (),
-        _ => {
-            while let Token::EndCommand = lexer.token() {
-                lexer.get();
-            }
-        }
-    };
-    result
 }
 
-pub fn parse(lexer: &mut Lexer, error: &Box<dyn Fn(Diagnostic)>) -> Result<Success, Failure> {
+pub fn parse(lexer: &mut Lexer, error: &Box<dyn Fn(Diagnostic)>) {
     parse_in_state(lexer, error, State::Initial)
 }
 
index 800626e3f7ff5cf5e2a2650cf3264edfbf0861d9..f48c1948c1c60f3d9230fefb38c6fdd79fd216b6 100644 (file)
@@ -1,6 +1,6 @@
 use crate::{
-    command::{parse, Failure, Success},
-    lex::lexer::{Lexer, Source},
+    command::parse,
+    lex::{lexer::{Lexer, Source}, token::Token},
     message::Diagnostic,
 };
 
@@ -17,29 +17,11 @@ impl Engine {
     fn run(&mut self, source: Source) {
         self.lexer.append(source);
         self.lexer.get();
-        loop {
+        while self.lexer.token() != &Token::End {
             let error: Box<dyn Fn(Diagnostic)> = Box::new(|diagnostic| {
                 println!("{diagnostic}");
             });
-            match parse(&mut self.lexer, &error) {
-                Ok(Success::Eof) | Ok(Success::Finish) => break,
-                Ok(Success::Success) => (),
-                Err(error) => match self.lexer.error_handling() {
-                    crate::lex::lexer::ErrorHandling::Continue
-                        if error == Failure::CascadingFailure =>
-                    {
-                        println!("Stopping syntax file processing here to avoid a cascade of dependent command failures.");
-                        self.lexer.discard_noninteractive();
-                        break;
-                    }
-                    crate::lex::lexer::ErrorHandling::Stop => {
-                        println!("Error encountered while ERROR=STOP is effective.");
-                        self.lexer.discard_noninteractive();
-                        break;
-                    }
-                    _ => (),
-                },
-            }
+            parse(&mut self.lexer, &error);
         }
     }
 }
@@ -59,7 +41,7 @@ mod tests {
     fn test_echo() {
         let mut engine = Engine::new();
         engine.run(Source::for_file_contents(
-            "ECHO 'hi there'.\n".to_string(),
+            "ECHO 'hi there'.\nECHO 'bye there'.\n".to_string(),
             Some("test.sps".to_string()),
             UTF_8,
             Mode::default(),
index 4bd1335595b0fe7856678de9b6123bd555baacd2..82ef008aefd5e2de020e7a91d38704caec1598c2 100644 (file)
@@ -463,11 +463,12 @@ impl Source {
         if (1..=self.lines.len() as i32).contains(&line_number) {
             let line_number = line_number as usize;
             let start = self.lines[line_number - 1];
-            let end = self
-                .lines
-                .get(line_number)
-                .copied()
-                .unwrap_or(self.buffer.len());
+            let end = self.lines.get(line_number).copied().unwrap_or(
+                self.buffer[start..]
+                    .find('\n')
+                    .map(|ofs| ofs + start)
+                    .unwrap_or(self.buffer.len()),
+            );
             let line = &self.buffer[start..end];
             line.strip_suffix("\r\n")
                 .unwrap_or(line.strip_suffix('\n').unwrap_or(line))