Forum | Documentation | Website | Blog

Skip to content
Snippets Groups Projects
Commit 49bba9b4 authored by Ary Borenszweig's avatar Ary Borenszweig
Browse files

Fixed with bin, octal and hex literals regarding their types and whether they...

Fixed with bin, octal and hex literals regarding their types and whether they fit in their type or in UInt64
parent 4aa6e824
Branches
Tags
No related merge requests found
......@@ -185,6 +185,8 @@ describe "Lexer" do
it_lexes_i64 ["2147483648", "-2147483649", "-9223372036854775808"]
it_lexes_u64 ["9223372036854775808", "-9223372036854775809"]
it_lexes_u64 ["18446744073709551615", "18446744073709551615", "14146167139683460000"]
it_lexes_i64 [["0x3fffffffffffffff", "4611686018427387903"]]
it_lexes_u64 [["0xffffffffffffffff", "18446744073709551615"]]
it_lexes_char "'a'", 'a'
it_lexes_char "'\\b'", 8.chr
......@@ -235,6 +237,10 @@ describe "Lexer" do
assert_syntax_error "18446744073709551616", "18446744073709551616 doesn't fit in an UInt64"
assert_syntax_error "0xFF_i8", "255 doesn't fit in an Int8"
assert_syntax_error "0200_i8", "128 doesn't fit in an Int8"
assert_syntax_error "0b10000000_i8", "128 doesn't fit in an Int8"
it "lexes not instance var" do
lexer = Lexer.new "!@foo"
token = lexer.next_token
......@@ -362,6 +368,15 @@ describe "Lexer" do
(token.value as Char).ord.should eq(0x10FFFF)
end
it "lexes float then zero (bug)" do
lexer = Lexer.new "2.5 0"
lexer.next_token.number_kind.should eq(:f64)
lexer.next_token.type.should eq(:SPACE)
token = lexer.next_token
token.type.should eq(:NUMBER)
token.number_kind.should eq(:i32)
end
assert_syntax_error "'\\uFEDZ'", "expected hexadecimal character in unicode escape"
assert_syntax_error "'\\u{}'", "expected hexadecimal character in unicode escape"
assert_syntax_error "'\\u{110000}'", "invalid unicode codepoint (too large)"
......
......@@ -191,7 +191,7 @@ module Crystal
when '>'
next_char :"->"
when '0'
scan_zero_number start, multiplier: -1, negative: true
scan_zero_number start, negative: true
when '1', '2', '3', '4', '5', '6', '7', '8', '9'
scan_number start, negative: true
else
......@@ -1153,36 +1153,12 @@ module Crystal
raise "#{string_value} doesn't fit in an UInt64", @token, (current_pos - start)
end
def scan_hex_number(multiplier = 1)
@token.type = :NUMBER
num = 0
next_char
while true
char = next_char
if char == '_'
else
hex_value = char_to_hex(char) { nil }
if hex_value
num = 16 * num + hex_value
else
break
end
end
end
num *= multiplier
@token.value = num.to_s
consume_optional_int_suffix
end
def scan_zero_number(start, multiplier = 1, negative = false)
def scan_zero_number(start, negative = false)
case peek_next_char
when 'x'
scan_hex_number(multiplier)
scan_hex_number(start, negative)
when 'b'
scan_bin_number(multiplier)
scan_bin_number(start, negative)
when '.'
scan_number(start)
when 'i'
......@@ -1221,13 +1197,32 @@ module Crystal
scan_number(start)
end
else
scan_octal_number(multiplier)
scan_octal_number(start, negative)
end
end
def scan_octal_number(multiplier = 1)
@token.type = :NUMBER
num = 0
def scan_bin_number(start, negative)
next_char
num = 0_u64
while true
case next_char
when '0'
num *= 2
when '1'
num = num * 2 + 1
when '_'
# Nothing
else
break
end
end
finish_scan_prefixed_number num, negative, start
end
def scan_octal_number(start, negative)
num = 0_u64
while true
char = next_char
......@@ -1239,45 +1234,53 @@ module Crystal
end
end
num *= multiplier
@token.value = num.to_s
consume_optional_int_suffix
finish_scan_prefixed_number num, negative, start
end
def scan_bin_number(multiplier = 1)
@token.type = :NUMBER
num = 0
def scan_hex_number(start, negative = false)
next_char
num = 0_u64
while true
case next_char
when '0'
num *= 2
when '1'
num = num * 2 + 1
when '_'
# Nothing
char = next_char
if char == '_'
else
break
hex_value = char_to_hex(char) { nil }
if hex_value
num = num * 16 + hex_value
else
break
end
end
end
num *= multiplier
@token.value = num.to_s
consume_optional_int_suffix
finish_scan_prefixed_number num, negative, start
end
def consume_optional_int_suffix
def finish_scan_prefixed_number(num, negative, start)
if negative
string_value = (-1 * num.to_i64).to_s
else
string_value = num.to_s
end
name_length = string_value.length
name_length -= 1 if negative
case current_char
when 'i'
consume_int_suffix
check_integer_literal_fits_in_size string_value, name_length, negative, start
when 'u'
consume_uint_suffix
check_integer_literal_fits_in_size string_value, name_length, negative, start
else
@token.number_kind = :i32
deduce_integer_kind string_value, name_length, negative, start
end
@token.type = :NUMBER
@token.value = string_value
end
def consume_int_suffix
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment