Monkey 分为表达式和语句.学过rust可能好理解一些
其中语句只有: Let语句, Return语句, 表达式语句, 还有比较特殊的块语句
表达式有: if-else ,bool 表达式, 函数调用等.
书里面对于这个语法要求很严格, 像是()这些不可以省的, 后面具体解析的时候可以发现
pub const Statement = union(enum) { let_statement: *LetStatement, return_statement: *ReturnStatement, expression: *ExpressionStatement, block: *BlockStatement, pub fn tokenLiteral(self: *const Statement) []const u8 { return switch (self.*) { .let_statement => |ls| ls.token.Literal, .return_statement => |rs| rs.token.Literal, .expression => |es| es.tokenLiteral(), .block => |bs| bs.token.Literal, }; }
pub fn string(self: *Statement, allocator: std.mem.Allocator) std.mem.Allocator.Error![]const u8 { return switch (self.*) { .let_statement => |s| s.string(allocator), .return_statement => |s| s.string(allocator), .expression => |s| s.string(allocator), .block => |s| s.string(allocator), }; }};pub const Expression = union(enum) { identifier: *Identifier, boolean: *Boolean, integer: *IntegerLiteral, prefix: *PrefixExpression, infix: *InfixExpression, if_expr: *IfExpression, function: *FunctionLiteral, call: *CallExpression, pub fn tokenLiteral(self: *Expression) []const u8 { return switch (self.*) { .identifier => |i| i.token.Literal, .boolean => |b| b.token.Literal, .integer => |il| il.token.Literal, .prefix => |pe| pe.token.Literal, .infix => |ie| ie.token.Literal, .if_expr => |ie| ie.token.Literal, .function => |fl| fl.token.Literal, .call => |ce| ce.token.Literal, }; } pub fn string(self: *Expression, allocator: std.mem.Allocator) std.mem.Allocator.Error![]const u8 { return switch (self.*) { .identifier => |e| e.string(allocator), .boolean => |e| e.string(allocator), .integer => |e| e.string(allocator), .prefix => |e| e.string(allocator), .infix => |e| e.string(allocator), .if_expr => |e| e.string(allocator), .function => |e| e.string(allocator), .call => |e| e.string(allocator), }; }};tokenLiteral和string 方法是为了调试, 和书中保持同步, 这两个枚举中的想当于一个分发器.
pub const LetStatement = struct { token: token.Token, name: *Identifier, value: ?*Expression, pub fn tokenLiteral(self: *LetStatement) []const u8 { return self.token.Literal; } pub fn string(self: *LetStatement, gpa: std.mem.Allocator) ![]const u8 { var buf: std.ArrayList(u8) = .empty; try buf.appendSlice(gpa, self.token.Literal); try buf.append(gpa, ' '); const ns = try self.name.string(gpa); defer gpa.free(ns); try buf.appendSlice(gpa, ns); try buf.appendSlice(gpa, " = "); if (self.value) |stmt| { const vs = try stmt.string(gpa); defer gpa.free(vs); try buf.appendSlice(gpa, vs); } try buf.append(gpa, ';'); return buf.toOwnedSlice(gpa); }};let [identifier] = [expression] 的形式
pub const ReturnStatement = struct { token: token.Token, return_value: ?*Expression, pub fn tokenLiteral(self: *ReturnStatement) []const u8 { return self.token.Literal; } pub fn string(self: *ReturnStatement, allocator: std.mem.Allocator) ![]const u8 { var buf: std.ArrayList(u8) = .empty; try buf.appendSlice(allocator, self.token.Literal); try buf.append(allocator, ' '); if (self.return_value) |item| { const vs = try item.string(allocator); defer allocator.free(vs); try buf.appendSlice(allocator, vs); } try buf.append(allocator, ';'); return buf.toOwnedSlice(allocator); }};return [expression]
pub const ExpressionStatement = struct { token: token.Token, expression: ?*Expression,
pub fn tokenLiteral(self: *ExpressionStatement) []const u8 { return self.token.Literal; }
pub fn string(self: *ExpressionStatement, allocator: std.mem.Allocator) ![]const u8 { if (self.expression) |exp| { return exp.string(allocator); } return ""; }};像是 5 + 5;这样的
pub const BlockStatement = struct { token: token.Token, statements: std.ArrayList(*Statement),
pub fn tokenLiteral(self: *BlockStatement) []const u8 { return self.token.Literal; } pub fn string(self: *BlockStatement, allocator: std.mem.Allocator) ![]const u8 { var buf: std.ArrayList(u8) = .empty; for (self.statements.items) |value| { const s = try value.string(allocator); defer allocator.free(s); try buf.appendSlice(allocator, s); } return buf.toOwnedSlice(allocator); }};这个是{}中的语句
太多了, 挑几个重要的说吧
pub const PrefixExpression = struct { token: token.Token, // 前缀操作符 token operator: []const u8, right: ?*Expression,
pub fn tokenLiteral(self: *PrefixExpression) []const u8 { return self.token.Literal; }
pub fn string(self: *PrefixExpression, allocator: std.mem.Allocator) ![]const u8 { var buf: std.ArrayList(u8) = .empty; try buf.append(allocator, '('); try buf.appendSlice(allocator, self.operator); if (self.right) |r| { const rs = try r.string(allocator); defer allocator.free(rs); try buf.appendSlice(allocator, rs); } try buf.append(allocator, ')'); return buf.toOwnedSlice(allocator); }};对于形如: -5, !true, !-5这样的表达式
pub const InfixExpression = struct { token: token.Token, // 操作符 token,'+' left: ?*Expression, operator: []const u8, right: ?*Expression,
pub fn tokenLiteral(self: *InfixExpression) []const u8 { return self.token.Literal; }
pub fn string(self: *InfixExpression, allocator: std.mem.Allocator) ![]const u8 { var buf: std.ArrayList(u8) = .empty; try buf.append(allocator, '('); if (self.left) |l| { const ls = try l.string(allocator); defer allocator.free(ls); try buf.appendSlice(allocator, ls); } try buf.append(allocator, ' '); try buf.appendSlice(allocator, self.operator); try buf.append(allocator, ' '); if (self.right) |r| { const rs = try r.string(allocator); defer allocator.free(rs); try buf.appendSlice(allocator, rs); } try buf.append(allocator, ')'); return buf.toOwnedSlice(allocator); }};5 + 5 这样的
pub const IfExpression = struct { token: token.Token, condition: ?*Expression, consequence: ?*BlockStatement, alternative: ?*BlockStatement,
pub fn tokenLiteral(self: *IfExpression) []const u8 { return self.token.Literal; }
pub fn string(self: *IfExpression, allocator: std.mem.Allocator) ![]const u8 { var buf: std.ArrayList(u8) = .empty; try buf.appendSlice(allocator, "if"); if (self.condition) |cond| { const cs = try cond.string(allocator); defer allocator.free(cs); try buf.append(allocator, ' '); try buf.appendSlice(allocator, cs); } try buf.append(allocator, ' '); if (self.consequence) |cons| { const cs = try cons.string(allocator); defer allocator.free(cs); try buf.appendSlice(allocator, cs); } if (self.alternative) |alt| { try buf.appendSlice(allocator, "else "); const as = try alt.string(allocator); defer allocator.free(as); try buf.appendSlice(allocator, as); } return buf.toOwnedSlice(allocator); }};if (a == 5) {[statements]} 这样的, 一定要严格写括号!
pub const FunctionLiteral = struct { token: token.Token, parameters: std.ArrayListUnmanaged(*Identifier), body: ?*BlockStatement,
pub fn tokenLiteral(self: *FunctionLiteral) []const u8 { return self.token.Literal; } pub fn string(self: *FunctionLiteral, allocator: std.mem.Allocator) ![]const u8 { var buf = std.ArrayList(u8).empty; try buf.appendSlice(allocator, self.token.Literal); try buf.append(allocator, '('); for (self.parameters.items, 0..) |parm, i| { if (i > 0) try buf.appendSlice(allocator, ", "); const ps = try parm.string(allocator); defer allocator.free(ps); try buf.appendSlice(allocator, ps); } try buf.appendSlice(allocator, ") "); if (self.body) |b| { const bs = try b.string(allocator); defer allocator.free(bs); try buf.appendSlice(allocator, bs); } return try buf.toOwnedSlice(allocator); }};fn(x,y) {}
pub const CallExpression = struct { token: token.Token, function: ?*Expression, arguments: std.ArrayListUnmanaged(*Expression),
pub fn tokenLiteral(self: *CallExpression) []const u8 { return self.token.Literal; }
pub fn string(self: *CallExpression, allocator: std.mem.Allocator) ![]const u8 { var buf = std.ArrayList(u8).empty; if (self.function) |f| { const fs = try f.string(allocator); defer allocator.free(fs); try buf.appendSlice(allocator, fs); } try buf.append(allocator, '('); for (self.arguments.items, 0..) |arg, i| { if (i > 0) try buf.appendSlice(allocator, ", "); const arg_str = try arg.string(allocator); defer allocator.free(arg_str); try buf.appendSlice(allocator, arg_str); } try buf.append(allocator, ')'); return buf.toOwnedSlice(allocator); }};add(5,1)
这也没什么好说的.