Skip to content

Commit

Permalink
Merge pull request #104 from Raiden1411/translate_solidity
Browse files Browse the repository at this point in the history
feat: add hability to translate solidity to zig
  • Loading branch information
Raiden1411 authored Sep 26, 2024
2 parents 22be15e + 4843243 commit b02f761
Show file tree
Hide file tree
Showing 7 changed files with 1,526 additions and 109 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ You can install the latest version of zig [here](https://ziglang.org/download/)
- BlockExplorer support. Only the free methods from those api endpoints are supported.
- Custom Secp256k1 ECDSA signer using only Zig and implementation of RFC6979 nonce generator.
- Custom JSON Parser that can be used to deserialize and serialized RPC data at runtime.
- Custom solidity tokenizer and parser generator.
- Hability to translate solidity source code to zig.
- ABI to zig types.
- Support for EIP712.
- Support for EIP3074 authorization message.
Expand Down
2 changes: 2 additions & 0 deletions docs/pages/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ You can install the latest version of zig [here](https://ziglang.org/download/)
- BlockExplorer support. Only the free methods from those api endpoints are supported.
- Custom Secp256k1 ECDSA signer using only Zig and implementation of RFC6979 nonce generator.
- Custom JSON Parser that can be used to deserialize and serialized RPC data at runtime.
- Custom solidity tokenizer and parser generator.
- Hability to translate solidity source code to zig.
- ABI to zig types.
- Support for EIP712.
- Support for EIP3074 authorization message.
Expand Down
171 changes: 144 additions & 27 deletions src/ast/Ast.zig

Large diffs are not rendered by default.

203 changes: 123 additions & 80 deletions src/ast/Parser.zig
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,13 @@ pub fn parseSourceUnit(self: *Parser) ParserErrors!Node.Index {
.keyword_event => return self.parseEvent(),
.keyword_type => return self.parseUserTypeDefinition(),
.keyword_using => return self.parseUsingDirective(),
.keyword_function => return self.parseFunctionDecl(),
else => return self.parseStateVariableDecl(),
.keyword_function => switch (self.token_tags[self.token_index + 1]) {
.identifier => return self.parseFunctionDecl(),
.l_paren => return self.parseConstantVariableDecl(),
else => return null_node,
},

else => return self.parseConstantVariableDecl(),
}
}
/// Parses a `contract_decl`, `interface_decl`, or `library_decl` according to the [grammar](https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.contractDefinition)
Expand Down Expand Up @@ -499,14 +504,10 @@ pub fn parseContractElementBody(self: *Parser) ParserErrors!Node.Index {
}
},
.keyword_function => {
const backup = self.token_index;
const proto = self.parseFullFunctionProto() catch |err| switch (err) {
error.OutOfMemory => return err,
error.ParsingError => {
// We reset the index since it probably moved.
self.token_index = backup;
return self.parseStateVariableDecl();
},
const proto = switch (self.token_tags[self.token_index + 1]) {
.identifier => try self.parseFullFunctionProto(),
.l_paren => return self.parseStateVariableDecl(),
else => return null_node,
};

switch (self.token_tags[self.token_index]) {
Expand Down Expand Up @@ -714,6 +715,29 @@ pub fn parseUsingAlias(self: *Parser) ParserErrors!Span {
else => Span{ .multi = try self.listToSpan(slice) },
};
}
/// [Grammar](https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.constantVariableDeclaration)
pub fn parseConstantVariableDecl(self: *Parser) ParserErrors!Node.Index {
const type_decl = try self.parseTypeExpr();

if (type_decl == 0)
return null_node;

_ = self.consumeToken(.keyword_constant) orelse return null_node;
const identifier = try self.expectToken(.identifier);

_ = try self.expectToken(.equal);
const expr = try self.expectExpr();
try self.expectSemicolon();

return self.addNode(.{
.tag = .constant_variable_decl,
.main_token = identifier,
.data = .{
.lhs = type_decl,
.rhs = expr,
},
});
}
/// [Grammar](https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.stateVariableDeclaration)
pub fn parseStateVariableDecl(self: *Parser) ParserErrors!Node.Index {
const type_decl = try self.parseTypeExpr();
Expand Down Expand Up @@ -1071,7 +1095,7 @@ pub fn parseConstructor(self: *Parser) ParserErrors!Node.Index {
},
}),
.multi => |elems| self.addNode(.{
.tag = .construct_decl_one,
.tag = .construct_decl,
.main_token = index,
.data = .{
.lhs = try self.addExtraData(Node.ConstructorProto{
Expand All @@ -1090,11 +1114,17 @@ pub fn parseInheritanceSpecifiers(self: *Parser) ParserErrors!Span {
defer self.scratch.shrinkRetainingCapacity(scratch);

while (true) {
const specificer = try self.parseSuffixExpr();
const specificer = try self.consumeIdentifierPath();

if (specificer != 0)
if (specificer != 0) {
try self.scratch.append(self.allocator, specificer);

const call = try self.parseCallExpression(specificer);

if (call != 0)
try self.scratch.append(self.allocator, call);
}

switch (self.token_tags[self.token_index]) {
.comma => self.token_index += 1,
.l_brace => break,
Expand Down Expand Up @@ -1135,21 +1165,6 @@ pub fn parseBlock(self: *Parser) ParserErrors!Node.Index {
if (self.token_tags[self.token_index] == .r_brace)
break;

if (self.consumeToken(.keyword_unchecked)) |token| {
const block = try self.expectBlock();

const unchecked = try self.addNode(.{
.tag = .unchecked_block,
.main_token = token,
.data = .{
.lhs = block,
.rhs = undefined,
},
});

try self.scratch.append(self.allocator, unchecked);
}

const statement = try self.expectStatementRecoverable();

if (statement == 0)
Expand Down Expand Up @@ -1499,6 +1514,22 @@ pub fn expectStatement(self: *Parser) ParserErrors!Node.Index {
.keyword_return => return self.expectReturnStatement(),
.keyword_continue => return self.expectContinueStatement(),
.keyword_break => return self.expectBreakStatement(),
.keyword_unchecked => {
const token = self.nextToken();

const block = try self.expectBlock();

const unchecked = try self.addNode(.{
.tag = .unchecked_block,
.main_token = token,
.data = .{
.lhs = block,
.rhs = undefined,
},
});

return unchecked;
},
.keyword_assembly => unreachable, // Not implemented
else => {},
}
Expand Down Expand Up @@ -1606,66 +1637,75 @@ pub fn parseSuffixExpr(self: *Parser) ParserErrors!Node.Index {
continue;
}

const l_paren = self.consumeToken(.l_paren) orelse return res;
const call = try self.parseCallExpression(res);

if (call == 0)
return res;

res = call;
}
}
/// [Grammar](https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.callArgumentList)
pub fn parseCallExpression(self: *Parser, lhs: Node.Index) ParserErrors!Node.Index {
const l_paren = self.consumeToken(.l_paren) orelse return null_node;

const scratch = self.scratch.items.len;
defer self.scratch.shrinkRetainingCapacity(scratch);
const scratch = self.scratch.items.len;
defer self.scratch.shrinkRetainingCapacity(scratch);

while (true) {
if (self.consumeToken(.r_paren)) |_| break;
while (true) {
if (self.consumeToken(.r_paren)) |_| break;

const struct_init = try self.parseCurlySuffixExpr();
const struct_init = try self.parseCurlySuffixExpr();

if (struct_init != 0) {
try self.scratch.append(self.allocator, struct_init);
} else {
const param = try self.expectExpr();
try self.scratch.append(self.allocator, param);
}
if (struct_init != 0) {
try self.scratch.append(self.allocator, struct_init);
} else {
const param = try self.expectExpr();
try self.scratch.append(self.allocator, param);
}

switch (self.token_tags[self.token_index]) {
.comma => self.token_index += 1,
.r_paren => {
self.token_index += 1;
break;
},
.colon, .r_brace, .r_bracket => return self.failMsg(.{
.tag = .expected_token,
.token = self.token_index,
.extra = .{ .expected_tag = .r_paren },
}),
else => try self.warn(.expected_comma_after),
}
switch (self.token_tags[self.token_index]) {
.comma => self.token_index += 1,
.r_paren => {
self.token_index += 1;
break;
},
.colon, .r_brace, .r_bracket => return self.failMsg(.{
.tag = .expected_token,
.token = self.token_index,
.extra = .{ .expected_tag = .r_paren },
}),
else => try self.warn(.expected_comma_after),
}
}

const params = self.scratch.items[scratch..];
const params = self.scratch.items[scratch..];

res = switch (params.len) {
0 => try self.addNode(.{
.tag = .call_one,
.main_token = l_paren,
.data = .{
.lhs = res,
.rhs = 0,
},
}),
1 => try self.addNode(.{
.tag = .call_one,
.main_token = l_paren,
.data = .{
.lhs = res,
.rhs = params[0],
},
}),
else => try self.addNode(.{
.tag = .call,
.main_token = l_paren,
.data = .{
.lhs = res,
.rhs = try self.addExtraData(try self.listToSpan(params)),
},
}),
};
switch (params.len) {
0 => return self.addNode(.{
.tag = .call_one,
.main_token = l_paren,
.data = .{
.lhs = lhs,
.rhs = 0,
},
}),
1 => return self.addNode(.{
.tag = .call_one,
.main_token = l_paren,
.data = .{
.lhs = lhs,
.rhs = params[0],
},
}),
else => return self.addNode(.{
.tag = .call,
.main_token = l_paren,
.data = .{
.lhs = lhs,
.rhs = try self.addExtraData(try self.listToSpan(params)),
},
}),
}
}
/// Suffix
Expand Down Expand Up @@ -1726,6 +1766,7 @@ pub fn parseSuffix(self: *Parser, lhs: Node.Index) ParserErrors!Node.Index {
else => return null_node,
}
}
/// [Grammar](https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.callArgumentList)
pub fn parseCurlySuffixExpr(self: *Parser) ParserErrors!Node.Index {
const l_brace = self.consumeToken(.l_brace) orelse return null_node;

Expand Down Expand Up @@ -2681,6 +2722,7 @@ pub fn parsePragmaVersion(self: *Parser) ParserErrors!TokenIndex {
.angle_bracket_right_equal,
.angle_bracket_left,
.angle_bracket_left_equal,
.caret,
=> {
self.token_index += 1;
_ = try self.expectToken(.number_literal);
Expand Down Expand Up @@ -2903,6 +2945,7 @@ pub fn parseMapping(self: *Parser) ParserErrors!Node.Index {
if (child_one == 0)
return self.fail(.expected_elementary_or_identifier_path);

_ = self.consumeToken(.identifier);
_ = try self.expectToken(.equal_bracket_right);

const child_two = try self.parseTypeExpr();
Expand Down
Loading

0 comments on commit b02f761

Please sign in to comment.