1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-27 19:17:43 +00:00

expr: Do not parse arguments using clap

This commit is contained in:
Dorian Peron 2025-02-24 02:42:27 +01:00
parent 81048228cf
commit 44077e37a8
2 changed files with 33 additions and 20 deletions

View file

@ -94,16 +94,29 @@ pub fn uu_app() -> Command {
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
// For expr utility we do not want getopts.
// The following usage should work without escaping hyphens: `expr -15 = 1 + 2 \* \( 3 - -4 \)`
let matches = uu_app().try_get_matches_from(args)?;
let token_strings: Vec<&str> = matches
.get_many::<String>(options::EXPRESSION)
.map(|v| v.into_iter().map(|s| s.as_ref()).collect::<Vec<_>>())
.unwrap_or_default();
let args: Vec<String> = args
.skip(1) // Skip binary name
.map(|a| a.to_string_lossy().to_string())
.collect();
let res: String = AstNode::parse(&token_strings)?.eval()?.eval_as_string();
if args.len() == 1 && args[0] == "--help" {
let _ = uu_app().print_help();
} else if args.len() == 1 && args[0] == "--version" {
println!("{} {}", uucore::util_name(), crate_version!())
} else {
// The first argument may be "--" and should be be ignored.
let args = if !args.is_empty() && args[0] == "--" {
&args[1..]
} else {
&args
};
let res: String = AstNode::parse(args)?.eval()?.eval_as_string();
println!("{res}");
if !is_truthy(&res.into()) {
return Err(1.into());
}
}
Ok(())
}

View file

@ -365,7 +365,7 @@ pub enum AstNode {
}
impl AstNode {
pub fn parse(input: &[&str]) -> ExprResult<Self> {
pub fn parse(input: &[impl AsRef<str>]) -> ExprResult<Self> {
Parser::new(input).parse()
}
@ -427,13 +427,13 @@ impl AstNode {
}
}
struct Parser<'a> {
input: &'a [&'a str],
struct Parser<'a, S: AsRef<str>> {
input: &'a [S],
index: usize,
}
impl<'a> Parser<'a> {
fn new(input: &'a [&'a str]) -> Self {
impl<'a, S: AsRef<str>> Parser<'a, S> {
fn new(input: &'a [S]) -> Self {
Self { input, index: 0 }
}
@ -441,19 +441,19 @@ impl<'a> Parser<'a> {
let next = self.input.get(self.index);
if let Some(next) = next {
self.index += 1;
Ok(next)
Ok(next.as_ref())
} else {
// The indexing won't panic, because we know that the input size
// is greater than zero.
Err(ExprError::MissingArgument(
self.input[self.index - 1].into(),
self.input[self.index - 1].as_ref().into(),
))
}
}
fn accept<T>(&mut self, f: impl Fn(&str) -> Option<T>) -> Option<T> {
let next = self.input.get(self.index)?;
let tok = f(next);
let tok = f(next.as_ref());
if let Some(tok) = tok {
self.index += 1;
Some(tok)
@ -468,7 +468,7 @@ impl<'a> Parser<'a> {
}
let res = self.parse_expression()?;
if let Some(arg) = self.input.get(self.index) {
return Err(ExprError::UnexpectedArgument(arg.to_string()));
return Err(ExprError::UnexpectedArgument(arg.as_ref().into()));
}
Ok(res)
}
@ -556,12 +556,12 @@ impl<'a> Parser<'a> {
// at `self.index - 1`. So this indexing won't panic.
Ok(_) => {
return Err(ExprError::ExpectedClosingBraceInsteadOf(
self.input[self.index - 1].into(),
self.input[self.index - 1].as_ref().into(),
));
}
Err(ExprError::MissingArgument(_)) => {
return Err(ExprError::ExpectedClosingBraceAfter(
self.input[self.index - 1].into(),
self.input[self.index - 1].as_ref().into(),
));
}
Err(e) => return Err(e),