Compare commits

...

5 Commits

Author SHA1 Message Date
Luna 6a52297cce readme: s/spoodle/vig 2019-08-26 13:43:07 -03:00
Luna bd036ff961 build.zig: s/spoodle/vig 2019-08-26 13:39:00 -03:00
Luna 45b027e90f add assignment to struct fields 2019-08-26 13:29:45 -03:00
Luna d55137a7c7 lift restraint on Calls being only made to Variables 2019-08-26 13:17:25 -03:00
Luna 0ecfb75081 add struct field getting 2019-08-26 13:15:08 -03:00
6 changed files with 112 additions and 28 deletions

View File

@ -1,10 +1,16 @@
# spoodle
# vig
a vlang parser in zig
a [v] parser in zig
[v]: https://vlang.io
(will likely be done as a full compiler, who knows, leave a like and subscribe
for more epic adventures)
## why
because i can
because i want to learn parsers and what best to do it with a language i'm
negatively charged towards
## variations
@ -17,7 +23,7 @@ because i can
## how
```
git clone https://gitdab.com/luna/spoodle.git
cd spoodle
git clone https://gitdab.com/luna/vig.git
cd vig
zig build install --prefix ~/.local/
```

View File

@ -2,7 +2,7 @@ const Builder = @import("std").build.Builder;
pub fn build(b: *Builder) void {
const mode = b.standardReleaseOptions();
const exe = b.addExecutable("spoodle", "src/main.zig");
const exe = b.addExecutable("vig", "src/main.zig");
exe.setBuildMode(mode);
const run_cmd = exe.run();

View File

@ -5,6 +5,11 @@ const (
Businesses = 4
)
struct Point {
x int
y int
}
fn main(a int) int {
1 + 2 + 3 + 4
1 + 1 * 1
@ -41,10 +46,7 @@ fn main(a int) int {
y: 20
}
//println(p.x)
}
p.x = 69
struct Point {
x int
y int
}
println(egg.scramble(3).with(cheddar))
}

View File

@ -80,6 +80,8 @@ pub const ExprType = enum {
Struct,
Grouping,
Get,
Set,
};
pub const VarDecl = struct {
@ -105,6 +107,17 @@ pub const StructExpr = struct {
inits: StructInitList,
};
pub const GetExpr = struct {
struc: *Expr,
name: Token,
};
pub const SetExpr = struct {
struc: *Expr,
field: Token,
value: *Expr,
};
pub const Expr = union(ExprType) {
Assign: AssignExpr,
VarDecl: VarDecl,
@ -118,6 +131,9 @@ pub const Expr = union(ExprType) {
Variable: Token,
Grouping: *Expr,
Call: CallExpr,
Get: GetExpr,
Set: SetExpr,
};
pub const Block = std.ArrayList(*Stmt);

View File

@ -4,6 +4,8 @@ const Token = tokens.Token;
usingnamespace @import("ast.zig");
const warn = std.debug.warn;
fn printIdent(ident: usize) void {
var i: usize = 0;
while (i < ident) : (i += 1) {
@ -177,6 +179,20 @@ pub fn printExpr(expr: *Expr) void {
std.debug.warn("))");
},
.Get => |get| {
warn("(");
printExpr(get.struc);
warn(".{})", get.name.lexeme);
},
.Set => |set| {
warn("(set ");
printExpr(set.struc);
warn(" {} ", set.field.lexeme);
printExpr(set.value);
warn(")");
},
else => std.debug.warn("UnknownExpr-{}", @tagName(expr.*)),
}
}

View File

@ -89,7 +89,11 @@ pub const Parser = struct {
}
fn consume(self: *Parser, ttype: TokenType, comptime msg: []const u8) !Token {
if (self.check(ttype)) return try self.nextToken();
if (self.check(ttype)) {
var tok = self.peek();
_ = try self.nextToken();
return tok;
}
try self.tokenError(self.peek(), msg);
return Result.CompileError;
@ -271,6 +275,31 @@ pub const Parser = struct {
return expr;
}
fn mkGet(self: *@This(), struc: *Expr, name: Token) !*Expr {
var expr = try self.allocator.create(Expr);
expr.* = Expr{
.Get = ast.GetExpr{
.struc = struc,
.name = name,
},
};
return expr;
}
fn mkSet(self: *@This(), struc: *Expr, field: Token, value: *Expr) !*Expr {
var expr = try self.allocator.create(Expr);
expr.* = Expr{
.Set = ast.SetExpr{
.struc = struc,
.field = field,
.value = value,
},
};
return expr;
}
fn mkBool(self: *Parser, val: bool) !*ast.Expr {
var expr = try self.allocator.create(Expr);
expr.* = Expr{
@ -582,15 +611,28 @@ pub const Parser = struct {
_ = try self.nextToken();
value = try self.parseAssignment();
if (ast.ExprType(expr.*) != .Variable) {
self.doError("Invalid assignment target");
return Result.CompileError;
}
switch (expr.*) {
.Variable => {
switch (op.ttype) {
.ColonEqual => return try self.mkVarDecl(expr.Variable, value, mutable),
.Equal => return try self.mkAssign(expr.Variable, value),
else => unreachable,
}
},
switch (op.ttype) {
.ColonEqual => return try self.mkVarDecl(expr.Variable, value, mutable),
.Equal => return try self.mkAssign(expr.Variable, value),
else => unreachable,
.Get => |get| {
if (op.ttype == .ColonEqual) {
self.doError("can not initialize struct field");
return Result.CompileError;
}
return try self.mkSet(get.struc, get.name, value);
},
else => |expr_typ| {
self.doError("Invalid assignment target {}", expr_typ);
return Result.CompileError;
},
}
}
@ -715,17 +757,18 @@ pub const Parser = struct {
printer.printExpr(expr);
if (self.check(.LeftParen)) {
if (ast.ExprType(expr.*) != .Variable) {
self.doError("cannot call non-variable {}", ast.ExprType(expr.*));
return Result.CompileError;
}
_ = try self.consumeSingle(.LeftParen);
expr = try self.finishCall(expr);
} else if (self.check(.Dot)) {
_ = try self.consumeSingle(.Dot);
_ = try self.consumeSingle(.LeftBrace);
expr = try self.finishStructVal(expr);
if (self.check(.LeftBrace)) {
_ = try self.consumeSingle(.LeftBrace);
expr = try self.finishStructVal(expr);
} else {
var name = try self.consume(.Identifier, "Expect property name after '.'");
expr = try self.mkGet(expr, name);
}
} else {
break;
}
@ -752,6 +795,7 @@ pub const Parser = struct {
}
}
// TODO shouldnt consume() return the current token, not nextToken?
var paren = try self.consume(.RightParen, "Expected ')' after arguments");
return self.mkCall(callee, paren, args);