~cricket/zckt

6f63ef3030a5a016af270c4a4b5b6efd85b418e6 — c piapiac 13 days ago 33d0477
changes to fit ckt changes
2 files changed, 53 insertions(+), 69 deletions(-)

M parser.zig
M tokenizer.zig
M parser.zig => parser.zig +9 -7
@@ 20,13 20,12 @@ const StringError = error{
fn skipWhitespace(str: []const u8, i: *usize) void {
    while (i.* < str.len) : (i.* += 1) {
        switch (str[i.*]) {
            ' ', '\t', 0x0B, 0x0C, '\r' => continue,
            ' ', '\t', '\r' => continue,
            else => return,
        }
    }
}

// i'm not sure if there's a way to do this without allocations
fn parseMultilineString(str: []const u8, a: *mem.Allocator) MemError![]const u8 {
    const State = enum { root, line };



@@ 36,7 35,9 @@ fn parseMultilineString(str: []const u8, a: *mem.Allocator) MemError![]const u8 

    var i: usize = 0;
    debug.assert(str[i] == '|');
    i += 1; // skip initial pipe

    // skip initial pipe
    i += 1;

    while (i < str.len) : (i += 1) {
        switch (state) {


@@ 76,9 77,8 @@ fn parseMultilineString(str: []const u8, a: *mem.Allocator) MemError![]const u8 
    return buf.toOwnedSlice();
}

// ~~stolen~~ inspired by std/zig/string_literal.zig
// inspired by std/zig/string_literal.zig
// think about making this match json's string escapes to make CKT -> JSON easy peasy
// again, i'm not sure if there's a way to do this without allocations
fn parseQuotedString(
    str: []const u8,
    a: *mem.Allocator,


@@ 128,7 128,9 @@ fn parseQuotedString(
                    try buf.append(0x0B);
                    state = State.root;
                },
                '\\', '"', '\'' => {
                '\\',
                '"',
                => {
                    try buf.append(char);
                    state = State.root;
                },


@@ 302,7 304,7 @@ pub const table_parser = struct {
        while (try tokens.next()) |token| {
            switch (token) {
                .table_end => return table,
                .keyeq => |str| key = try parseString(str, a),
                .key => |str| key = try parseString(str, a),
                .table_start => value = .{ .table = try parseTable(tokens, a) },
                .value => |str| value = .{ .string = try parseString(str, a) },
            }

M tokenizer.zig => tokenizer.zig +44 -62
@@ 9,12 9,7 @@ pub const Token = union(enum) {
        quoted: []const u8,
        multiline: []const u8,

        pub fn format(
            self: String,
            comptime _: []const u8,
            options: fmt.FormatOptions,
            writer: anytype,
        ) !void {
        pub fn format(self: String, comptime _: []const u8, options: fmt.FormatOptions, writer: anytype) !void {
            switch (self) {
                .unquoted => |str| try writer.print("unquoted: {s}", .{str}),
                .quoted => |str| try writer.print("quoted: {s}", .{str}),


@@ 23,19 18,14 @@ pub const Token = union(enum) {
        }
    };

    keyeq: String, // key =
    value: String, // value
    table_start, // [
    table_end, // ]

    pub fn format(
        self: Token,
        comptime _: []const u8,
        options: fmt.FormatOptions,
        writer: anytype,
    ) !void {
    key: String,
    value: String,
    table_start,
    table_end,

    pub fn format(self: Token, comptime _: []const u8, options: fmt.FormatOptions, writer: anytype) !void {
        switch (self) {
            .keyeq => |str| try writer.print("key {{{s}}} =", .{str}),
            .key => |str| try writer.print("key {{{s}}} =", .{str}),
            .value => |str| try writer.print("value {{{s}}};", .{str}),
            .table_start => |str| try writer.print("[", .{}),
            .table_end => |str| try writer.print("]", .{}),


@@ 82,16 72,11 @@ pub const Tokenizer = struct {
        }
    }

    fn skipPastNewline(self: *Tokenizer) Error!void {
        try self.skipToNewline();
        self.index += 1;
    }

    fn skipWhitespace(self: *Tokenizer) Error!void {
        while (self.index < self.content.len) : (self.index += 1) {
            switch (self.content[self.index]) {
                // actual whitespace
                ' ', '\t', 0x0B, 0x0C, '\r' => continue,
                ' ', '\t', '\r' => continue,
                '#' => return try self.skipToNewline(),
                else => return,
            }


@@ 102,7 87,7 @@ pub const Tokenizer = struct {
        while (self.index < self.content.len) : (self.index += 1) {
            switch (self.content[self.index]) {
                // actual whitespace
                ' ', '\t', 0x0B, 0x0C, '\r' => continue,
                ' ', '\t', '\r' => continue,
                '#' => try self.skipToNewline(),
                '\n' => continue,
                else => return,


@@ 115,7 100,7 @@ pub const Tokenizer = struct {
        while (self.index < self.content.len) : (self.index += 1) {
            switch (self.content[self.index]) {
                // actual whitespace
                ' ', '\t', 0x0B, 0x0C, '\r' => continue,
                ' ', '\t', '\r' => continue,
                ';', ',' => continue,
                '#' => try self.skipToNewline(),
                '\n' => continue,


@@ 151,7 136,7 @@ pub const Tokenizer = struct {
        return self.content[start_index..self.index];
    }

    fn readQuotedString(self: *Tokenizer, comptime quote: u8) Error![]const u8 {
    fn readQuotedString(self: *Tokenizer) Error![]const u8 {
        const start_index = self.index;

        self.index += 1;


@@ 159,7 144,7 @@ pub const Tokenizer = struct {
        while (self.index < self.content.len) : (self.index += 1) {
            const char = self.content[self.index];
            switch (char) {
                quote => {
                '"' => {
                    self.index += 1;
                    return self.content[start_index..self.index];
                },


@@ 204,40 189,37 @@ pub const Tokenizer = struct {

    pub fn next(self: *Tokenizer) Error!?Token {
        if (!self.finished) {
            self.last = ret: {
                // treat ; and , as whitespace
                try self.skipWhitespaceAndNewlinesAndBreaks();
                if (self.finished) return null;
                const char = self.content[self.index];
                switch (char) {
                    '[' => break :ret Token.table_start,
                    ']' => break :ret Token.table_end,
                    '=' => return error.EmptyKey,
                    else => {
                        var value: Token.String = switch (char) {
                            '"' => Token.String{ .quoted = try self.readQuotedString('"') },
                            '\'' => Token.String{ .quoted = try self.readQuotedString('\'') },
                            '|' => Token.String{ .multiline = try self.readMultilineString() },
                            else => Token.String{ .unquoted = try self.readString() },
                        };
                        try self.skipWhitespaceAndNewlines();
                        if (!self.finished) {
                            switch (self.content[self.index]) {
                                ';', ',' => break :ret Token{ .value = value },
                                '=' => break :ret Token{ .keyeq = value },
                                ']' => {
                                    self.index -= 1;
                                    break :ret Token{ .value = value };
                                },
                                else => {
                                    self.index -= 1;
                                    break :ret Token{ .value = value };
                                },
                            }
                        } else break :ret Token{ .value = value };
                    },
                }
            };
            // treat ; and , as whitespace
            try self.skipWhitespaceAndNewlinesAndBreaks();
            if (self.finished) return null;
            const char = self.content[self.index];
            switch (char) {
                '[' => self.last = Token.table_start,
                ']' => self.last = Token.table_end,
                '=' => return error.EmptyKey,
                else => {
                    var value: Token.String = switch (char) {
                        '"' => Token.String{ .quoted = try self.readQuotedString() },
                        '|' => Token.String{ .multiline = try self.readMultilineString() },
                        else => Token.String{ .unquoted = try self.readString() },
                    };
                    try self.skipWhitespaceAndNewlines();
                    if (!self.finished) {
                        switch (self.content[self.index]) {
                            ';', ',' => self.last = Token{ .value = value },
                            '=' => self.last = Token{ .key = value },
                            ']' => {
                                self.index -= 1;
                                self.last = Token{ .value = value };
                            },
                            else => {
                                self.index -= 1;
                                self.last = Token{ .value = value };
                            },
                        }
                    } else self.last = Token{ .value = value };
                },
            }
            self.index += 1;
            if (self.index >= self.content.len) try self.eof();
            return self.last;