Skip to content

Commit 6c29708

Browse files
committed
regex: Remove in-tree version
The regex library was largely used for non-critical aspects of the compiler and various external tooling. The library at this point is duplicated with its out-of-tree counterpart and as such imposes a bit of a maintenance overhead as well as compile time hit for the compiler itself. The last major user of the regex library is the libtest library, using regexes for filters when running tests. This removal means that the filtering has gone back to substring matching rather than using regexes.
1 parent 494896f commit 6c29708

31 files changed

+187
-4450
lines changed

mk/crates.mk

+5-7
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151

5252
TARGET_CRATES := libc std flate arena term \
5353
serialize getopts collections test rand \
54-
log regex graphviz core rbml alloc \
54+
log graphviz core rbml alloc \
5555
unicode rustc_bitflags
5656
RUSTC_CRATES := rustc rustc_typeck rustc_borrowck rustc_resolve rustc_driver \
5757
rustc_trans rustc_back rustc_llvm rustc_privacy
@@ -95,16 +95,15 @@ DEPS_term := std log
9595
DEPS_getopts := std
9696
DEPS_collections := core alloc unicode
9797
DEPS_num := std
98-
DEPS_test := std getopts serialize rbml term regex native:rust_test_helpers
98+
DEPS_test := std getopts serialize rbml term native:rust_test_helpers
9999
DEPS_rand := core
100-
DEPS_log := std regex
101-
DEPS_regex := std
100+
DEPS_log := std
102101
DEPS_fmt_macros = std
103102

104103
TOOL_DEPS_compiletest := test getopts
105104
TOOL_DEPS_rustdoc := rustdoc
106105
TOOL_DEPS_rustc := rustc_driver
107-
TOOL_DEPS_rustbook := std regex rustdoc
106+
TOOL_DEPS_rustbook := std rustdoc
108107
TOOL_SOURCE_compiletest := $(S)src/compiletest/compiletest.rs
109108
TOOL_SOURCE_rustdoc := $(S)src/driver/driver.rs
110109
TOOL_SOURCE_rustc := $(S)src/driver/driver.rs
@@ -130,9 +129,8 @@ DOC_CRATES := $(filter-out rustc, \
130129
$(filter-out rustc_driver, \
131130
$(filter-out rustc_privacy, \
132131
$(filter-out log, \
133-
$(filter-out regex, \
134132
$(filter-out getopts, \
135-
$(filter-out syntax, $(CRATES))))))))))))
133+
$(filter-out syntax, $(CRATES)))))))))))
136134
COMPILER_DOC_CRATES := rustc rustc_trans rustc_borrowck rustc_resolve \
137135
rustc_typeck rustc_driver syntax rustc_privacy
138136

src/compiletest/common.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ pub use self::Mode::*;
1111

1212
use std::fmt;
1313
use std::str::FromStr;
14-
use regex::Regex;
1514

1615
#[derive(Clone, PartialEq, Debug)]
1716
pub enum Mode {
@@ -101,10 +100,7 @@ pub struct Config {
101100
pub run_ignored: bool,
102101

103102
// Only run tests that match this filter
104-
pub filter: Option<Regex>,
105-
106-
// Precompiled regex for finding expected errors in cfail
107-
pub cfail_regex: Regex,
103+
pub filter: Option<String>,
108104

109105
// Write out a parseable log of tests that were run
110106
pub logfile: Option<Path>,

src/compiletest/compiletest.rs

+35-31
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ extern crate getopts;
2222

2323
#[macro_use]
2424
extern crate log;
25-
extern crate regex;
2625

2726
use std::os;
2827
use std::io;
@@ -33,7 +32,6 @@ use getopts::{optopt, optflag, reqopt};
3332
use common::Config;
3433
use common::{Pretty, DebugInfoGdb, DebugInfoLldb, Codegen};
3534
use util::logv;
36-
use regex::Regex;
3735

3836
pub mod procsrv;
3937
pub mod util;
@@ -116,14 +114,7 @@ pub fn parse_config(args: Vec<String> ) -> Config {
116114
}
117115

118116
let filter = if !matches.free.is_empty() {
119-
let s = matches.free[0].as_slice();
120-
match regex::Regex::new(s) {
121-
Ok(re) => Some(re),
122-
Err(e) => {
123-
println!("failed to parse filter /{}/: {:?}", s, e);
124-
panic!()
125-
}
126-
}
117+
Some(matches.free[0].clone())
127118
} else {
128119
None
129120
};
@@ -145,7 +136,6 @@ pub fn parse_config(args: Vec<String> ) -> Config {
145136
.as_slice()).expect("invalid mode"),
146137
run_ignored: matches.opt_present("ignored"),
147138
filter: filter,
148-
cfail_regex: Regex::new(errors::EXPECTED_PATTERN).unwrap(),
149139
logfile: matches.opt_str("logfile").map(|s| Path::new(s)),
150140
runtool: matches.opt_str("runtool"),
151141
host_rustcflags: matches.opt_str("host-rustcflags"),
@@ -374,18 +364,24 @@ fn extract_gdb_version(full_version_line: Option<String>) -> Option<String> {
374364
if full_version_line.as_slice().trim().len() > 0 => {
375365
let full_version_line = full_version_line.as_slice().trim();
376366

377-
let re = Regex::new(r"(^|[^0-9])([0-9]\.[0-9])([^0-9]|$)").unwrap();
378-
379-
match re.captures(full_version_line) {
380-
Some(captures) => {
381-
Some(captures.at(2).unwrap_or("").to_string())
367+
// used to be a regex "(^|[^0-9])([0-9]\.[0-9])([^0-9]|$)"
368+
for (pos, c) in full_version_line.char_indices() {
369+
if !c.is_digit(10) { continue }
370+
if pos + 2 >= full_version_line.len() { continue }
371+
if full_version_line.char_at(pos + 1) != '.' { continue }
372+
if !full_version_line.char_at(pos + 2).is_digit(10) { continue }
373+
if pos > 0 && full_version_line.char_at_reverse(pos).is_digit(10) {
374+
continue
382375
}
383-
None => {
384-
println!("Could not extract GDB version from line '{}'",
385-
full_version_line);
386-
None
376+
if pos + 3 < full_version_line.len() &&
377+
full_version_line.char_at(pos + 3).is_digit(10) {
378+
continue
387379
}
380+
return Some(full_version_line[pos..pos+3].to_string());
388381
}
382+
println!("Could not extract GDB version from line '{}'",
383+
full_version_line);
384+
None
389385
},
390386
_ => None
391387
}
@@ -408,18 +404,26 @@ fn extract_lldb_version(full_version_line: Option<String>) -> Option<String> {
408404
if full_version_line.as_slice().trim().len() > 0 => {
409405
let full_version_line = full_version_line.as_slice().trim();
410406

411-
let re = Regex::new(r"[Ll][Ll][Dd][Bb]-([0-9]+)").unwrap();
412-
413-
match re.captures(full_version_line) {
414-
Some(captures) => {
415-
Some(captures.at(1).unwrap_or("").to_string())
416-
}
417-
None => {
418-
println!("Could not extract LLDB version from line '{}'",
419-
full_version_line);
420-
None
421-
}
407+
for (pos, l) in full_version_line.char_indices() {
408+
if l != 'l' && l != 'L' { continue }
409+
if pos + 5 >= full_version_line.len() { continue }
410+
let l = full_version_line.char_at(pos + 1);
411+
if l != 'l' && l != 'L' { continue }
412+
let d = full_version_line.char_at(pos + 2);
413+
if d != 'd' && d != 'D' { continue }
414+
let b = full_version_line.char_at(pos + 3);
415+
if b != 'b' && b != 'B' { continue }
416+
let dash = full_version_line.char_at(pos + 4);
417+
if dash != '-' { continue }
418+
419+
let vers = full_version_line[pos + 5..].chars().take_while(|c| {
420+
c.is_digit(10)
421+
}).collect::<String>();
422+
if vers.len() > 0 { return Some(vers) }
422423
}
424+
println!("Could not extract LLDB version from line '{}'",
425+
full_version_line);
426+
None
423427
},
424428
_ => None
425429
}

src/compiletest/errors.rs

+38-35
Original file line numberDiff line numberDiff line change
@@ -9,32 +9,26 @@
99
// except according to those terms.
1010
use self::WhichLine::*;
1111

12-
use std::ascii::AsciiExt;
1312
use std::io::{BufferedReader, File};
14-
use regex::Regex;
1513

1614
pub struct ExpectedError {
1715
pub line: uint,
1816
pub kind: String,
1917
pub msg: String,
2018
}
2119

20+
#[derive(PartialEq, Show)]
21+
enum WhichLine { ThisLine, FollowPrevious(uint), AdjustBackward(uint) }
22+
2223
/// Looks for either "//~| KIND MESSAGE" or "//~^^... KIND MESSAGE"
2324
/// The former is a "follow" that inherits its target from the preceding line;
2425
/// the latter is an "adjusts" that goes that many lines up.
2526
///
2627
/// Goal is to enable tests both like: //~^^^ ERROR go up three
2728
/// and also //~^ ERROR message one for the preceding line, and
2829
/// //~| ERROR message two for that same line.
29-
30-
pub static EXPECTED_PATTERN : &'static str =
31-
r"//~(?P<follow>\|)?(?P<adjusts>\^*)\s*(?P<kind>\S*)\s*(?P<msg>.*)";
32-
33-
#[derive(PartialEq, Show)]
34-
enum WhichLine { ThisLine, FollowPrevious(uint), AdjustBackward(uint) }
35-
3630
// Load any test directives embedded in the file
37-
pub fn load_errors(re: &Regex, testfile: &Path) -> Vec<ExpectedError> {
31+
pub fn load_errors(testfile: &Path) -> Vec<ExpectedError> {
3832
let mut rdr = BufferedReader::new(File::open(testfile).unwrap());
3933

4034
// `last_nonfollow_error` tracks the most recently seen
@@ -50,7 +44,7 @@ pub fn load_errors(re: &Regex, testfile: &Path) -> Vec<ExpectedError> {
5044
rdr.lines().enumerate().filter_map(|(line_no, ln)| {
5145
parse_expected(last_nonfollow_error,
5246
line_no + 1,
53-
ln.unwrap().as_slice(), re)
47+
ln.unwrap().as_slice())
5448
.map(|(which, error)| {
5549
match which {
5650
FollowPrevious(_) => {}
@@ -63,30 +57,39 @@ pub fn load_errors(re: &Regex, testfile: &Path) -> Vec<ExpectedError> {
6357

6458
fn parse_expected(last_nonfollow_error: Option<uint>,
6559
line_num: uint,
66-
line: &str,
67-
re: &Regex) -> Option<(WhichLine, ExpectedError)> {
68-
re.captures(line).and_then(|caps| {
69-
let adjusts = caps.name("adjusts").unwrap_or("").len();
70-
let kind = caps.name("kind").unwrap_or("").to_ascii_lowercase();
71-
let msg = caps.name("msg").unwrap_or("").trim().to_string();
72-
let follow = caps.name("follow").unwrap_or("").len() > 0;
60+
line: &str) -> Option<(WhichLine, ExpectedError)> {
61+
let start = match line.find_str("//~") { Some(i) => i, None => return None };
62+
let (follow, adjusts) = if line.char_at(start + 3) == '|' {
63+
(true, 0)
64+
} else {
65+
(false, line[start + 3..].chars().take_while(|c| *c == '^').count())
66+
};
67+
let kind_start = start + 3 + adjusts + (follow as usize);
68+
let letters = line[kind_start..].chars();
69+
let kind = letters.skip_while(|c| c.is_whitespace())
70+
.take_while(|c| !c.is_whitespace())
71+
.map(|c| c.to_lowercase())
72+
.collect::<String>();
73+
let letters = line[kind_start..].chars();
74+
let msg = letters.skip_while(|c| c.is_whitespace())
75+
.skip_while(|c| !c.is_whitespace())
76+
.collect::<String>().trim().to_string();
7377

74-
let (which, line) = if follow {
75-
assert!(adjusts == 0, "use either //~| or //~^, not both.");
76-
let line = last_nonfollow_error.unwrap_or_else(|| {
77-
panic!("encountered //~| without preceding //~^ line.")
78-
});
79-
(FollowPrevious(line), line)
80-
} else {
81-
let which =
82-
if adjusts > 0 { AdjustBackward(adjusts) } else { ThisLine };
83-
let line = line_num - adjusts;
84-
(which, line)
85-
};
78+
let (which, line) = if follow {
79+
assert!(adjusts == 0, "use either //~| or //~^, not both.");
80+
let line = last_nonfollow_error.unwrap_or_else(|| {
81+
panic!("encountered //~| without preceding //~^ line.")
82+
});
83+
(FollowPrevious(line), line)
84+
} else {
85+
let which =
86+
if adjusts > 0 { AdjustBackward(adjusts) } else { ThisLine };
87+
let line = line_num - adjusts;
88+
(which, line)
89+
};
8690

87-
debug!("line={} which={:?} kind={:?} msg={:?}", line_num, which, kind, msg);
88-
Some((which, ExpectedError { line: line,
89-
kind: kind,
90-
msg: msg, }))
91-
})
91+
debug!("line={} which={:?} kind={:?} msg={:?}", line_num, which, kind, msg);
92+
Some((which, ExpectedError { line: line,
93+
kind: kind,
94+
msg: msg, }))
9295
}

src/compiletest/runtest.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ fn run_cfail_test(config: &Config, props: &TestProps, testfile: &Path) {
9999
}
100100

101101
let output_to_check = get_output(props, &proc_res);
102-
let expected_errors = errors::load_errors(&config.cfail_regex, testfile);
102+
let expected_errors = errors::load_errors(testfile);
103103
if !expected_errors.is_empty() {
104104
if !props.error_patterns.is_empty() {
105105
fatal("both error pattern and expected errors specified");

src/grammar/verify.rs

+13-12
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,11 @@
1313
extern crate syntax;
1414
extern crate rustc;
1515

16-
extern crate regex;
17-
1816
#[macro_use]
1917
extern crate log;
2018

2119
use std::collections::HashMap;
2220
use std::io::File;
23-
use regex::Regex;
2421

2522
use syntax::parse;
2623
use syntax::parse::lexer;
@@ -167,15 +164,19 @@ fn count(lit: &str) -> usize {
167164
}
168165

169166
fn parse_antlr_token(s: &str, tokens: &HashMap<String, token::Token>) -> TokenAndSpan {
170-
let re = Regex::new(
171-
r"\[@(?P<seq>\d+),(?P<start>\d+):(?P<end>\d+)='(?P<content>.+?)',<(?P<toknum>-?\d+)>,\d+:\d+]"
172-
).unwrap();
173-
174-
let m = re.captures(s).expect(format!("The regex didn't match {}", s).as_slice());
175-
let start = m.name("start").unwrap_or("");
176-
let end = m.name("end").unwrap_or("");
177-
let toknum = m.name("toknum").unwrap_or("");
178-
let content = m.name("content").unwrap_or("");
167+
// old regex:
168+
// \[@(?P<seq>\d+),(?P<start>\d+):(?P<end>\d+)='(?P<content>.+?)',<(?P<toknum>-?\d+)>,\d+:\d+]
169+
let start = s.find_str("[@").unwrap();
170+
let comma = start + s[start..].find_str(",").unwrap();
171+
let colon = comma + s[comma..].find_str(":").unwrap();
172+
let content_start = colon + s[colon..].find_str("='").unwrap();
173+
let content_end = content_start + s[content_start..].find_str("',<").unwrap();
174+
let toknum_end = content_end + s[content_end..].find_str(">,").unwrap();
175+
176+
let start = &s[comma + 1 .. colon];
177+
let end = &s[colon + 1 .. content_start];
178+
let content = &s[content_start + 2 .. content_end];
179+
let toknum = &s[content_end + 3 .. toknum_end];
179180

180181
let proto_tok = tokens.get(toknum).expect(format!("didn't find token {:?} in the map",
181182
toknum).as_slice());

src/liblog/directive.rs

+2-13
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use regex::Regex;
1211
use std::ascii::AsciiExt;
1312
use std::cmp;
1413

@@ -34,7 +33,7 @@ fn parse_log_level(level: &str) -> Option<u32> {
3433
///
3534
/// Valid log levels are 0-255, with the most likely ones being 1-4 (defined in
3635
/// std::). Also supports string log levels of error, warn, info, and debug
37-
pub fn parse_logging_spec(spec: &str) -> (Vec<LogDirective>, Option<Regex>) {
36+
pub fn parse_logging_spec(spec: &str) -> (Vec<LogDirective>, Option<String>) {
3837
let mut dirs = Vec::new();
3938

4039
let mut parts = spec.split('/');
@@ -80,17 +79,7 @@ pub fn parse_logging_spec(spec: &str) -> (Vec<LogDirective>, Option<Regex>) {
8079
});
8180
}});
8281

83-
let filter = filter.map_or(None, |filter| {
84-
match Regex::new(filter) {
85-
Ok(re) => Some(re),
86-
Err(e) => {
87-
println!("warning: invalid regex filter - {:?}", e);
88-
None
89-
}
90-
}
91-
});
92-
93-
return (dirs, filter);
82+
(dirs, filter.map(|s| s.to_string()))
9483
}
9584

9685
#[cfg(test)]

0 commit comments

Comments
 (0)