Crates.io | linera-alloy-syn-solidity |
lib.rs | linera-alloy-syn-solidity |
version | 0.7.4 |
source | src |
created_at | 2024-05-30 20:02:32.023106 |
updated_at | 2024-05-30 20:02:32.023106 |
description | syn-powered Solidity parser |
homepage | https://github.com/MathieuDutSik/ethreum_core/tree/main/crates/linera-alloy-syn-solidity |
repository | https://github.com/MathieuDutSik/ethreum_core |
max_upload_size | |
id | 1257226 |
size | 311,529 |
syn
-powered parser for Solidity-like TokenStream
s.
The parsed root element is the [File
], which contains a list of [Item
]s.
[Item
]s also support outer attributes, as shown below.
⚠️ Work in progress ⚠️
This parser is specifically designed for Rust procedural macros. It aims to
mimic the behavior of the official Solidity compiler (Solc) when it comes to
parsing valid Solidity code. This means that all valid Solidity code, as
recognized by Solc v0.5.*1 and above, will also be recognized and parsed
correctly by linera-alloy-syn-solidity
.
However, linera-alloy-syn-solidity
is more permissive and lenient compared to the official
Solidity compiler and grammar specifications. Some examples of code patterns
that are valid in linera-alloy-syn-solidity
but not in the official compiler include:
syn::Ident
), and as such cannot contain
the dollar sign ($
), but can contain unicode characters,
) in function arguments or enums
definitionsinternal
functions or functions with implementations ({ ... }
) in interfacesuint256[] memory
in
a struct or error definition(T, U, ..)
is allowed wherever a type is expected, and can
optionally be preceded by the tuple
keyword.
This is the same as ethers.js
's Human-Readable ABIThis lenient behavior is intentionally designed to facilitate usage within procedural macros, and to reduce general code complexity in the parser and AST.
This parser is limited to only valid Rust tokens, meaning that certain Solidity constructs are not supported. Some examples include, but are not limited to:
$
) inside of identifiershex
and unicode
string literal prefixes.
Literal prefixes are reserved in Rust edition 2021 and above."\uXXXX"
unicode escapes. Rust uses "\u{XXXX}"
for unicode codepoints/*/*/
does not parse.For the most part, you can copy-paste Solidity code and expect it to parse correctly most of the time. You can see a few examples of Solidity code that parses correctly (after some very light patching) in the tests directory.
Basic usage:
use quote::quote;
use linera_alloy_syn_solidity::{Expr, File, Item, Lit, Stmt};
// Create a Solidity `TokenStream`
let tokens = quote! {
/// @name HelloWorld
/// @notice A hello world example in Solidity.
contract HelloWorld {
/// @notice Returns the string "Hello, World!".
function helloWorld() external pure returns (string memory) {
return "Hello, World!";
}
}
};
// Parse the tokens into a `File`
let ast: File = linera_alloy_syn_solidity::parse2(tokens)?;
let items: &[Item] = &ast.items;
let Some(Item::Contract(contract)) = items.first() else {
unreachable!()
};
assert_eq!(contract.name, "HelloWorld");
assert_eq!(contract.attrs.len(), 2); // doc comments
let body: &[Item] = &contract.body;
let Some(Item::Function(function)) = body.first() else {
unreachable!()
};
assert_eq!(function.attrs.len(), 1); // doc comment
assert_eq!(function.name.as_ref().unwrap(), "helloWorld");
assert!(function.parameters.is_empty()); // ()
assert_eq!(function.attributes.len(), 2); // external pure
assert!(function.returns.is_some());
let Some([Stmt::Return(ret)]) = function.body() else {
unreachable!()
};
let Some(Expr::Lit(Lit::Str(s))) = &ret.expr else {
unreachable!()
};
assert_eq!(s.value(), "Hello, World!");
# syn::Result::Ok(())
Older versions may still parse successfully, but this is not guaranteed. ↩