expr: implement regular expressions

This commit is contained in:
Arcterus 2016-12-02 14:06:21 -08:00 committed by Alex Lyon
parent eb75085595
commit 9abc3208d3
10 changed files with 318 additions and 221 deletions

473
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -171,7 +171,7 @@ To do
* [x] echo
* [x] env
* [x] expand
* [ ] expr (almost done, no regular expressions)
* [x] expr
* [x] factor
* [x] false
* [x] fmt

View file

@ -8,8 +8,8 @@ name = "uu_date"
path = "date.rs"
[dependencies]
chrono = "*"
clap = "*"
chrono = "0.4"
clap = "2.25"
uucore = { path="../uucore" }
[[bin]]

View file

@ -15,7 +15,7 @@ extern crate clap;
extern crate uucore;
use chrono::{DateTime, FixedOffset, Offset, Local};
use chrono::offset::utc::UTC;
use chrono::offset::Utc;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::PathBuf;
@ -123,7 +123,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
// Get the current time, either in the local time zone or UTC.
let now: DateTime<FixedOffset> = match settings.utc {
true => {
let now = UTC::now();
let now = Utc::now();
now.with_timezone(&now.offset().fix())
}
false => {

View file

@ -9,6 +9,7 @@ path = "expr.rs"
[dependencies]
libc = "*"
onig = "1.1"
uucore = { path="../uucore" }
[[bin]]

View file

@ -11,6 +11,7 @@
#[macro_use]
extern crate uucore;
extern crate onig;
mod tokens;
mod syntax_tree;
@ -95,9 +96,9 @@ separates increasing precedence groups. EXPRESSION may be:
ARG1 / ARG2 arithmetic quotient of ARG1 divided by ARG2
ARG1 % ARG2 arithmetic remainder of ARG1 divided by ARG2
STRING : REGEXP [NOT IMPLEMENTED] anchored pattern match of REGEXP in STRING
STRING : REGEXP anchored pattern match of REGEXP in STRING
match STRING REGEXP [NOT IMPLEMENTED] same as STRING : REGEXP
match STRING REGEXP same as STRING : REGEXP
substr STRING POS LENGTH substring of STRING, POS counted from 1
index STRING CHARS index in STRING where any CHARS is found, or 0
length STRING length of STRING

View file

@ -13,6 +13,7 @@
//!
use tokens::{Token};
use onig::{Regex, Syntax, REGEX_OPTION_NONE};
type TokenStack = Vec<(usize, Token)>;
pub type OperandsList = Vec< Box<ASTNode> >;
@ -105,6 +106,7 @@ impl ASTNode {
),
"|" => infix_operator_or(&operand_values),
"&" => infix_operator_and(&operand_values),
":" | "match" => operator_match(&operand_values),
"length" => prefix_operator_length( &operand_values ),
"index" => prefix_operator_index( &operand_values ),
"substr" => prefix_operator_substr( &operand_values ),
@ -350,6 +352,25 @@ fn infix_operator_and( values: &Vec<String> ) -> Result<String, String> {
}
}
fn operator_match(values: &Vec<String>) -> Result<String, String> {
assert!(values.len() == 2);
let re = match Regex::with_options(&values[1], REGEX_OPTION_NONE, Syntax::grep()) {
Ok(m) => m,
Err(err) => return Err(err.description().to_string())
};
if re.captures_len() > 0 {
Ok(match re.captures(&values[0]) {
Some(captures) => captures.at(1).unwrap().to_string(),
None => "".to_string()
})
} else {
Ok(match re.find(&values[0]) {
Some((start, end)) => (end - start).to_string(),
None => "0".to_string()
})
}
}
fn prefix_operator_length( values: &Vec<String> ) -> Result<String, String> {
assert!( values.len() == 1 );
Ok( values[0].len().to_string() )

View file

@ -295,12 +295,12 @@ fn hashsum(algoname: &str, mut digest: Box<Digest>, files: Vec<String>, binary:
for (i, line) in buffer.lines().enumerate() {
let line = safe_unwrap!(line);
let (ck_filename, sum, binary_check) = match gnu_re.captures(&line) {
Some(caps) => (caps.name("fileName").unwrap(),
caps.name("digest").unwrap().to_ascii_lowercase(),
caps.name("binary").unwrap() == "*"),
Some(caps) => (caps.name("fileName").unwrap().as_str(),
caps.name("digest").unwrap().as_str().to_ascii_lowercase(),
caps.name("binary").unwrap().as_str() == "*"),
None => match bsd_re.captures(&line) {
Some(caps) => (caps.name("fileName").unwrap(),
caps.name("digest").unwrap().to_ascii_lowercase(),
Some(caps) => (caps.name("fileName").unwrap().as_str(),
caps.name("digest").unwrap().as_str().to_ascii_lowercase(),
true),
None => {
bad_format += 1;

View file

@ -8,12 +8,12 @@ name = "uu_ptx"
path = "ptx.rs"
[dependencies]
getopts = "*"
libc = "*"
aho-corasick = "*"
memchr = "*"
regex-syntax = "*"
regex = "*"
getopts = "0.2"
libc = "0.2"
aho-corasick = "0.6"
memchr = "1.0"
regex-syntax = "0.4"
regex = "0.2"
uucore = { path="../uucore" }
[[bin]]

View file

@ -237,11 +237,12 @@ fn create_word_set(config: &Config, filter: &WordFilter,
for line in &lines.0 {
// if -r, exclude reference from word set
let (ref_beg, ref_end) = match ref_reg.find(line) {
Some(x) => x,
Some(x) => (x.start(), x.end()),
None => (0,0)
};
// match words with given regex
for (beg, end) in reg.find_iter(line) {
for mat in reg.find_iter(line) {
let (beg, end) = (mat.start(), mat.end());
if config.input_ref && ((beg, end) == (ref_beg, ref_end)) {
continue;
}
@ -279,7 +280,7 @@ fn get_reference(config: &Config, word_ref: &WordRef, line: &str) ->
} else if config.input_ref {
let reg = Regex::new(&config.context_regex).unwrap();
let (beg, end) = match reg.find(line) {
Some(x) => x,
Some(x) => (x.start(), x.end()),
None => (0,0)
};
format!("{}", &line[beg .. end])