Skip to content

Commit

Permalink
Introduce Config to Lexer (#442)
Browse files Browse the repository at this point in the history
  • Loading branch information
magicant authored Dec 31, 2024
2 parents c591d60 + d90248c commit 8a58f1f
Show file tree
Hide file tree
Showing 49 changed files with 727 additions and 653 deletions.
10 changes: 4 additions & 6 deletions yash-builtin/src/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@
use crate::Result;
use std::cell::RefCell;
use std::num::NonZeroU64;
use std::rc::Rc;
#[cfg(doc)]
use yash_env::semantics::ExitStatus;
Expand All @@ -80,12 +79,11 @@ pub async fn main(env: &mut Env, args: Vec<Field>) -> Result {
};

// Parse and execute the command string
let input = Box::new(Memory::new(&command.value));
let start_line_number = NonZeroU64::new(1).unwrap();
let source = Rc::new(Source::Eval {
let mut config = Lexer::config();
config.source = Some(Rc::new(Source::Eval {
original: command.origin,
});
let mut lexer = Lexer::new(input, start_line_number, source);
}));
let mut lexer = config.input(Box::new(Memory::new(&command.value)));
let divert = read_eval_loop(&RefCell::new(env), &mut lexer).await;
Result::with_exit_status_and_divert(env.exit_status, divert)
}
Expand Down
11 changes: 5 additions & 6 deletions yash-builtin/src/source/semantics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ use crate::common::report_failure;
use std::cell::RefCell;
use std::ffi::CStr;
use std::ffi::CString;
use std::num::NonZeroU64;
use std::ops::ControlFlow;
use std::rc::Rc;
use yash_env::input::Echo;
Expand Down Expand Up @@ -65,13 +64,13 @@ impl Command {
// Parse and execute the command script
let system = env.system.clone();
let ref_env = RefCell::new(&mut *env);
let input = Box::new(Echo::new(FdReader::new(fd, system), &ref_env));
let start_line_number = NonZeroU64::new(1).unwrap();
let source = Rc::new(Source::DotScript {
let mut config = Lexer::config();
config.source = Some(Rc::new(Source::DotScript {
name: self.file.value,
origin: self.file.origin,
});
let mut lexer = Lexer::new(input, start_line_number, source);
}));
let input = Box::new(Echo::new(FdReader::new(fd, system), &ref_env));
let mut lexer = config.input(input);
let divert = read_eval_loop(&ref_env, &mut { lexer }).await;

_ = env.system.close(fd);
Expand Down
9 changes: 2 additions & 7 deletions yash-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ pub mod startup;
use self::startup::args::Parse;
use self::startup::init_file::run_rcfile;
use self::startup::input::prepare_input;
use self::startup::input::SourceInput;
use std::cell::RefCell;
use std::num::NonZeroU64;
use std::ops::ControlFlow::{Break, Continue};
use yash_env::option::{Interactive, On};
use yash_env::signal;
Expand All @@ -43,7 +41,6 @@ use yash_executor::Executor;
use yash_semantics::trap::run_exit_trap;
use yash_semantics::{interactive_read_eval_loop, read_eval_loop};
use yash_semantics::{Divert, ExitStatus};
use yash_syntax::parser::lex::Lexer;

async fn print_version(env: &mut Env) -> ExitStatus {
let version = env!("CARGO_PKG_VERSION");
Expand Down Expand Up @@ -79,8 +76,8 @@ async fn parse_and_print(mut env: Env) -> ExitStatus {

// Prepare the input for the main read-eval loop
let ref_env = &RefCell::new(&mut env);
let SourceInput { input, source } = match prepare_input(ref_env, &work.source) {
Ok(input) => input,
let lexer = match prepare_input(ref_env, &work.source) {
Ok(lexer) => lexer,
Err(e) => {
let arg0 = std::env::args().next().unwrap_or_else(|| "yash".to_owned());
let message = format!("{}: {}\n", arg0, e);
Expand All @@ -95,8 +92,6 @@ async fn parse_and_print(mut env: Env) -> ExitStatus {
};
}
};
let line = NonZeroU64::new(1).unwrap();
let mut lexer = Lexer::new(input, line, source.into());

// Run the read-eval loop
let result = if is_interactive {
Expand Down
11 changes: 5 additions & 6 deletions yash-cli/src/startup/init_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
use super::args::InitFile;
use std::cell::RefCell;
use std::ffi::CString;
use std::num::NonZeroU64;
use std::rc::Rc;
use thiserror::Error;
use yash_env::input::{Echo, FdReader};
Expand Down Expand Up @@ -171,12 +170,12 @@ pub async fn run_init_file(env: &mut Env, path: &str) {
let env = &mut *env.push_frame(Frame::InitFile);
let system = env.system.clone();
let ref_env = RefCell::new(&mut *env);
let input = Box::new(Echo::new(FdReader::new(fd, system), &ref_env));
let start_line_number = NonZeroU64::MIN;
let source = Rc::new(Source::InitFile {
let mut config = Lexer::config();
config.source = Some(Rc::new(Source::InitFile {
path: path.to_owned(),
});
let mut lexer = Lexer::new(input, start_line_number, source);
}));
let input = Box::new(Echo::new(FdReader::new(fd, system), &ref_env));
let mut lexer = config.input(input);
read_eval_loop(&ref_env, &mut { lexer }).await;

if let Err(errno) = env.system.close(fd) {
Expand Down
47 changes: 25 additions & 22 deletions yash-cli/src/startup/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

//! Preparing input object
//! Preparing input for the parser
//!
//! This module implements the [`prepare_input`] function that prepares the input
//! object for the shell. The input object is constructed from the given source
//! and decorated with the [`Echo`] and [`Prompter`] decorators as necessary.
//! This module implements the [`prepare_input`] function that prepares the
//! input for the shell syntax parser. The input is constructed from the given
//! source and decorated with the [`Echo`] and [`Prompter`] decorators as
//! necessary.
//!
//! The [`SourceInput`] and [`PrepareInputError`] types define the return value
//! of the function.
//! [`PrepareInputError`] defines the error that may occur when preparing the
//! input.
use super::args::Source;
use std::cell::RefCell;
Expand All @@ -44,17 +45,10 @@ use yash_env::System;
use yash_prompt::Prompter;
use yash_syntax::input::InputObject;
use yash_syntax::input::Memory;
use yash_syntax::parser::lex::Lexer;
use yash_syntax::source::Source as SyntaxSource;

/// Result of [`prepare_input`].
pub struct SourceInput<'a> {
/// Input to be passed to the lexer
pub input: Box<dyn InputObject + 'a>,
/// Description of the source
pub source: SyntaxSource,
}

/// Error returned by [`prepare_input`].
/// Error returned by [`prepare_input`]
#[derive(Clone, Debug, Eq, Error, PartialEq)]
#[error("cannot open script file '{path}': {errno}")]
pub struct PrepareInputError<'a> {
Expand All @@ -64,10 +58,10 @@ pub struct PrepareInputError<'a> {
pub path: &'a str,
}

/// Prepares the input for the shell.
/// Prepares the input for the shell syntax parser.
///
/// This function constructs an input object from the given source with the
/// following decorators:
/// This function constructs a lexer from the given source with the
/// following decorators applied to the input object:
///
/// - If the source is read with a file descriptor, the [`Echo`] decorator is
/// applied to the input to implement the [`Verbose`] shell option.
Expand All @@ -89,7 +83,16 @@ pub struct PrepareInputError<'a> {
pub fn prepare_input<'s: 'i + 'e, 'i, 'e>(
env: &'i RefCell<&mut Env>,
source: &'s Source,
) -> Result<SourceInput<'i>, PrepareInputError<'e>> {
) -> Result<Lexer<'i>, PrepareInputError<'e>> {
fn lexer_with_input_and_source<'a>(
input: Box<dyn InputObject + 'a>,
source: SyntaxSource,
) -> Lexer<'a> {
let mut config = Lexer::config();
config.source = Some(source.into());
config.input(input)
}

match source {
Source::Stdin => {
let mut system = env.borrow().system.clone();
Expand All @@ -103,7 +106,7 @@ pub fn prepare_input<'s: 'i + 'e, 'i, 'e>(

let input = prepare_fd_input(Fd::STDIN, env);
let source = SyntaxSource::Stdin;
Ok(SourceInput { input, source })
Ok(lexer_with_input_and_source(input, source))
}

Source::File { path } => {
Expand All @@ -126,7 +129,7 @@ pub fn prepare_input<'s: 'i + 'e, 'i, 'e>(
let input = prepare_fd_input(fd, env);
let path = path.to_owned();
let source = SyntaxSource::CommandFile { path };
Ok(SourceInput { input, source })
Ok(lexer_with_input_and_source(input, source))
}

Source::String(command) => {
Expand All @@ -139,7 +142,7 @@ pub fn prepare_input<'s: 'i + 'e, 'i, 'e>(
Box::new(basic_input)
};
let source = SyntaxSource::CommandString;
Ok(SourceInput { input, source })
Ok(lexer_with_input_and_source(input, source))
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions yash-prompt/src/expand_posix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ use futures_util::FutureExt as _;
use yash_env::Env;
use yash_semantics::expansion::expand_text;
use yash_syntax::parser::lex::Lexer;
use yash_syntax::source::Source;
use yash_syntax::syntax::Text;
use yash_syntax::syntax::TextUnit::{self, Literal};

Expand All @@ -42,7 +41,7 @@ use yash_syntax::syntax::TextUnit::{self, Literal};
/// implementations support backslash escapes in the prompt string. This
/// discrepancy may be reconsidered in the future.
pub async fn expand_posix(env: &mut Env, prompt: &str, excl: bool) -> String {
let mut lexer = Lexer::from_memory(prompt, Source::Unknown);
let mut lexer = Lexer::with_code(prompt);
let text_result = lexer.text(|_| false, |_| false).now_or_never().unwrap();

let mut text = text_result.unwrap_or_else(|_| {
Expand Down
5 changes: 3 additions & 2 deletions yash-prompt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
//! # use futures_util::future::FutureExt as _;
//! # async {
//! use std::cell::RefCell;
//! use std::num::NonZeroU64;
//! use std::ops::ControlFlow::Continue;
//! use yash_env::Env;
//! use yash_env::input::FdReader;
Expand All @@ -58,7 +57,9 @@
//! let reader = FdReader::new(Fd::STDIN, env.system.clone());
//! let mut ref_env = RefCell::new(&mut env);
//! let input = Box::new(Prompter::new(reader, &ref_env));
//! let mut lexer = Lexer::new(input, NonZeroU64::MIN, Source::Stdin.into());
//! let mut config = Lexer::config();
//! config.source = Some(Source::Stdin.into());
//! let mut lexer = config.input(input);
//! let result = read_eval_loop(&ref_env, &mut lexer).await;
//! drop(lexer);
//! assert_eq!(result, Continue(()));
Expand Down
Loading

0 comments on commit 8a58f1f

Please sign in to comment.