Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement docstrings #267

Merged
merged 14 commits into from
Sep 29, 2021
Merged
26 changes: 14 additions & 12 deletions core_lang/src/hll.pest
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ while_keyword = {"while"}
match_keyword = {"match"}
mut_keyword = {"mut"}
assign = _{"="}
docstring_open = {"///"}
line_comment_open = {"//"}
block_comment_open = {"/*"}
block_comment_close = {"*/"}
Expand Down Expand Up @@ -99,10 +100,10 @@ struct_expr_fields = {struct_field_name ~ ":" ~ expr ~ ("," ~ struct_field_name
array_exp = {"[" ~ (expr ~ ("," ~ expr)*) ~ "]"}

// declarations
declaration = {(enum_decl|var_decl|fn_decl|trait_decl|abi_decl|struct_decl|reassignment|impl_trait|impl_self)}
declaration = {docstring|enum_decl|var_decl|fn_decl|trait_decl|abi_decl|struct_decl|reassignment|impl_trait|impl_self}
var_decl = {var_decl_keyword ~ mut_keyword? ~ var_name ~ type_ascription? ~ assign ~ expr ~ ";"}
type_ascription = {":" ~ type_name}
fn_decl = {visibility ~ fn_signature ~ code_block}
fn_decl = {docstring? ~ visibility ~ fn_signature ~ code_block}
fn_signature = {fn_decl_keyword ~ fn_decl_name ~ type_params? ~ fn_decl_params ~ (fn_returns ~ return_type)? ~ trait_bounds?}
var_name = {ident}
reassignment = {variable_reassignment | struct_field_reassignment}
Expand All @@ -113,11 +114,11 @@ visibility = {"pub"?}

struct_decl = {visibility ~ struct_keyword ~ struct_name ~ type_params? ~ trait_bounds? ~ "{" ~ struct_fields ~ "}"}
struct_name = {ident}
struct_fields = {struct_field_name ~ ":" ~ type_name ~ ("," ~ struct_field_name ~ ":" ~ type_name)* ~ ","?}
struct_fields = {docstring? ~ struct_field_name ~ ":" ~ type_name ~ ("," ~ docstring? ~ struct_field_name ~ ":" ~ type_name)* ~ ","?}
struct_field_name = {ident}
// // enum declaration
enum_decl = {enum_keyword ~ enum_name ~ type_params? ~ trait_bounds? ~ "{" ~ enum_fields ~ "}"}
enum_fields = {enum_field_name ~ ":" ~ type_name ~ ("," ~ enum_field_name ~ ":" ~ type_name)* ~ ","?}
enum_fields = {docstring? ~ enum_field_name ~ ":" ~ type_name ~ ("," ~ docstring? ~ enum_field_name ~ ":" ~ type_name)* ~ ","?}
enum_name = {ident}
enum_field_name = {ident}

Expand Down Expand Up @@ -170,16 +171,17 @@ opcode = {ident}
control_flow = _{while_loop|return_statement}

// boilerplate
WHITESPACE = _{(" "|"\t"|"\r"|"\n")+}
COMMENT = _{block_comment|line_comment}
block_comment = @{block_comment_open ~ (!block_comment_close ~ ANY)* ~ block_comment_close}
line_comment = @{line_comment_open ~ (!("\r"|"\n") ~ ANY)*}
char = @{
WHITESPACE = _{(" "|"\t"|"\r"|"\n")+}
COMMENT = _{block_comment|line_comment}
docstring = @{docstring_open ~ (!("\r"|"\n") ~ ANY)*}
block_comment = @{block_comment_open ~ (!block_comment_close ~ ANY)* ~ block_comment_close}
line_comment = @{line_comment_open ~ (!"/") ~ (!("\r"|"\n") ~ ANY)*}
char = @{
!("\""|"\\") ~ ANY
| "\\" ~ ("\""|"\\"|"/"|"b"|"f"|"n"|"r"|"t")
| "\\" ~ ("u" ~ ASCII_HEX_DIGIT{4})
}
unit = {"(" ~ ")"}
ident = @{ ASCII_ALPHA ~ (ASCII_ALPHANUMERIC|"_")* }
reserved_words = @{(true_keyword|false_keyword|asm_keyword|ref_keyword|deref_keyword|abi_keyword|while_keyword|struct_keyword|enum_keyword|match_keyword|use_keyword|var_decl_keyword|fn_decl_keyword|trait_decl_keyword|return_keyword|include_keyword) ~ !(ASCII_ALPHANUMERIC|"_")}
unit = {"(" ~ ")"}
ident = @{ ASCII_ALPHA ~ (ASCII_ALPHANUMERIC|"_")* }
reserved_words = @{(true_keyword|false_keyword|asm_keyword|ref_keyword|deref_keyword|abi_keyword|while_keyword|struct_keyword|enum_keyword|match_keyword|use_keyword|var_decl_keyword|fn_decl_keyword|trait_decl_keyword|return_keyword|include_keyword) ~ !(ASCII_ALPHANUMERIC|"_")}

58 changes: 44 additions & 14 deletions core_lang/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use semantic_analysis::{TreeType, TypedParseTree};
pub mod types;
pub(crate) mod utils;
pub use crate::parse_tree::{Declaration, Expression, UseStatement, WhileLoop};
use std::collections::HashMap;

pub use crate::span::Span;
pub use error::{CompileError, CompileResult, CompileWarning};
Expand Down Expand Up @@ -118,12 +119,14 @@ pub fn parse<'sc>(
)
}
};
let mut docstrings = HashMap::new();
let res = check!(
parse_root_from_pairs(parsed.next().unwrap().into_inner(), config),
parse_root_from_pairs(parsed.next().unwrap().into_inner(), config, &mut docstrings),
return err(warnings, errors),
warnings,
errors
);
println!("{:#?}", docstrings);
emilyaherbert marked this conversation as resolved.
Show resolved Hide resolved
ok(res, warnings, errors)
}

Expand Down Expand Up @@ -525,6 +528,7 @@ fn perform_control_flow_analysis_on_library_exports<'sc>(
fn parse_root_from_pairs<'sc>(
input: impl Iterator<Item = Pair<'sc, Rule>>,
config: Option<&BuildConfig>,
docstrings: &mut HashMap<String, Vec<String>>,
) -> CompileResult<'sc, HllParseTree<'sc>> {
let path = config.map(|config| config.dir_of_code.clone());
let mut warnings = Vec::new();
Expand All @@ -535,6 +539,7 @@ fn parse_root_from_pairs<'sc>(
predicate_ast: None,
library_exports: vec![],
};
let mut unassigned_docstrings = vec![];
for block in input {
let mut parse_tree = ParseTree::new(span::Span {
span: block.as_span(),
Expand All @@ -546,19 +551,41 @@ fn parse_root_from_pairs<'sc>(
for pair in input {
match pair.as_rule() {
Rule::declaration => {
let decl = check!(
Declaration::parse_from_pair(pair.clone(), config),
continue,
warnings,
errors
);
parse_tree.push(AstNode {
content: AstNodeContent::Declaration(decl),
span: span::Span {
span: pair.as_span(),
path: path.clone(),
},
});
let mut decl = pair.clone().into_inner();
let decl_inner = decl.next().unwrap();
match decl_inner.as_rule() {
Rule::docstring => {
let docstring = decl_inner
.as_str()
.to_string()
.split_off(3)
.as_str()
.trim()
.to_string();
unassigned_docstrings.push(docstring);
}
_ => {
let decl = check!(
Declaration::parse_from_pair(
pair.clone(),
config,
unassigned_docstrings.clone(),
docstrings
),
continue,
warnings,
errors
);
parse_tree.push(AstNode {
content: AstNodeContent::Declaration(decl),
span: span::Span {
span: pair.as_span(),
path: path.clone(),
},
});
unassigned_docstrings.clear();
}
}
}
Rule::use_statement => {
let stmt = check!(
Expand All @@ -574,6 +601,7 @@ fn parse_root_from_pairs<'sc>(
path: path.clone(),
},
});
unassigned_docstrings.clear();
}
Rule::library_name => {
let lib_pair = pair.into_inner().next().unwrap();
Expand All @@ -583,6 +611,7 @@ fn parse_root_from_pairs<'sc>(
warnings,
errors
));
unassigned_docstrings.clear();
}
Rule::include_statement => {
// parse the include statement into a reference to a specific file
Expand All @@ -599,6 +628,7 @@ fn parse_root_from_pairs<'sc>(
path: path.clone(),
},
});
unassigned_docstrings.clear();
}
_ => unreachable!("{:?}", pair.as_str()),
}
Expand Down
96 changes: 70 additions & 26 deletions core_lang/src/parse_tree/code_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ impl<'sc> CodeBlock<'sc> {
pub(crate) fn parse_from_pair(
block: Pair<'sc, Rule>,
config: Option<&BuildConfig>,
docstrings: &mut HashMap<String, Vec<String>>,
) -> CompileResult<'sc, Self> {
let path = config.map(|c| c.path());
let mut warnings = Vec::new();
Expand All @@ -30,80 +31,120 @@ impl<'sc> CodeBlock<'sc> {
path: path.clone(),
};
let block_inner = block.into_inner();
let mut unassigned_docstrings: Vec<String> = vec![];
let mut contents = Vec::new();
for pair in block_inner {
contents.push(match pair.as_rule() {
Rule::declaration => AstNode {
content: AstNodeContent::Declaration(check!(
Declaration::parse_from_pair(pair.clone(), config),
continue,
warnings,
errors
)),
span: span::Span {
span: pair.as_span(),
path: path.clone(),
},
},
let content = match pair.as_rule() {
Rule::declaration => {
let mut decl = pair.clone().into_inner();
let decl_inner = decl.next().unwrap();
match decl_inner.as_rule() {
Rule::docstring => {
let mut parts = decl_inner.clone().into_inner();
let docstring = parts
.next()
.unwrap()
.as_str()
.trim()
.to_string()
.split_off(3)
.as_str()
.trim()
.to_string();
unassigned_docstrings.push(docstring);
None
}
_ => {
let decl_stmt = AstNode {
content: AstNodeContent::Declaration(check!(
Declaration::parse_from_pair(
pair.clone(),
config,
unassigned_docstrings.clone(),
docstrings
),
continue,
warnings,
errors
)),
span: span::Span {
span: pair.as_span(),
path: path.clone(),
},
};
unassigned_docstrings.clear();
Some(decl_stmt)
}
}
}
Rule::expr_statement => {
let evaluated_node = check!(
Expression::parse_from_pair(
pair.clone().into_inner().next().unwrap().clone(),
config
config,
docstrings
),
continue,
warnings,
errors
);
AstNode {
let expr_stmt = AstNode {
content: AstNodeContent::Expression(evaluated_node),
span: span::Span {
span: pair.as_span(),
path: path.clone(),
},
}
};
unassigned_docstrings.clear();
Some(expr_stmt)
}
Rule::return_statement => {
let evaluated_node = check!(
ReturnStatement::parse_from_pair(pair.clone(), config),
ReturnStatement::parse_from_pair(pair.clone(), config, docstrings),
continue,
warnings,
errors
);
AstNode {
let return_stmt = AstNode {
content: AstNodeContent::ReturnStatement(evaluated_node),
span: span::Span {
span: pair.as_span(),
path: path.clone(),
},
}
};
unassigned_docstrings.clear();
Some(return_stmt)
}
Rule::expr => {
let res = check!(
Expression::parse_from_pair(pair.clone(), config),
Expression::parse_from_pair(pair.clone(), config, docstrings),
continue,
warnings,
errors
);
AstNode {
let expr = AstNode {
content: AstNodeContent::ImplicitReturnExpression(res.clone()),
span: res.span(),
}
};
unassigned_docstrings.clear();
Some(expr)
}
Rule::while_loop => {
let res = check!(
WhileLoop::parse_from_pair(pair.clone(), config),
WhileLoop::parse_from_pair(pair.clone(), config, docstrings),
continue,
warnings,
errors
);
AstNode {
let while_stmt = AstNode {
content: AstNodeContent::WhileLoop(res),
span: span::Span {
span: pair.as_span(),
path: path.clone(),
},
}
};
unassigned_docstrings.clear();
Some(while_stmt)
}
a => {
println!("In code block parsing: {:?} {:?}", a, pair.as_str());
Expand All @@ -116,7 +157,10 @@ impl<'sc> CodeBlock<'sc> {
));
continue;
}
})
};
if let Some(content) = content {
contents.push(content);
}
}

ok(
Expand Down
4 changes: 3 additions & 1 deletion core_lang/src/parse_tree/declaration/abi_declaration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::parser::Rule;
use crate::span::Span;
use crate::{error::*, Ident};
use pest::iterators::Pair;
use std::collections::HashMap;

/// An `abi` declaration, which declares an interface for a contract
/// to implement or for a caller to use to call a contract.
Expand All @@ -23,6 +24,7 @@ impl<'sc> AbiDeclaration<'sc> {
pub(crate) fn parse_from_pair(
pair: Pair<'sc, Rule>,
config: Option<&BuildConfig>,
docstrings: &mut HashMap<String, Vec<String>>,
) -> CompileResult<'sc, Self> {
let span = Span {
span: pair.as_span(),
Expand Down Expand Up @@ -50,7 +52,7 @@ impl<'sc> AbiDeclaration<'sc> {
errors
)),
Rule::fn_decl => methods.push(check!(
FunctionDeclaration::parse_from_pair(func, config),
FunctionDeclaration::parse_from_pair(func, config, docstrings),
continue,
warnings,
errors
Expand Down
Loading