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] {
name: "ECHO",
run: Box::new(|_context| {
println!("hi");
- Ok(())
}),
}]
}
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),
_ => {
.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)
}
use crate::{
- command::{parse, Failure, Success},
- lex::lexer::{Lexer, Source},
+ command::parse,
+ lex::{lexer::{Lexer, Source}, token::Token},
message::Diagnostic,
};
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);
}
}
}
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(),
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))