parse numerics of all possible bases (0b, 0o, 0x, 0NNN_)

This commit is contained in:
Gwenhael Le Moine 2022-02-22 15:33:36 +01:00
parent dec32d7f9b
commit 1f62c632fd
No known key found for this signature in database
GPG key ID: FDFE3669426707A7
2 changed files with 28 additions and 9 deletions

View file

@ -112,20 +112,30 @@ class Interpreter
if %I[string name].include?( parsed_entry[:type] )
parsed_entry[:value] = parsed_entry[:value][1..-2]
elsif parsed_entry[:type] == :program
elsif %I[program].include?( parsed_entry[:type] )
parsed_entry[:value] = parsed_entry[:value][2..-3]
elsif parsed_entry[:type] == :list
elsif %I[list].include?( parsed_entry[:type] )
parsed_entry[:value] = parse( parsed_entry[:value][2..-3] )
elsif parsed_entry[:type] == :numeric
parsed_entry[:base] = 10 # TODO: parse others possible bases 0x...
elsif %I[numeric].include?( parsed_entry[:type] )
underscore_position = parsed_entry[:value].index('_')
begin
parsed_entry[:value] = Float( parsed_entry[:value] )
parsed_entry[:value] = parsed_entry[:value].to_i if (parsed_entry[:value] % 1).zero? && elt.index('.').nil?
rescue ArgumentError
parsed_entry[:value] = Integer( parsed_entry[:value] )
if parsed_entry[:value][0] == '0' && ( ['b', 'o', 'x'].include?( parsed_entry[:value][1] ) || !underscore_position.nil? )
if parsed_entry[:value][1] == 'x'
parsed_entry[:base] = 16
elsif parsed_entry[:value][1] == 'b'
parsed_entry[:base] = 2
elsif parsed_entry[:value][1] == 'o'
parsed_entry[:base] = 8
parsed_entry[:value] = parsed_entry[:value][2..]
elsif !underscore_position.nil?
parsed_entry[:base] = parsed_entry[:value][1..(underscore_position - 1)].to_i
parsed_entry[:value] = parsed_entry[:value][(underscore_position + 1)..]
end
else
parsed_entry[:base] = 10
end
parsed_entry[:value] = parsed_entry[:value].to_i( parsed_entry[:base] ) unless parsed_entry[:base] == 10
parsed_entry[:value] = BigDecimal( parsed_entry[:value], @precision )
end

View file

@ -9,6 +9,15 @@ class TestParser < MiniTest::Test
def test_number
result = Rpl.new.parse( '1' )
assert_equal [{ value: 1, type: :numeric, base: 10 }], result
result = Rpl.new.parse( '0b101' )
assert_equal [{ value: BigDecimal( 5 ), type: :numeric, base: 2 }], result
result = Rpl.new.parse( '0o57' )
assert_equal [{ value: BigDecimal( 47 ), type: :numeric, base: 8 }], result
result = Rpl.new.parse( '03_10' )
assert_equal [{ value: BigDecimal( 3 ), type: :numeric, base: 3 }], result
end
def test_word