From f6fe07d1f3f8e98120169dea59ebc4d2eee4255c Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Fri, 2 Sep 2011 01:39:44 -0400 Subject: [PATCH] Add support for negative literals. --- src/comp/syntax/parse/lexer.rs | 31 +++++++++++++++++++++++++------ src/test/run-pass/negative.rs | 6 ++++++ 2 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 src/test/run-pass/negative.rs diff --git a/src/comp/syntax/parse/lexer.rs b/src/comp/syntax/parse/lexer.rs index ed842322f5dd4..1d6a10744b569 100644 --- a/src/comp/syntax/parse/lexer.rs +++ b/src/comp/syntax/parse/lexer.rs @@ -158,10 +158,15 @@ fn consume_block_comment(rdr: reader) { be consume_whitespace_and_comments(rdr); } -fn digits_to_string(s: str) -> int { +fn string_to_int(s: str) -> int { + let negative = false; + if str::char_at(s, 0u) == '-' { + negative = true; + s = str::substr(s, 1u, str::byte_len(s) - 1u); + } let accum_int: int = 0; for c: u8 in s { accum_int *= 10; accum_int += dec_digit_val(c as char); } - ret accum_int; + ret if negative { -accum_int } else { accum_int }; } fn scan_exponent(rdr: reader) -> option::t { @@ -182,6 +187,17 @@ fn scan_exponent(rdr: reader) -> option::t { } else { ret none::; } } +fn scan_dec_digits_with_prefix(rdr: reader) -> str { + let negative = false; + if rdr.curr() == '-' { + negative = true; + rdr.bump(); + } + let digits = scan_dec_digits(rdr); + if negative { str::unshift_char(digits, '-') } + ret digits; +} + fn scan_dec_digits(rdr: reader) -> str { let c = rdr.curr(); let rslt: str = ""; @@ -196,7 +212,6 @@ fn scan_dec_digits(rdr: reader) -> str { fn scan_number(c: char, rdr: reader) -> token::token { let accum_int = 0; let num_str: str = ""; - let is_dec_integer: bool = false; let n = rdr.next(); if c == '0' && n == 'x' { rdr.bump(); @@ -216,8 +231,10 @@ fn scan_number(c: char, rdr: reader) -> token::token { rdr.bump(); c = rdr.curr(); } - } else { num_str = scan_dec_digits(rdr); is_dec_integer = true; } - if is_dec_integer { accum_int = digits_to_string(num_str); } + } else { + num_str = scan_dec_digits_with_prefix(rdr); + accum_int = string_to_int(num_str); + } c = rdr.curr(); n = rdr.next(); if c == 'u' || c == 'i' { @@ -341,7 +358,9 @@ fn next_token_inner(rdr: reader) -> token::token { ret token::IDENT(interner::intern::(*rdr.get_interner(), accum_str), is_mod_name); } - if is_dec_digit(c) { ret scan_number(c, rdr); } + if is_dec_digit(c) || (c == '-' && is_dec_digit(rdr.next())) { + ret scan_number(c, rdr); + } fn binop(rdr: reader, op: token::binop) -> token::token { rdr.bump(); if rdr.curr() == '=' { diff --git a/src/test/run-pass/negative.rs b/src/test/run-pass/negative.rs new file mode 100644 index 0000000000000..78f0451c9cf40 --- /dev/null +++ b/src/test/run-pass/negative.rs @@ -0,0 +1,6 @@ +fn main() { + alt -5 { + -5 {} + _ { fail } + } +} \ No newline at end of file