mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-30 12:37:49 +00:00
expr: prefix operators length/1, index/3 and substr/3
This commit is contained in:
parent
092e4d1ed4
commit
7b54410557
3 changed files with 56 additions and 3 deletions
|
@ -105,9 +105,9 @@ separates increasing precedence groups. EXPRESSION may be:
|
||||||
STRING : REGEXP [NOT IMPLEMENTED] anchored pattern match of REGEXP in STRING
|
STRING : REGEXP [NOT IMPLEMENTED] anchored pattern match of REGEXP in STRING
|
||||||
|
|
||||||
match STRING REGEXP [NOT IMPLEMENTED] same as STRING : REGEXP
|
match STRING REGEXP [NOT IMPLEMENTED] same as STRING : REGEXP
|
||||||
substr STRING POS LENGTH [NOT IMPLEMENTED] substring of STRING, POS counted from 1
|
substr STRING POS LENGTH substring of STRING, POS counted from 1
|
||||||
index STRING CHARS [NOT IMPLEMENTED] index in STRING where any CHARS is found, or 0
|
index STRING CHARS index in STRING where any CHARS is found, or 0
|
||||||
length STRING [NOT IMPLEMENTED] length of STRING
|
length STRING length of STRING
|
||||||
+ TOKEN interpret TOKEN as a string, even if it is a
|
+ TOKEN interpret TOKEN as a string, even if it is a
|
||||||
keyword like 'match' or an operator like '/'
|
keyword like 'match' or an operator like '/'
|
||||||
|
|
||||||
|
|
|
@ -103,6 +103,9 @@ impl ASTNode {
|
||||||
|a: &String, b: &String| Ok( bool_as_string(a >= b) ),
|
|a: &String, b: &String| Ok( bool_as_string(a >= b) ),
|
||||||
&operand_values
|
&operand_values
|
||||||
),
|
),
|
||||||
|
"length" => prefix_operator_length( &operand_values ),
|
||||||
|
"index" => prefix_operator_index( &operand_values ),
|
||||||
|
"substr" => prefix_operator_substr( &operand_values ),
|
||||||
|
|
||||||
_ => Err(format!("operation not implemented: {}", op_type))
|
_ => Err(format!("operation not implemented: {}", op_type))
|
||||||
}
|
}
|
||||||
|
@ -328,6 +331,55 @@ fn infix_operator_two_ints_or_two_strings<FI, FS>( fi: FI, fs: FS, values: &Vec<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn prefix_operator_length( values: &Vec<String> ) -> Result<String, String> {
|
||||||
|
assert!( values.len() == 1 );
|
||||||
|
Ok( values[0].len().to_string() )
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prefix_operator_index( values: &Vec<String> ) -> Result<String, String> {
|
||||||
|
assert!( values.len() == 2 );
|
||||||
|
let haystack = &values[0];
|
||||||
|
let needles = &values[1];
|
||||||
|
|
||||||
|
let mut current_idx = 0;
|
||||||
|
for ch_h in haystack.chars() {
|
||||||
|
current_idx += 1;
|
||||||
|
|
||||||
|
for ch_n in needles.chars() {
|
||||||
|
if ch_n == ch_h {
|
||||||
|
return Ok( current_idx.to_string() )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok( "0".to_string() )
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prefix_operator_substr( values: &Vec<String> ) -> Result<String, String> {
|
||||||
|
assert!( values.len() == 3 );
|
||||||
|
let subj = &values[0];
|
||||||
|
let mut idx = match values[1].parse::<i64>() {
|
||||||
|
Ok( i ) => i,
|
||||||
|
Err( _ ) => return Err( "expected integer as POS arg to 'substr'".to_string() ),
|
||||||
|
};
|
||||||
|
let mut len = match values[2].parse::<i64>() {
|
||||||
|
Ok( i ) => i,
|
||||||
|
Err( _ ) => return Err( "expected integer as LENGTH arg to 'substr'".to_string() ),
|
||||||
|
};
|
||||||
|
|
||||||
|
if idx <= 0 || len <= 0 { return Ok( "".to_string() ) }
|
||||||
|
|
||||||
|
let mut out_str = String::new();
|
||||||
|
for ch in subj.chars() {
|
||||||
|
idx -= 1;
|
||||||
|
if idx <= 0 {
|
||||||
|
if len <= 0 { break; }
|
||||||
|
len -= 1;
|
||||||
|
|
||||||
|
out_str.push( ch );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok( out_str )
|
||||||
|
}
|
||||||
|
|
||||||
fn bool_as_int( b: bool ) -> i64 { if b { 1 } else { 0 } }
|
fn bool_as_int( b: bool ) -> i64 { if b { 1 } else { 0 } }
|
||||||
fn bool_as_string( b: bool ) -> String { if b { "1".to_string() } else { "0".to_string() } }
|
fn bool_as_string( b: bool ) -> String { if b { "1".to_string() } else { "0".to_string() } }
|
||||||
|
|
|
@ -110,6 +110,7 @@ pub fn strings_to_tokens( strings: &Vec<String> ) -> Result< Vec<(usize, Token)>
|
||||||
"match" => Token::PrefixOp{ arity: 2, value: s.clone() },
|
"match" => Token::PrefixOp{ arity: 2, value: s.clone() },
|
||||||
"substr" => Token::PrefixOp{ arity: 3, value: s.clone() },
|
"substr" => Token::PrefixOp{ arity: 3, value: s.clone() },
|
||||||
"index" => Token::PrefixOp{ arity: 2, value: s.clone() },
|
"index" => Token::PrefixOp{ arity: 2, value: s.clone() },
|
||||||
|
"length" => Token::PrefixOp{ arity: 1, value: s.clone() },
|
||||||
|
|
||||||
_ => Token::new_value( &s ),
|
_ => Token::new_value( &s ),
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue