Permalink
Browse files

added (for now parsing-only) support for many BMS extensions; lex! no…

…w uses a slice instead of an owned string.
  • Loading branch information...
1 parent 610fc5b commit f33357d810f641b812c2bb2155f092cc130791c9 @lifthrasiir lifthrasiir committed Jul 21, 2013
Showing with 346 additions and 77 deletions.
  1. +2 −6 src/engine/keyspec.rs
  2. +295 −32 src/format/bms/parse.rs
  3. +2 −1 src/ui/loading.rs
  4. +2 −3 src/ui/options.rs
  5. +1 −1 src/util/filesearch.rs
  6. +37 −15 src/util/lex.rs
  7. +7 −19 src/util/std.rs
@@ -153,18 +153,14 @@ impl KeySpec {
/// Parses the key specification from the string.
pub fn parse_key_spec(s: &str) -> Option<~[(Lane, KeyKind)]> {
- use util::std::str::StrUtil;
-
let mut specs = ~[];
- let mut s = s.trim_left().to_owned();
+ let mut s = s.trim_left();
while !s.is_empty() {
let mut chan = Key(0);
let mut kind = '\x00';
- let mut s2 = ~"";
- if !lex!(s; Key -> chan, char -> kind, ws*, str* -> s2, !) {
+ if !lex!(s; Key -> chan, char -> kind, ws*, str* -> s, !) {
return None;
}
- s = s2;
match (chan, KeyKind::from_char(kind)) {
(Key(36/*1*36*/..107/*3*36-1*/), Some(kind)) => {
specs.push((Lane(*chan as uint - 1*36), kind));
Oops, something went wrong.
View
@@ -200,11 +200,12 @@ pub fn graphic_update_status(path: Option<~str>, screen: &Screen, scene: &Loadin
/// A callback template for `load_resource` with the textual loading screen.
pub fn text_update_status(path: Option<~str>, ticker: &mut Ticker, atexit: &fn()) {
+ use util::std::str::StrUtil;
let mut path = path; // XXX #4654
do ticker.on_tick(get_ticks()) {
match ::std::util::replace(&mut path, None) { // XXX #4654
Some(path) => {
- let path = if path.len() < 63 {path} else {path.slice(0, 63).to_owned()};
+ let path = path.slice_upto(0, 63);
update_line(~"Loading: " + path);
}
None => { update_line("Loading done."); }
View
@@ -107,7 +107,6 @@ pub enum ParsingResult {
/// Parses given arguments (excluding the program name) and returns a parsed path to BMS file and
/// options. `get_path` is called only when arguments do not contain the path.
pub fn parse_opts(args: &[~str], get_path: &fn() -> Option<~str>) -> ParsingResult {
- use util::std::str::StrUtil;
use util::std::hashmap::map_from_vec;
let longargs = map_from_vec([
@@ -155,7 +154,7 @@ pub fn parse_opts(args: &[~str], get_path: &fn() -> Option<~str>) -> ParsingResu
None => { return Error(fmt!("Invalid option: %s", args[i])); }
}
} else {
- args[i].slice_to_end(1).to_owned()
+ args[i].slice_from(1).to_owned()
};
let nshortargs = shortargs.len();
@@ -167,7 +166,7 @@ pub fn parse_opts(args: &[~str], get_path: &fn() -> Option<~str>) -> ParsingResu
let nextarg =
if inside && off < nshortargs {
// remaining portion of `args[i]` is an argument
- shortargs.slice_to_end(off)
+ shortargs.slice_from(off)
} else {
// `args[i+1]` is an argument as a whole
i += 1;
@@ -60,7 +60,7 @@ pub fn resolve_relative_path(basedir: &Path, path: &str, exts: &[&str]) -> Optio
if !found {
match next_.rfind('.') {
Some(idx) => {
- let nextnoext = next_.slice(0, idx).to_owned();
+ let nextnoext = next_.slice_to(idx).to_owned();
for exts.iter().advance |ext| {
if nextnoext + ext.to_owned() == lastpart {
found = true;
View
@@ -29,6 +29,8 @@
*
* - `Key [-> e2]`: Consumes a two-letter alphanumeric key and optionally saves it to `e2`.
* - `Measure [-> e2]`: Consumes exactly three digits and optionally saves it to `e2`.
+ * - `ARGB [-> e2]`: Almost same as `uint [-> e2a], ',', uint [-> e2r], ',', uint [-> e2g], ',',
+ * uint [-> e2b]` but `e2` is a tuple of four `u8` values and overflows are considered an error.
*/
// Rust: - there is no `std::libc::sscanf` due to the varargs. maybe regex support will make
// this obsolete in the future, but not now.
@@ -50,38 +52,37 @@ macro_rules! lex(
// Rust: `std::num::from_str_bytes_common` does not recognize a number followed
// by garbage, so we need to parse it ourselves.
do _line.scan_int().map_default(false) |&_endpos| {
- let _prefix = _line.slice(0, _endpos);
+ let _prefix = _line.slice_to(_endpos);
do ::std::int::from_str(_prefix).map_default(false) |&_value| {
$dst = _value;
- lex!(_line.slice_to_end(_endpos); $($tail)*)
+ lex!(_line.slice_from(_endpos); $($tail)*)
}
}
});
($e:expr; uint -> $dst:expr, $($tail:tt)*) => ({
let _line: &str = $e;
do _line.scan_uint().map_default(false) |&_endpos| {
- let _prefix = _line.slice(0, _endpos);
+ let _prefix = _line.slice_to(_endpos);
do ::std::uint::from_str(_prefix).map_default(false) |&_value| {
$dst = _value;
- lex!(_line.slice_to_end(_endpos); $($tail)*)
+ lex!(_line.slice_from(_endpos); $($tail)*)
}
}
});
($e:expr; float -> $dst:expr, $($tail:tt)*) => ({
let _line: &str = $e;
do _line.scan_float().map_default(false) |&_endpos| {
- let _prefix = _line.slice(0, _endpos);
+ let _prefix = _line.slice_to(_endpos);
do ::std::float::from_str(_prefix).map_default(false) |&_value| {
$dst = _value;
- lex!(_line.slice_to_end(_endpos); $($tail)*)
+ lex!(_line.slice_from(_endpos); $($tail)*)
}
}
});
($e:expr; str -> $dst:expr, ws*, $($tail:tt)*) => ({
let _line: &str = $e;
if !_line.is_empty() {
- // Rust: we should be able to avoid a copy here. (#5550)
- $dst = _line.trim_right().to_owned(); // XXX #5550
+ $dst = _line.trim_right();
lex!(""; $($tail)*) // optimization!
} else {
false
@@ -90,28 +91,28 @@ macro_rules! lex(
($e:expr; str -> $dst:expr, $($tail:tt)*) => ({
let _line: &str = $e;
if !_line.is_empty() {
- $dst = _line.to_owned(); // XXX #5550
+ $dst = _line.slice_from(0); // Rust: why we need to reborrow `_line` here?!
lex!(""; $($tail)*) // optimization!
} else {
false
}
});
($e:expr; str* -> $dst:expr, ws*, $($tail:tt)*) => ({
let _line: &str = $e;
- $dst = _line.trim_right().to_owned(); // XXX #5550
+ $dst = _line.trim_right();
lex!(""; $($tail)*) // optimization!
});
($e:expr; str* -> $dst:expr, $($tail:tt)*) => ({
let _line: &str = $e;
- $dst = _line.to_owned(); // XXX #5550
+ $dst = _line.slice_from(0); // Rust: why we need to reborrow `_line` here?!
lex!(""; $($tail)*) // optimization!
});
($e:expr; char -> $dst:expr, $($tail:tt)*) => ({
let _line: &str = $e;
if !_line.is_empty() {
let _range = _line.char_range_at(0);
$dst = _range.ch;
- lex!(_line.slice_to_end(_range.next); $($tail)*)
+ lex!(_line.slice_from(_range.next); $($tail)*)
} else {
false
}
@@ -121,7 +122,7 @@ macro_rules! lex(
let _line: &str = $e;
do ::format::bms::types::Key::from_str(_line).map_default(false) |&_value| {
$dst = _value;
- lex!(_line.slice_to_end(2u); $($tail)*)
+ lex!(_line.slice_from(2u); $($tail)*)
}
});
($e:expr; Measure -> $dst:expr, $($tail:tt)*) => ({
@@ -130,8 +131,23 @@ macro_rules! lex(
// Rust: this is plain annoying.
if _line.len() >= 3 && _isdigit(_line.char_at(0)) && _isdigit(_line.char_at(1)) &&
_isdigit(_line.char_at(2)) {
- $dst = ::std::uint::from_str(_line.slice(0u, 3u)).unwrap();
- lex!(_line.slice_to_end(3u); $($tail)*)
+ $dst = ::std::uint::from_str(_line.slice_to(3u)).unwrap();
+ lex!(_line.slice_from(3u); $($tail)*)
+ } else {
+ false
+ }
+ });
+ ($e:expr; ARGB -> $dst:expr, $($tail:tt)*) => ({
+ let mut _a: uint = 0;
+ let mut _r: uint = 0;
+ let mut _g: uint = 0;
+ let mut _b: uint = 0;
+ let mut _remainder: &str = "";
+ if lex!($e; uint -> _a, ws*, ',', ws*, uint -> _r, ws*, ',', ws*,
+ uint -> _g, ws*, ',', ws*, uint -> _b, str* -> _remainder, !) &&
+ _a < 256 && _r < 256 && _g < 256 && _b < 256 {
+ $dst = (_a as u8, _r as u8, _g as u8, _b as u8);
+ lex!(_remainder; $($tail)*)
} else {
false
}
@@ -181,6 +197,10 @@ macro_rules! lex(
let mut _dummy: uint = 0;
lex!($e; Measure -> _dummy, $($tail)*)
});
+ ($e:expr; ARGB, $($tail:tt)*) => ({
+ let mut _dummy: (u8,u8,u8,u8) = (0,0,0,0);
+ lex!($e; ARGB -> _dummy, $($tail)*)
+ });
// end Sonorous-specific
($e:expr; $lit:expr, $($tail:tt)*) => ({
do $lit.prefix_shifted($e).map_default(false) |&_line| {
@@ -199,6 +219,7 @@ macro_rules! lex(
// start Sonorous-specific
($e:expr; Key -> $dst:expr) => (lex!($e; Key -> $dst, ));
($e:expr; Measure -> $dst:expr) => (lex!($e; Measure -> $dst, ));
+ ($e:expr; ARGB -> $dst:expr) => (lex!($e; ARGB -> $dst, ));
// end Sonorous-specific
($e:expr; ws) => (lex!($e; ws, ));
@@ -212,6 +233,7 @@ macro_rules! lex(
// start Sonorous-specific
($e:expr; Key) => (lex!($e; Key, ));
($e:expr; Measure) => (lex!($e; Measure, ));
+ ($e:expr; ARGB) => (lex!($e; ARGB, ));
// end Sonorous-specific
($e:expr; $lit:expr) => (lex!($e; $lit, ))
)
View
@@ -51,14 +51,6 @@ pub mod str {
/// Extensions to `str`.
pub trait StrUtil<'self> {
- /// Returns a slice of the given string starting from `begin`.
- ///
- /// # Failure
- ///
- /// If `begin` does not point to valid characters or beyond the last character of
- /// the string
- fn slice_to_end(&self, begin: uint) -> &'self str;
-
/// Returns a slice of the given string starting from `begin` and up to the byte
/// position `end`. `end` doesn't have to point to valid characters.
///
@@ -102,10 +94,6 @@ pub mod str {
}
impl<'self> StrUtil<'self> for &'self str {
- fn slice_to_end(&self, begin: uint) -> &'self str {
- self.slice(begin, self.len())
- }
-
fn slice_upto(&self, begin: uint, end: uint) -> &'self str {
self.slice(begin, begin + self.count_bytes_upto(begin, end))
}
@@ -139,7 +127,7 @@ pub mod str {
fn scan_int(&self) -> Option<uint> {
if self.starts_with("-") || self.starts_with("+") {
- self.slice_to_end(1u).scan_uint().map(|&pos| pos + 1u)
+ self.slice_from(1u).scan_uint().map(|&pos| pos + 1u)
} else {
self.scan_uint()
}
@@ -148,7 +136,7 @@ pub mod str {
fn scan_float(&self) -> Option<uint> {
do self.scan_int().chain |pos| {
if self.len() > pos && self.char_at(pos) == '.' {
- let pos2 = self.slice_to_end(pos + 1u).scan_uint();
+ let pos2 = self.slice_from(pos + 1u).scan_uint();
pos2.map(|&pos2| pos + pos2 + 1u)
} else {
Some(pos)
@@ -176,25 +164,25 @@ pub mod str {
pub trait ShiftablePrefix {
/// Returns a slice of given string with `self` at the start of the string stripped only
/// once, if any.
- fn prefix_shifted(&self, s: &str) -> Option<~str>;
+ fn prefix_shifted<'r>(&self, s: &'r str) -> Option<&'r str>;
}
impl ShiftablePrefix for char {
- fn prefix_shifted(&self, s: &str) -> Option<~str> {
+ fn prefix_shifted<'r>(&self, s: &'r str) -> Option<&'r str> {
if !s.is_empty() {
let CharRange {ch, next} = s.char_range_at(0u);
if ch == *self {
- return Some(s.slice_to_end(next).to_owned());
+ return Some(s.slice_from(next));
}
}
None
}
}
impl<'self> ShiftablePrefix for &'self str {
- fn prefix_shifted(&self, s: &str) -> Option<~str> {
+ fn prefix_shifted<'r>(&self, s: &'r str) -> Option<&'r str> {
if s.starts_with(*self) {
- Some(s.slice_to_end(self.len()).to_owned())
+ Some(s.slice_from(self.len()))
} else {
None
}

0 comments on commit f33357d

Please sign in to comment.