From: Ben Pfaff Date: Mon, 26 Aug 2024 14:19:01 +0000 (-0700) Subject: work X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=75bebe924bfb9175de033259074fdae50fa95c0b;p=pspp work --- diff --git a/rust/pspp/src/command.rs b/rust/pspp/src/command.rs index 325d3d9502..dfa8c5c68e 100644 --- a/rust/pspp/src/command.rs +++ b/rust/pspp/src/command.rs @@ -1,10 +1,9 @@ #![allow(dead_code)] -use std::{fmt::Write, sync::OnceLock}; +use std::{fmt::Write, ops::RangeFrom, sync::OnceLock}; use flagset::{flags, FlagSet}; use crate::{ - identifier::Identifier, integer::ToInteger, lex::{ command_name::CommandMatcher, @@ -106,6 +105,7 @@ fn commands() -> &'static [Command] { no_abbrev: false, name: "ECHO", run: Box::new(|_context| { + println!("hi"); }), }, @@ -126,22 +126,22 @@ fn commands() -> &'static [Command] { COMMANDS.get_or_init(|| new_commands()).as_slice() } -fn parse_command_word(lexer: &mut NewLexer, s: &mut String, n: isize) -> bool { +fn parse_command_word(lexer: &mut NewLexer, s: &mut String, n: usize) -> bool { let separator = match s.chars().next_back() { Some(c) if c != '-' => " ", _ => "", }; - match lexer.next(n) { - Token::Punct(Punct::Dash) => { + match lexer.get(n) { + Some(Token::Punct(Punct::Dash)) => { s.push('-'); true } - Token::Id(id) => { + Some(Token::Id(id)) => { write!(s, "{separator}{id}").unwrap(); true } - Token::Number(number) if number.is_sign_positive() => { + Some(Token::Number(number)) if number.is_sign_positive() => { if let Some(integer) = number.to_exact_usize() { write!(s, "{separator}{integer}").unwrap(); true @@ -164,7 +164,7 @@ fn find_best_match(s: &str) -> (Option<&'static Command>, isize) { fn parse_command_name( lexer: &mut NewLexer, error: &Box, -) -> Result<(&'static Command, isize), ()> { +) -> Result<(&'static Command, usize), ()> { let mut s = String::new(); let mut word = 0; let mut missing_words = 0; @@ -183,12 +183,12 @@ fn parse_command_name( } match command { - Some(command) => Ok((command, (word + 1) + missing_words)), + Some(command) => Ok((command, ((word as isize + 1) + missing_words) as usize)), None => { - if s.is_empty() { - error(lexer.error("Syntax error expecting command name")) + if word == 0 { + error(lexer.error(0..=0, "Syntax error expecting command name")) } else { - error(lexer.error("Unknown command `{s}`.")) + error(lexer.error(0..=word, "Unknown command `{s}`.")) }; Err(()) } @@ -201,14 +201,14 @@ pub enum Success { Finish, } -pub fn end_of_command(context: &Context) -> Result { - match context.lexer.token() { - Token::EndCommand => Ok(Success::Success), +pub fn end_of_command(context: &Context, range: RangeFrom) -> Result { + match context.lexer.get(range.start) { + None | Some(Token::EndCommand) => Ok(Success::Success), _ => { context.error( context .lexer - .error("Syntax error expecting end of command."), + .error(range, "Syntax error expecting end of command."), ); Err(()) } @@ -217,20 +217,16 @@ pub fn end_of_command(context: &Context) -> Result { fn parse_in_state(mut lexer: NewLexer, error: &Box, _state: State) { println!("{}:{}", file!(), line!()); - match lexer.token() { - Token::EndCommand => (), + match lexer.get(0) { + None | Some(Token::EndCommand) => (), _ => { if let Ok((command, n_tokens)) = parse_command_name(&mut lexer, error) { - for _ in 0..n_tokens { - lexer.get(); - } let mut context = Context { error, - lexer, + lexer: lexer.sublexer(n_tokens..), command_name: Some(command.name), }; (command.run)(&mut context); - let _ = end_of_command(&context); } } } @@ -250,17 +246,4 @@ impl<'a> Context<'a> { pub fn error(&self, diagnostic: Diagnostic) { (self.error)(diagnostic); } - - pub fn force_id(&mut self) -> Option { - match self.lexer.token() { - Token::Id(id) => { - let id = id.clone(); - self.lexer.get(); - Some(id) - } - _ => { - todo!() - } - } - } } diff --git a/rust/pspp/src/engine.rs b/rust/pspp/src/engine.rs index 32132c8cdb..fa4940fccb 100644 --- a/rust/pspp/src/engine.rs +++ b/rust/pspp/src/engine.rs @@ -1,21 +1,17 @@ use crate::{ command::parse_command, lex::{ - lexer::{Lexer, NewLexer, NewSource}, + lexer::{NewLexer, NewSource}, }, macros::MacroSet, message::Diagnostic, }; -pub struct Engine { - lexer: Lexer, -} +pub struct Engine; impl Engine { fn new() -> Self { - Self { - lexer: Lexer::new(Box::new(|location, error| println!("{location}: {error}"))), - } + Self } fn run(&mut self, mut source: NewSource) { let macros = MacroSet::new(); diff --git a/rust/pspp/src/lex/lexer.rs b/rust/pspp/src/lex/lexer.rs index 288aa7e9fa..1cb694bbd6 100644 --- a/rust/pspp/src/lex/lexer.rs +++ b/rust/pspp/src/lex/lexer.rs @@ -6,7 +6,7 @@ use std::{ io::Result as IoResult, iter::once, mem::{self, take}, - ops::{Range, RangeInclusive}, + ops::{Bound, Range, RangeBounds, RangeInclusive}, path::Path, sync::Arc, }; @@ -980,7 +980,6 @@ pub struct NewLexer<'a> { backing: &'a Tokens, tokens: &'a [LexToken], start: usize, - pos: usize, } impl<'a> NewLexer<'a> { @@ -989,57 +988,48 @@ impl<'a> NewLexer<'a> { backing, tokens: backing.tokens.as_slice(), start: 0, - pos: 0, } } - pub fn get(&mut self) { - if !self.at_end() { - self.pos += 1; - } - } - - pub fn at_end(&self) -> bool { - self.pos >= self.tokens.len() - } - - pub fn match_(&mut self, token: &Token) -> bool { - if self.token() == token { - self.get(); - true - } else { - false - } - } - - pub fn token(&self) -> &Token { - self.tokens - .get(self.pos) - .map_or(&Token::EndCommand, |token| &token.token) - } - - pub fn next(&self, ofs: isize) -> &Token { - ofs.checked_add(self.pos as isize) - .and_then(|index| usize::try_from(index).ok()) - .and_then(|index| self.tokens.get(index)) - .map_or(&Token::EndCommand, |token| &token.token) + pub fn get(&self, index: usize) -> Option<&Token> { + self.tokens.get(index).map(|token| &token.token) } -/* - pub fn force_string(&mut self) -> Result { - if let Token::String(s) = self.token() { - let s = s.clone(); - self. - } - }*/ - - pub fn error(&self, text: S) -> Diagnostic + pub fn error(&self, range: B, text: S) -> Diagnostic where S: ToString, + B: RangeBounds, { - let abs_pos = self.start + self.pos; + let start = match range.start_bound() { + Bound::Included(&index) => index, + Bound::Excluded(&index) => index + 1, + Bound::Unbounded => 0, + }; + let end = match range.end_bound() { + Bound::Included(&index) => index + 1, + Bound::Excluded(&index) => index, + Bound::Unbounded => self.tokens.len(), + }; + let abs_range = (start + self.start)..=(end + self.start - 1); self.backing - .diagnostic(Severity::Error, abs_pos..=abs_pos, text.to_string()) + .diagnostic(Severity::Error, abs_range, text.to_string()) + } + + pub fn sublexer(&self, range: B) -> Self + where + B: RangeBounds, + { + Self { + backing: self.backing, + start: self.start + + match range.start_bound() { + Bound::Included(index) => *index, + Bound::Excluded(index) => *index + 1, + Bound::Unbounded => 0, + }, + tokens: &self.backing.tokens + [(range.start_bound().cloned(), range.end_bound().cloned())], + } } } @@ -1109,6 +1099,7 @@ impl NewSource { Some(ScanToken::Error(error)) => errors.push(LexError { error, pos }), } } + // XXX report errors if pp.is_empty() { return false; }