Skip to content

Commit

Permalink
Eval: Add String DataType, fix: Intparsing Error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
kamva9697 committed Dec 23, 2023
1 parent 1a643d7 commit c718c16
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 39 deletions.
94 changes: 56 additions & 38 deletions src/ast.zig
Original file line number Diff line number Diff line change
Expand Up @@ -6,44 +6,7 @@ const ArrayList = std.ArrayList;
const Parser = @import("parser.zig");
const io = std.io;

pub const Operator = enum {
plus,
minus,
multiply,
divide,
not,
greater_than,
less_than,
equal_to,
not_equal_to,

pub fn toString(op: Operator) []const u8 {
return switch (op) {
Operator.plus => "+",
Operator.minus => "-",
Operator.multiply => "*",
Operator.divide => "/",
Operator.not => "!",
Operator.greater_than => ">",
Operator.less_than => "<",
Operator.equal_to => "==",
Operator.not_equal_to => "!=",
};
}
pub fn fromString(literal: []const u8) ?Operator {
const ops = @typeInfo(Operator).Enum.fields;
inline for (ops) |op| {
const operator: Operator = @enumFromInt(op.value);

if (std.mem.eql(u8, operator.toString(), literal)) {
return operator;
}
}
return null;
}
};

///// Abstract Types/ Interfaces //////
///// Base Type//////
pub const Node = struct {
id: Id,

Expand All @@ -59,6 +22,7 @@ pub const Node = struct {
IfExpression,
Block,
FunctionLiteral,
StringLiteral,
CallExpression,

pub fn Type(comptime id: Id) type {
Expand All @@ -73,6 +37,7 @@ pub const Node = struct {
.Boolean => Boolean,
.IfExpression => IfExpression,
.Block => Block,
.StringLiteral => StringLiteral,
.FunctionLiteral => FunctionLiteral,
.CallExpression => CallExpression,
};
Expand All @@ -98,6 +63,18 @@ pub const Node = struct {
return &self.base;
}
};

pub const StringLiteral = struct {
pub const Self = @This();
base: Node = .{ .id = .StringLiteral },
token: Token,
value: []const u8,

pub inline fn toNode(self: *Self) *Node {
return &self.base;
}
};

pub const ReturnStatement = struct {
pub const Self = @This();
base: Node = .{ .id = .ReturnStatement },
Expand Down Expand Up @@ -345,6 +322,10 @@ pub const Node = struct {

try (&functionLiteralNode.body.base).toString(writer);
},
.StringLiteral => {
const stringNode = node.cast(.StringLiteral);
try writer.writeAll(stringNode.value);
},
.CallExpression => {
var callExpressionNode = node.cast(.CallExpression);

Expand Down Expand Up @@ -419,3 +400,40 @@ test "Tree Test" {

try testing.expectEqualStrings("let myVar = anotherVar;", buf.items);
}

pub const Operator = enum {
plus,
minus,
multiply,
divide,
not,
greater_than,
less_than,
equal_to,
not_equal_to,

pub fn toString(op: Operator) []const u8 {
return switch (op) {
Operator.plus => "+",
Operator.minus => "-",
Operator.multiply => "*",
Operator.divide => "/",
Operator.not => "!",
Operator.greater_than => ">",
Operator.less_than => "<",
Operator.equal_to => "==",
Operator.not_equal_to => "!=",
};
}
pub fn fromString(literal: []const u8) ?Operator {
const ops = @typeInfo(Operator).Enum.fields;
inline for (ops) |op| {
const operator: Operator = @enumFromInt(op.value);

if (std.mem.eql(u8, operator.toString(), literal)) {
return operator;
}
}
return null;
}
};
11 changes: 11 additions & 0 deletions src/evaluator.zig
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,17 @@ pub fn eval(
);
return obj.toObject();
},
.StringLiteral => {
const strNode = node.cast(.StringLiteral);
const obj = try Object.create(
Object.String,
alloc,
Object.String{
.value = strNode.value,
},
);
return obj.toObject();
},
.Boolean => {
const boolNode = node.cast(.Boolean);
const obj = if (boolNode.value) @constCast(TRUE_VALUE) else @constCast(FALSE_VALUE);
Expand Down
16 changes: 16 additions & 0 deletions src/lexer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ pub const Lexer = struct {
'|' => .{ .Type = .OR, .Literal = token.OR },
'&' => .{ .Type = .AND, .Literal = token.AND },
'^' => .{ .Type = .XOR, .Literal = token.XOR },
'\"' => blk: {
const literal = self.readString();
break :blk .{ .Type = .STRING, .Literal = literal };
},
'=' => blk: {
if (self.input[self.peekPosition] == '=') {
self.readChar();
Expand Down Expand Up @@ -69,6 +73,18 @@ pub const Lexer = struct {
};
}

// TODO: Test case
pub inline fn readString(self: *Lexer) []const u8 {
const position = self.position + 1;

self.readChar(); // consume opening '"'
while (self.ch != '\"' or self.ch == 0) {
self.readChar();
}

return self.input[position..self.position];
}

pub inline fn readChar(self: *Lexer) void {
if (self.peekPosition >= self.input.len) {
self.ch = 0;
Expand Down
16 changes: 16 additions & 0 deletions src/object.zig
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub const Object = struct {
ReturnValue,
Function,
Error,
String,

pub inline fn Type(comptime ty: ObjectType) type {
return switch (ty) {
Expand All @@ -29,6 +30,7 @@ pub const Object = struct {
.Null => Null,
.ReturnValue => ReturnValue,
.Function => Function,
.String => String,
.Error => Error,
};
}
Expand All @@ -39,6 +41,7 @@ pub const Object = struct {
.Null => "Null",
.ReturnValue => "ReturnValue",
.Function => "Function",
.String => "String",
.Error => "Error",
};
}
Expand Down Expand Up @@ -71,6 +74,10 @@ pub const Object = struct {
.Null => {
try writer.print("null", .{});
},
.String => {
const str = cast(self, .String);
try writer.print("{s}", .{str.value});
},
.Function => {
const func = cast(self, .Function);

Expand All @@ -93,6 +100,15 @@ pub const Object = struct {
},
}
}
pub const String = struct {
pub const Self = @This();
base: Object = .{ .ty = .String },
value: []const u8,

pub inline fn toObject(self: *Self) *Object {
return &self.base;
}
};

pub const Function = struct {
pub const Self = @This();
Expand Down
32 changes: 31 additions & 1 deletion src/parser.zig
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub const Parser = struct {
NoPrefixParseFn,
UnexpectedToken,
ParameterListTooLong,
InvalidCharacter,
TypeMismatch,
UnknownOperator,
};
Expand Down Expand Up @@ -74,6 +75,7 @@ pub const Parser = struct {
.errors = .{},
};

p.registerPrefix(TokenType.STRING, &parseStringLiteral);
p.registerInfix(TokenType.LPAREN, &parseCallExpression);
p.registerPrefix(TokenType.FUNCTION, &parseFunctionLiteral);
p.registerPrefix(TokenType.IF, &parseIfExpression);
Expand Down Expand Up @@ -211,7 +213,13 @@ pub const Parser = struct {
return exprPtr;
}

// Parse Literals
pub fn parseStringLiteral(self: *Parser) !?*Node {
const lit = try self.arena.allocator().create(Node.StringLiteral);
lit.* = Node.StringLiteral{ .token = self.curToken, .value = self.curToken.Literal };
return lit.toNode();
}

// Parse Function Literals
pub fn parseFunctionLiteral(self: *Parser) !?*Node {
var lit = try self.arena.allocator().create(Node.FunctionLiteral);

Expand Down Expand Up @@ -286,6 +294,10 @@ pub const Parser = struct {

litPtr.* = Node.IntegerLiteral{ .token = self.curToken, .value = undefined };

if (!(try self.isDigit(litPtr.token.Literal))) {
return litPtr.toNode();
}

litPtr.value = try std.fmt.parseInt(u32, litPtr.token.Literal, 10);

return litPtr.toNode();
Expand Down Expand Up @@ -442,6 +454,24 @@ pub const Parser = struct {
}

///////////// Utilities ////////////////////////
pub inline fn isDigit(self: *Parser, num: []const u8) !bool {
for (num) |c| {
if (!std.ascii.isDigit(c)) {
const ctx: ParserErrorContext = .{
.err = ParserError.InvalidCharacter,
.msg = try std.fmt.ParseIntError.allocPrint(
self.arena.allocator(),
"Invalid Integer Character: {c} in {s}",
.{ c, num },
),
};

try self.errors.append(self.arena.allocator(), ctx);
return false;
}
}
return true;
}
pub inline fn peekPrecedence(self: *Parser) Precedence {
return Precedence.fromTokenType(self.peekToken.Type);
}
Expand Down
2 changes: 2 additions & 0 deletions src/token.zig
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub const TokenType = enum {
// identifiers and literals
IDENT,
INT,
STRING,

//Delimiters
COMMA,
Expand Down Expand Up @@ -110,3 +111,4 @@ pub const LPAREN = "(";
pub const RPAREN = ")";
pub const LBRACE = "{";
pub const RBRACE = "}";
pub const STRING = "STRING";

0 comments on commit c718c16

Please sign in to comment.