split access modifier parsing into own func

- revamp parsing of access modifiers so it is correct
This commit is contained in:
Luna 2019-08-26 21:43:58 -03:00
parent 96d48f8762
commit ac5d29819c
3 changed files with 63 additions and 13 deletions

View file

@ -54,3 +54,16 @@ fn main(a int) int {
} }
fn (v Typ) voidfunc() {} fn (v Typ) voidfunc() {}
struct Foo {
a int
mut:
b int
c int
pub:
d int
pub mut:
e int
pub mut mut:
f int
}

View file

@ -107,6 +107,10 @@ pub fn printNode(node: *Node, ident: usize) void {
std.debug.warn("pub "); std.debug.warn("pub ");
} }
if (field.mutable_outside) {
std.debug.warn("MUT_OUT ");
}
std.debug.warn("{} {})\n", field.name.lexeme, field.typ.lexeme); std.debug.warn("{} {})\n", field.name.lexeme, field.typ.lexeme);
} }
print(ident, "))\n"); print(ident, "))\n");

View file

@ -502,19 +502,7 @@ pub const Parser = struct {
var field_state = FieldState{}; var field_state = FieldState{};
while (!self.check(.RightBrace)) { while (!self.check(.RightBrace)) {
if (self.check(.Mut)) { try self.parseFieldModifiers(&field_state);
_ = try self.consumeSingle(.Mut);
_ = try self.consumeSingle(.Colon);
if (field_state.mutable) {
field_state.mutable_outside = true;
} else {
field_state.mutable = true;
}
} else if (self.check(.Pub)) {
_ = try self.consumeSingle(.Pub);
_ = try self.consumeSingle(.Colon);
field_state.public = true;
}
const field_name = try self.consumeSingle(.Identifier); const field_name = try self.consumeSingle(.Identifier);
const field_type = try self.consumeSingle(.Identifier); const field_type = try self.consumeSingle(.Identifier);
@ -538,6 +526,51 @@ pub const Parser = struct {
return Node.mkStructDecl(self.allocator, name, fields); return Node.mkStructDecl(self.allocator, name, fields);
} }
fn parseFieldModifiers(self: *@This(), field_state: *FieldState) !void {
// there are five access modifiers:
// - none (private immutable)
// - mut (private mutable)
// - pub (public immutable)
// - pub mut (public mutable only in module)
// - pub mut mut (public mutable everywhere)
// this function takes care of that by changing the current FieldState
// to what the modifiers dictate.
switch (self.peek().ttype) {
.Mut => {
// There are no oher modifiers that start with mut, so we
// can just go the way of marking it as mutable
_ = try self.consumeSingle(.Mut);
_ = try self.consumeSingle(.Colon);
field_state.mutable = true;
},
// 'pub', 'pub mut', and 'pub mut mut' are all handled here
.Pub => {
_ = try self.consumeSingle(.Pub);
field_state.public = true;
if (self.check(.Mut)) {
_ = try self.consumeSingle(.Mut);
field_state.mutable = true;
if (self.check(.Mut)) {
_ = try self.consumeSingle(.Mut);
field_state.mutable_outside = true;
}
}
_ = try self.consumeSingle(.Colon);
},
// if it isn't mut or pub we're likely in an identifier, just
// ignore it.
else => return,
}
}
fn parseTopDecl(self: *@This()) !*Node { fn parseTopDecl(self: *@This()) !*Node {
return switch (self.peek().ttype) { return switch (self.peek().ttype) {
.Fn => try self.parseFnDecl(), .Fn => try self.parseFnDecl(),