add better numbers
This commit is contained in:
parent
07bce5ef28
commit
b0a1735145
@ -3,7 +3,7 @@
|
||||
|
||||
.version = "1.0.0",
|
||||
|
||||
.fingerprint = 0x255cfdbd72bde30d,
|
||||
.fingerprint = 0x27a0a7c056e7482c,
|
||||
.minimum_zig_version = "0.15.0-dev.552+bc2f7c754",
|
||||
|
||||
.dependencies = .{},
|
||||
|
55
language.zig
55
language.zig
@ -13,10 +13,30 @@ pub const Error = enum { Eof, TrailingComma, MissingKey, MissingValue, Unexpecte
|
||||
|
||||
pub const JsonType = enum { null, bool, number, string, array, object };
|
||||
|
||||
pub const JsonNumber = union(enum) {
|
||||
int: i128,
|
||||
float: f64,
|
||||
|
||||
pub fn cast(self: JsonNumber, comptime T: type) T {
|
||||
return switch (self) {
|
||||
.int => |i| switch (@typeInfo(T)) {
|
||||
.float => @as(T, @floatFromInt(i)),
|
||||
.int => @as(T, @intCast(i)),
|
||||
else => @compileError("not a number type"),
|
||||
},
|
||||
.float => |f| switch (@typeInfo(T)) {
|
||||
.float => @as(T, @floatCast(f)),
|
||||
.int => @as(T, @intFromFloat(f)),
|
||||
else => @compileError("not a number type"),
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub const JsonValue = union(JsonType) {
|
||||
null: void,
|
||||
bool: bool,
|
||||
number: f64,
|
||||
number: JsonNumber,
|
||||
string: StringIndex,
|
||||
array: ArraySlice,
|
||||
object: ObjectEntry,
|
||||
@ -25,7 +45,7 @@ pub const JsonValue = union(JsonType) {
|
||||
pub const JsonInput = union(JsonType) {
|
||||
null: void,
|
||||
bool: bool,
|
||||
number: f64,
|
||||
number: JsonNumber,
|
||||
string: []const u8,
|
||||
array: []JsonInput,
|
||||
object: std.StringArrayHashMapUnmanaged(JsonInput),
|
||||
@ -39,9 +59,8 @@ pub const JsonInput = union(JsonType) {
|
||||
},
|
||||
.object => |*object| {
|
||||
var it = object.iterator();
|
||||
while (it.next()) |entry| {
|
||||
while (it.next()) |entry|
|
||||
entry.value_ptr.deinit(allocator);
|
||||
}
|
||||
@constCast(object).deinit(allocator);
|
||||
},
|
||||
else => {},
|
||||
@ -57,7 +76,10 @@ pub const JsonInput = union(JsonType) {
|
||||
switch (self) {
|
||||
.null => try writer.writeAll("null"),
|
||||
.bool => try writer.writeAll(if (self.bool) "true" else "false"),
|
||||
.number => try writer.print("{d}", .{self.number}),
|
||||
.number => switch (self.number) {
|
||||
.int => try writer.print("{d}", .{self.number.int}),
|
||||
.float => try writer.print("{d:.1}", .{self.number.float}),
|
||||
},
|
||||
.string => try writer.print("\"{s}\"", .{self.string}),
|
||||
.array => {
|
||||
try writer.writeByte('[');
|
||||
@ -127,7 +149,7 @@ pub fn deinit(self: *Self, allocator: mem.Allocator) void {
|
||||
self.property_map.deinit(allocator);
|
||||
}
|
||||
|
||||
fn addNumber(self: *Self, allocator: mem.Allocator, number: f64) !usize {
|
||||
fn addNumber(self: *Self, allocator: mem.Allocator, number: JsonNumber) !usize {
|
||||
try self.index.ensureUnusedCapacity(allocator, 1);
|
||||
const idx = self.index.addOneAssumeCapacity();
|
||||
self.index.set(idx, .{ .number = number });
|
||||
@ -382,7 +404,6 @@ pub fn parse(self: *Self, allocator: mem.Allocator, tokenizer: *Tokenizer) !usiz
|
||||
}
|
||||
},
|
||||
.true, .false => {
|
||||
defer tokenizer.skipWhitespace();
|
||||
const idx = try self.addBool(allocator, if (token.type == .true) true else false);
|
||||
|
||||
if (query.len == 0) {
|
||||
@ -445,16 +466,28 @@ pub fn parse(self: *Self, allocator: mem.Allocator, tokenizer: *Tokenizer) !usiz
|
||||
},
|
||||
}
|
||||
},
|
||||
.number => {
|
||||
.int, .float => |number| {
|
||||
if (query.len == 0) {
|
||||
// root
|
||||
_ = try self.addNumber(allocator, token.value.?.number);
|
||||
self.index.set(root, .{ .number = token.value.?.number });
|
||||
_ = switch (number) {
|
||||
.int => try self.addNumber(allocator, .{ .int = token.value.?.int }),
|
||||
.float => try self.addNumber(allocator, .{ .float = token.value.?.float }),
|
||||
else => unreachable,
|
||||
};
|
||||
self.index.set(root, .{ .number = switch (number) {
|
||||
.int => .{ .int = token.value.?.int },
|
||||
.float => .{ .float = token.value.?.float },
|
||||
else => unreachable,
|
||||
} });
|
||||
return root;
|
||||
}
|
||||
|
||||
const parent_idx = query.get(query.len - 1);
|
||||
const idx = try self.addNumber(allocator, token.value.?.number);
|
||||
const idx = switch (number) {
|
||||
.int => try self.addNumber(allocator, .{ .int = token.value.?.int }),
|
||||
.float => try self.addNumber(allocator, .{ .float = token.value.?.float }),
|
||||
else => unreachable,
|
||||
};
|
||||
switch (self.index.get(parent_idx)) {
|
||||
.array => |slice| {
|
||||
self.index.set(parent_idx, .{ .array = ArraySlice{
|
||||
|
@ -58,23 +58,26 @@ pub fn reflectT(self: *Self, comptime T: type, allocator: mem.Allocator, idx: us
|
||||
else => return error.TypeError,
|
||||
},
|
||||
.number => |number| switch (Schema) {
|
||||
.int, .comptime_int => return @intFromFloat(number),
|
||||
.float, .comptime_float => return @floatCast(number),
|
||||
.int, .comptime_int => return @intCast(number.int),
|
||||
.float, .comptime_float => return switch (number) {
|
||||
.float => @floatCast(number.float),
|
||||
.int => @floatFromInt(number.int),
|
||||
},
|
||||
.@"enum" => |enumInfo| {
|
||||
const int: enumInfo.tag_type = @intFromFloat(number);
|
||||
const int: enumInfo.tag_type = @intCast(number.int);
|
||||
return @enumFromInt(int);
|
||||
},
|
||||
.@"struct" => |structInfo| switch (structInfo.layout) {
|
||||
.@"packed" => {
|
||||
const int: structInfo.backing_integer.? = @intFromFloat(number);
|
||||
const int: structInfo.backing_integer.? = @intCast(number.int);
|
||||
return @bitCast(int);
|
||||
},
|
||||
else => return error.TypeError,
|
||||
},
|
||||
.@"union" => |unionInfo| {
|
||||
inline for (unionInfo.fields) |field| switch (@typeInfo(field.type)) {
|
||||
.int, .comptime_int => return @unionInit(T, field.name, @intFromFloat(number)),
|
||||
.float, .comptime_float => return @unionInit(T, field.name, @floatCast(number)),
|
||||
.int, .comptime_int => return @unionInit(T, field.name, @intCast(number.int)),
|
||||
.float, .comptime_float => return @unionInit(T, field.name, @floatCast(number.float)),
|
||||
else => {},
|
||||
};
|
||||
return error.TypeError;
|
||||
|
@ -20,7 +20,8 @@ pub const TokenType = enum(u8) {
|
||||
null,
|
||||
true,
|
||||
false,
|
||||
number,
|
||||
int,
|
||||
float,
|
||||
string,
|
||||
property,
|
||||
object_begin,
|
||||
@ -34,7 +35,12 @@ pub const TokenType = enum(u8) {
|
||||
|
||||
pub const Token = struct {
|
||||
type: TokenType,
|
||||
value: ?union { number: f64, string: []const u8, symbol: u8 },
|
||||
value: ?union {
|
||||
int: i128,
|
||||
float: f64,
|
||||
string: []const u8,
|
||||
symbol: u8,
|
||||
},
|
||||
start: usize,
|
||||
end: usize,
|
||||
};
|
||||
@ -217,18 +223,28 @@ pub fn nextNumber(self: *Self, allocator: mem.Allocator) Error!Token {
|
||||
if (self.matchChar('e') != null or self.matchChar('E') != null) {
|
||||
self.matchChar('+') orelse self.matchChar('-') orelse {};
|
||||
while (self.matchCharRange('0', '9') != null) {}
|
||||
} else {
|
||||
// int found
|
||||
const int = std.fmt.parseInt(i128, self.extractSlice(start), 10) catch {
|
||||
return error.BadNumber; // no floating point
|
||||
};
|
||||
|
||||
return Token{
|
||||
.type = .int,
|
||||
.value = .{ .int = int },
|
||||
.start = start,
|
||||
.end = self.currentPosition(),
|
||||
};
|
||||
}
|
||||
|
||||
// int found
|
||||
// float with e found
|
||||
const float = std.fmt.parseFloat(f64, self.extractSlice(start)) catch {
|
||||
return error.BadNumber; // no floating point
|
||||
};
|
||||
|
||||
return Token{
|
||||
.type = .number,
|
||||
.value = .{
|
||||
.number = float,
|
||||
},
|
||||
.type = .float,
|
||||
.value = .{ .float = float },
|
||||
.start = start,
|
||||
.end = self.currentPosition(),
|
||||
};
|
||||
@ -246,10 +262,8 @@ pub fn nextNumber(self: *Self, allocator: mem.Allocator) Error!Token {
|
||||
};
|
||||
|
||||
return .{
|
||||
.type = .number,
|
||||
.value = .{
|
||||
.number = float,
|
||||
},
|
||||
.type = .float,
|
||||
.value = .{ .float = float },
|
||||
.start = start,
|
||||
.end = self.currentPosition(),
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user