Compare commits
29 Commits
Author | SHA1 | Date |
---|---|---|
Karchnu | c3c418c80c | |
Karchnu | 45b0f212a8 | |
Karchnu | 80d46f16e7 | |
Karchnu | 6d354fd7c2 | |
Karchnu | 5adcd203f9 | |
Karchnu | c460858a69 | |
Karchnu | 0e1dcf7342 | |
Karchnu | 80a94a5fdd | |
Karchnu | 3d604c3238 | |
Karchnu | eac5b58017 | |
Karchnu | 78080c43a0 | |
Karchnu | 00eac1ff5f | |
Karchnu | 0ec3b80d6c | |
Karchnu | 8a0abd070e | |
Karchnu | bf8283b7cf | |
Karchnu | 70d0454695 | |
Karchnu | 1bea958fed | |
Karchnu | bf6aa3ecf6 | |
Karchnu | 4f6891c4ab | |
Karchnu | c887e2d786 | |
Karchnu | 46df247608 | |
Karchnu | 6e9f8cf142 | |
Karchnu | 3bfff518b2 | |
Karchnu | dc61c8ee6f | |
Karchnu | 69122b1e7b | |
Karchnu | 78afcf554e | |
Karchnu | 0d9130ec89 | |
Karchnu | a93c718e1f | |
Karchnu | 774fff73a4 |
|
@ -1,7 +1,9 @@
|
||||||
|
|
||||||
|
# This is a comment.
|
||||||
Object {
|
Object {
|
||||||
property string thing: "i has the thing"
|
property string thing: "i has the thing"
|
||||||
|
|
||||||
Object {
|
Object (my-children-id) {
|
||||||
property string thing: "i has the other thing"
|
property string thing: "i has the other thing"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
Text (my-identifier) {
|
||||||
|
text: "Hello, there!"
|
||||||
|
font {
|
||||||
|
family: "SansSerif"
|
||||||
|
pixelSize: 15
|
||||||
|
}
|
||||||
|
width: 200
|
||||||
|
height: 200
|
||||||
|
}
|
|
@ -1,12 +1,12 @@
|
||||||
Rectangle {
|
Rectangle {
|
||||||
color: "red"
|
property String color: "red"
|
||||||
width: 300
|
property Int width: 300
|
||||||
height: 200
|
property Int height: 200
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
color: "blue"
|
property String color: "blue"
|
||||||
width: 100
|
property Int width: 100
|
||||||
height: 100
|
property Int height: 100
|
||||||
|
|
||||||
anchors {
|
anchors {
|
||||||
top: 50
|
top: 50
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: clickable
|
id: clickable
|
||||||
color: "blue"
|
color: "blue"
|
||||||
width: 300
|
width: 300
|
||||||
height: 300
|
height: 300
|
||||||
onClick: emit ["hello, there", "i has events"]
|
onClick: emit ["hello, there", "i has events"]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,51 +1,185 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const hashString = std.hash_map.hashString;
|
|
||||||
const eqlString = std.hash_map.eqlString;
|
|
||||||
const HashMap = std.HashMap;
|
|
||||||
const AutoHashMap = std.AutoHashMap;
|
const AutoHashMap = std.AutoHashMap;
|
||||||
const ArrayList = std.ArrayList;
|
const ArrayList = std.ArrayList;
|
||||||
|
|
||||||
|
/// This file introduces the main structures used by guid once running.
|
||||||
|
/// Tests show how to use them.
|
||||||
|
/// Type.create do no allocate memory for the structure, only to its attributes.
|
||||||
|
/// Type.deinit works in cascade (deinit its children).
|
||||||
|
|
||||||
const PropertyHashMap = AutoHashMap([] const u8, PropertyValue);
|
const PropertyHashMap = AutoHashMap([] const u8, PropertyValue);
|
||||||
const NodeList = ArrayList(Node);
|
const NodeList = ArrayList(Node);
|
||||||
const Definitions = AutoHashMap([] const u8, Node);
|
const DefinitionHashMap = AutoHashMap([] const u8, Node);
|
||||||
|
|
||||||
|
|
||||||
pub const Node = struct {
|
pub const Node = struct {
|
||||||
id: ?[] const u8,
|
id: ?[] const u8,
|
||||||
type_name: [] const u8,
|
type_name: [] const u8,
|
||||||
properties: PropertyHashMap,
|
properties: PropertyHashMap,
|
||||||
children: NodeList,
|
children: NodeList,
|
||||||
|
|
||||||
|
gpa: *Allocator,
|
||||||
|
|
||||||
|
pub fn deinit(self: *Node) void {
|
||||||
|
self.properties.deinit();
|
||||||
|
for (self.children.items) |*value| {
|
||||||
|
value.deinit();
|
||||||
|
}
|
||||||
|
self.children.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create(allocator: *Allocator, type_name: []const u8, id: ?[]const u8) !Node {
|
||||||
|
return Node{
|
||||||
|
.id = id,
|
||||||
|
.type_name = type_name,
|
||||||
|
.properties = PropertyHashMap.init(allocator),
|
||||||
|
.children = NodeList.init(allocator),
|
||||||
|
.gpa = allocator,
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const PropertyValue = union {
|
const PropertyValueTags = enum {
|
||||||
string: [] const u8, // String.
|
string,
|
||||||
integer: u64, // Num (integer).
|
integer,
|
||||||
float: f64, // Num (float).
|
float,
|
||||||
reference: *u8, // Reference to another property (property binding).
|
reference,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Root = struct {
|
pub const PropertyValue = union(PropertyValueTags) {
|
||||||
definitions: Definitions,
|
// nil: null,
|
||||||
|
string: [] const u8, // String.
|
||||||
|
integer: u64, // Num (integer).
|
||||||
|
float: f64, // Num (float).
|
||||||
|
reference: [] const u8, // Reference to another property (property binding).
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Tree = struct {
|
||||||
|
definitions: DefinitionHashMap,
|
||||||
children: NodeList,
|
children: NodeList,
|
||||||
|
|
||||||
|
gpa: *Allocator,
|
||||||
|
|
||||||
|
pub fn deinit(self: *Tree) void {
|
||||||
|
self.definitions.deinit();
|
||||||
|
for (self.children.items) |*value| {
|
||||||
|
value.deinit();
|
||||||
|
}
|
||||||
|
self.children.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create(allocator: *Allocator) !Tree {
|
||||||
|
return Tree{
|
||||||
|
.definitions = DefinitionHashMap.init(allocator),
|
||||||
|
.children = NodeList.init(allocator),
|
||||||
|
.gpa = allocator,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
test "simple test about structures" {
|
// TESTS and private util functions.
|
||||||
const allocator = std.heap.page_allocator;
|
|
||||||
var value = PropertyValue { .integer = 10 };
|
|
||||||
|
|
||||||
var properties = PropertyHashMap.init(allocator);
|
fn say(tosay: []const u8) void {
|
||||||
defer properties.deinit();
|
std.debug.print("{}", .{tosay});
|
||||||
|
}
|
||||||
|
|
||||||
try properties.put("hello", value);
|
fn print_properties(properties: PropertyHashMap) void {
|
||||||
|
|
||||||
std.debug.print("\n", .{});
|
|
||||||
var it = properties.iterator();
|
var it = properties.iterator();
|
||||||
while(it.next()) |kv| {
|
while(it.next()) |kv| {
|
||||||
std.debug.print("key: {} => value: {}\n", .{kv.key, properties.get(kv.key)});
|
std.debug.print("\t{} => {}\n", .{kv.key, properties.get(kv.key)});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn print_node(node: Node) void {
|
||||||
|
std.debug.print("Node type {} (id: {})\n", .{node.type_name, node.id});
|
||||||
|
print_properties(node.properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_tree(tree: Tree) void {
|
||||||
|
say("\ntree.definitions:\n");
|
||||||
|
var it = tree.definitions.iterator();
|
||||||
|
while(it.next()) |kv| {
|
||||||
|
std.debug.print("{} => ", .{kv.key});
|
||||||
|
const node = tree.definitions.get(kv.key);
|
||||||
|
if(node) |n| { print_node(n); }
|
||||||
|
}
|
||||||
|
|
||||||
|
say("tree.children:\n");
|
||||||
|
for(tree.children.items) |v, k| {
|
||||||
|
std.debug.print("{} => ", .{k});
|
||||||
|
print_node(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test "simple test about structures" {
|
||||||
|
var gpa = std.heap.GeneralPurposeAllocator(.{.safety = true}){};
|
||||||
|
const allocator = &gpa.allocator;
|
||||||
|
|
||||||
|
var value = PropertyValue { .integer = 10 };
|
||||||
|
var properties = PropertyHashMap.init(allocator);
|
||||||
|
try properties.put("hello", value);
|
||||||
|
|
||||||
|
// Displaying the content.
|
||||||
|
// say("\n");
|
||||||
|
// print_properties(properties);
|
||||||
|
|
||||||
|
// Freeing the properties.
|
||||||
|
properties.deinit();
|
||||||
|
|
||||||
|
// Testing memory leaks at the end of the test.
|
||||||
|
const leaks = gpa.deinit();
|
||||||
|
if (leaks) {
|
||||||
|
say("\nthere were leaks, oh no\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
say("\nno leaks, yay!\n");
|
||||||
|
}
|
||||||
|
std.testing.expect(! leaks);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_stuff(allocator: *Allocator) !Tree {
|
||||||
|
var tree = try Tree.create(allocator);
|
||||||
|
|
||||||
|
// Creating a definition and a few children.
|
||||||
|
try tree.definitions.put("MyObject", try Node.create(allocator, "my-type-name", "my-id"));
|
||||||
|
var new_node = try Node.create(allocator, "Object", "some-id-for-this-object");
|
||||||
|
var value = PropertyValue { .integer = 10 };
|
||||||
|
try new_node.properties.put("integer-val", value);
|
||||||
|
value = PropertyValue { .string = "some value" };
|
||||||
|
try new_node.properties.put("string-val", value);
|
||||||
|
|
||||||
|
try tree.children.append(new_node);
|
||||||
|
try tree.children.append(try Node.create(allocator, "Object", "my-id"));
|
||||||
|
try tree.children.append(try Node.create(allocator, "OtherObject", null));
|
||||||
|
try tree.children.append(try Node.create(allocator, "Text", "my-id-for-text-object"));
|
||||||
|
|
||||||
|
return tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
test "init a Tree structure" {
|
||||||
|
// Allocator with safety on: checking for memory leaks.
|
||||||
|
var gpa = std.heap.GeneralPurposeAllocator(.{.safety = true}){};
|
||||||
|
const allocator = &gpa.allocator;
|
||||||
|
|
||||||
|
// Creating a tree.
|
||||||
|
var tree = try init_stuff(allocator);
|
||||||
|
|
||||||
|
// Display the content of the tree.
|
||||||
|
// print_tree(tree);
|
||||||
|
|
||||||
|
// Freeing the tree.
|
||||||
|
tree.deinit();
|
||||||
|
|
||||||
|
// Testing memory leaks at the end of the test.
|
||||||
|
const leaks = gpa.deinit();
|
||||||
|
if (leaks) {
|
||||||
|
say("\nthere were leaks, oh no\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
say("\nno leaks, yay!\n");
|
||||||
|
}
|
||||||
|
std.testing.expect(! leaks);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
3573
src/parse.zig
3573
src/parse.zig
File diff suppressed because it is too large
Load Diff
|
@ -1,13 +1,3 @@
|
||||||
// test "recovery: invalid parameter" {
|
|
||||||
// try testError(
|
|
||||||
// \\fn main() void {
|
|
||||||
// \\ a(comptime T: type)
|
|
||||||
// \\}
|
|
||||||
// , &[_]Error{
|
|
||||||
// .ExpectedToken,
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const mem = std.mem;
|
const mem = std.mem;
|
||||||
const warn = std.debug.warn;
|
const warn = std.debug.warn;
|
||||||
|
@ -23,33 +13,34 @@ const own_parser = @import("./parse.zig");
|
||||||
fn testParse(source: []const u8, allocator: *mem.Allocator) !void {
|
fn testParse(source: []const u8, allocator: *mem.Allocator) !void {
|
||||||
const stderr = io.getStdErr().outStream();
|
const stderr = io.getStdErr().outStream();
|
||||||
|
|
||||||
const tree = try own_parser.parse(allocator, source);
|
var tree = try own_parser.parse(allocator, source);
|
||||||
defer tree.deinit();
|
defer tree.deinit();
|
||||||
|
|
||||||
for (tree.errors) |*parse_error| {
|
// for (tree.errors) |*parse_error| {
|
||||||
const token = tree.token_locs[parse_error.loc()];
|
// const token = tree.token_locs[parse_error.loc()];
|
||||||
const loc = tree.tokenLocation(0, parse_error.loc());
|
// const loc = tree.tokenLocation(0, parse_error.loc());
|
||||||
try stderr.print("(memory buffer):{}:{}: error: ", .{ loc.line + 1, loc.column + 1 });
|
// try stderr.print("(memory buffer):{}:{}: error: ", .{ loc.line + 1, loc.column + 1 });
|
||||||
try tree.renderError(parse_error, stderr);
|
// try tree.renderError(parse_error, stderr);
|
||||||
try stderr.print("\n{}\n", .{source[loc.line_start..loc.line_end]});
|
// try stderr.print("\n{}\n", .{source[loc.line_start..loc.line_end]});
|
||||||
{
|
// {
|
||||||
var i: usize = 0;
|
// var i: usize = 0;
|
||||||
while (i < loc.column) : (i += 1) {
|
// while (i < loc.column) : (i += 1) {
|
||||||
try stderr.writeAll(" ");
|
// try stderr.writeAll(" ");
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
{
|
// {
|
||||||
const caret_count = token.end - token.start;
|
// const caret_count = token.end - token.start;
|
||||||
var i: usize = 0;
|
// var i: usize = 0;
|
||||||
while (i < caret_count) : (i += 1) {
|
// while (i < caret_count) : (i += 1) {
|
||||||
try stderr.writeAll("~");
|
// try stderr.writeAll("~");
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
try stderr.writeAll("\n");
|
// try stderr.writeAll("\n");
|
||||||
}
|
// }
|
||||||
if (tree.errors.len != 0) {
|
|
||||||
return error.ParseError;
|
// if (tree.errors.len != 0) {
|
||||||
}
|
// return error.ParseError;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
const Error = @TagType(ast.Error);
|
const Error = @TagType(ast.Error);
|
||||||
|
|
|
@ -12,16 +12,13 @@ pub const Token = struct {
|
||||||
|
|
||||||
pub const keywords = std.ComptimeStringMap(Id, .{
|
pub const keywords = std.ComptimeStringMap(Id, .{
|
||||||
.{ "property", .Keyword_property },
|
.{ "property", .Keyword_property },
|
||||||
|
.{ "define", .Keyword_define },
|
||||||
|
.{ "require", .Keyword_require },
|
||||||
.{ "false", .Keyword_false },
|
.{ "false", .Keyword_false },
|
||||||
.{ "null", .Keyword_null },
|
.{ "null", .Keyword_null },
|
||||||
.{ "true", .Keyword_true },
|
.{ "true", .Keyword_true },
|
||||||
.{ "undefined", .Keyword_undefined },
|
.{ "undefined", .Keyword_undefined },
|
||||||
|
|
||||||
.{ "text", .Keyword_text },
|
|
||||||
.{ "pixel-size", .Keyword_pixel_size },
|
|
||||||
.{ "family", .Keyword_family },
|
|
||||||
.{ "height", .Keyword_height },
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
pub fn getKeyword(bytes: []const u8) ?Id {
|
pub fn getKeyword(bytes: []const u8) ?Id {
|
||||||
|
@ -99,16 +96,13 @@ pub const Token = struct {
|
||||||
ShebangLine,
|
ShebangLine,
|
||||||
|
|
||||||
Keyword_property,
|
Keyword_property,
|
||||||
|
Keyword_define,
|
||||||
|
Keyword_require,
|
||||||
Keyword_false,
|
Keyword_false,
|
||||||
Keyword_null,
|
Keyword_null,
|
||||||
Keyword_true,
|
Keyword_true,
|
||||||
Keyword_undefined,
|
Keyword_undefined,
|
||||||
|
|
||||||
Keyword_text,
|
|
||||||
Keyword_pixel_size,
|
|
||||||
Keyword_family,
|
|
||||||
Keyword_height,
|
|
||||||
|
|
||||||
pub fn symbol(id: Id) []const u8 {
|
pub fn symbol(id: Id) []const u8 {
|
||||||
return switch (id) {
|
return switch (id) {
|
||||||
.Invalid => "Invalid",
|
.Invalid => "Invalid",
|
||||||
|
@ -182,16 +176,13 @@ pub const Token = struct {
|
||||||
.Tilde => "~",
|
.Tilde => "~",
|
||||||
|
|
||||||
.Keyword_property => "property",
|
.Keyword_property => "property",
|
||||||
|
.Keyword_define => "define",
|
||||||
|
.Keyword_require => "require",
|
||||||
.Keyword_false => "false",
|
.Keyword_false => "false",
|
||||||
.Keyword_null => "null",
|
.Keyword_null => "null",
|
||||||
.Keyword_true => "true",
|
.Keyword_true => "true",
|
||||||
.Keyword_undefined => "undefined",
|
.Keyword_undefined => "undefined",
|
||||||
|
|
||||||
.Keyword_text => "text",
|
|
||||||
.Keyword_pixel_size => "pixel-size",
|
|
||||||
.Keyword_family => "family",
|
|
||||||
.Keyword_height => "height",
|
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -562,7 +553,9 @@ pub const Tokenizer = struct {
|
||||||
},
|
},
|
||||||
|
|
||||||
.identifier => switch (c) {
|
.identifier => switch (c) {
|
||||||
'a'...'z', 'A'...'Z', '_', '0'...'9' => {},
|
// Include "-", "+" and "?" as an identifer token, this is the only difference
|
||||||
|
// with the Zig tokenizer.
|
||||||
|
'a'...'z', 'A'...'Z', '_', '-', '+', '?', '0'...'9' => {},
|
||||||
else => {
|
else => {
|
||||||
if (Token.getKeyword(self.buffer[result.loc.start..self.index])) |id| {
|
if (Token.getKeyword(self.buffer[result.loc.start..self.index])) |id| {
|
||||||
result.id = id;
|
result.id = id;
|
||||||
|
|
Loading…
Reference in New Issue