Skip to content

Commit

Permalink
fix parsing of docstrings and annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
timbod7 committed Aug 15, 2022
1 parent 9acb077 commit e29d2e0
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 41 deletions.
18 changes: 13 additions & 5 deletions rust/compiler/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,12 @@ where
}

pub fn docstring(i: Input) -> Res<Input, &str> {
let (i,_) = preceded(whitespace, tag("///"))(i)?;
let (i,_) = ws( tag("///"))(i)?;
let (i,text) = i.split_at_position_complete(|item| {
let c = item.as_char();
c == '\r' || c == '\n'
})?;
let (i,_) = i.take_split(1); // drop newline
Ok((i,&text))
}

Expand Down Expand Up @@ -209,7 +210,7 @@ pub fn scoped_name(i: Input) -> Res<Input,adlast::ScopedName> {
}

pub fn module(i: Input) -> Res<Input,(adlast::Module<TypeExpr0>, Vec<ExplicitAnnotation>)> {

let (i,annotations) = many0(prefix_annotation)(i)?;
let (i,_) = ws(tag("module"))(i)?;
let (i,name) = ws( spanned(module_name))(i)?;
let (i,(imports,decls_or_annotations)) = delimited(
Expand Down Expand Up @@ -237,7 +238,7 @@ pub fn module(i: Input) -> Res<Input,(adlast::Module<TypeExpr0>, Vec<ExplicitAnn
name,
imports,
decls,
Map::new(Vec::new()),
merge_annotations(annotations)
);

Ok( (i,(module, explicit_annotations)) )
Expand Down Expand Up @@ -293,11 +294,18 @@ pub fn decl(i: Input) -> Res<Input,adlast::Decl<TypeExpr0>> {

pub fn prefix_annotation(i: Input) -> Res<Input, (adlast::ScopedName, serde_json::Value)> {
alt((
preceded(wtag("@"), pair(scoped_name, json)),
prefix_annotation_,
map(docstring, |s| (docstring_scoped_name(), serde_json::Value::from(s))),
))(i)
}

pub fn prefix_annotation_(i: Input) -> Res<Input, (adlast::ScopedName, serde_json::Value)> {
let (i,_) = wtag("@")(i)?;
let (i,sn) = scoped_name(i)?;
let (i,ojv) = opt(json)(i)?;
Ok((i,(sn, ojv.unwrap_or(serde_json::Value::Null))))
}

pub fn merge_annotations(anns: Vec<(adlast::ScopedName, serde_json::Value)>) -> adlast::Annotations {
// Create a map out of the annotations, but join any doc strings as separate lines
let mut hm = HashMap::new();
Expand Down Expand Up @@ -478,7 +486,7 @@ pub fn explicit_decl_annotation(i: Input) -> Res<Input, ExplicitAnnotation> {

pub fn explicit_field_annotation(i: Input) -> Res<Input, ExplicitAnnotation> {
let (i,decl_name) = ws(ident0)(i)?;
let (i,_) = wtag(".")(i)?;
let (i,_) = wtag("::")(i)?;
let (i,field_name) = ws(ident0)(i)?;
let (i,scoped_name) = ws(scoped_name)(i)?;
let (i,value) = json(i)?;
Expand Down
95 changes: 59 additions & 36 deletions rust/compiler/src/parser/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ fn parse_decl_annotations() {

assert_parse_eq(
decl(inp("@X.Z true @Y \"xyzzy\" struct A {}")),
adlast::Decl{
adlast::Decl{
name: adlast::Spanned::new("A".to_string(), adlast::Span::new(28, 29)),
version: Maybe::nothing(),
annotations: Map::from_iter(vec![
Expand Down Expand Up @@ -178,7 +178,7 @@ fn parse_explicit_annotations() {
);

assert_parse_eq(
explicit_annotation(inp("annotation MyStruct.f1 Bool false")),
explicit_annotation(inp("annotation MyStruct::f1 Bool false")),
ExplicitAnnotation{
refr: ExplicitAnnotationRef::Field(("MyStruct".to_owned(), "f1".to_owned())),
scoped_name: mk_scoped_name("", "Bool"),
Expand All @@ -187,40 +187,40 @@ fn parse_explicit_annotations() {
);
}

// #[test]
// fn parse_docstring() {
// assert_eq!(docstring(" /// my doc string\n"), Ok(("\n", " my doc string")));

// assert_eq!(
// decl("/// Some doc\n struct A {}"),
// Ok(("", adlast::Decl{
// name: "A".to_string(),
// version: Maybe::nothing(),
// annotations: Map::from_iter(vec![
// (docstring_scoped_name(), serde_json::Value::from(" Some doc")),
// ]),
// r#type: adlast::DeclType::Struct(adlast::Struct{
// type_params: Vec::new(),
// fields: vec![],
// }),
// })),
// );

// assert_eq!(
// decl("/// Some doc\n /// with line 2\n struct A {}"),
// Ok(("", adlast::Decl{
// name: "A".to_string(),
// version: Maybe::nothing(),
// annotations: Map::from_iter(vec![
// (mk_scoped_name("sys.annotations", "Doc"), serde_json::Value::from(" Some doc\n with line 2")),
// ]),
// r#type: adlast::DeclType::Struct(adlast::Struct{
// type_params: Vec::new(),
// fields: vec![],
// }),
// })),
// );
// }
#[test]
fn parse_docstring() {
assert_parse_eq(docstring(inp(" /// my doc string\n")), " my doc string");

assert_parse_eq(
decl(inp("/// Some doc\n struct A {}")),
adlast::Decl{
name: adlast::Spanned::new("A".to_string(), adlast::Span::new(21, 22)),
version: Maybe::nothing(),
annotations: Map::from_iter(vec![
(docstring_scoped_name(), serde_json::Value::from(" Some doc")),
]),
r#type: adlast::DeclType::Struct(adlast::Struct{
type_params: Vec::new(),
fields: vec![],
}),
},
);

assert_parse_eq(
decl(inp("/// Some doc\n /// with line 2\n struct A {}")),
adlast::Decl{
name: adlast::Spanned::new("A".to_string(), adlast::Span::new(38, 39)),
version: Maybe::nothing(),
annotations: Map::from_iter(vec![
(mk_scoped_name("sys.annotations", "Doc"), serde_json::Value::from(" Some doc\n with line 2")),
]),
r#type: adlast::DeclType::Struct(adlast::Struct{
type_params: Vec::new(),
fields: vec![],
}),
},
);
}

#[test]
fn parse_empty_module() {
Expand Down Expand Up @@ -278,6 +278,29 @@ fn parse_json() {
assert_module_file_ok("../../haskell/compiler/tests/test8/input/test.adl");
assert_module_file_ok("../../haskell/compiler/tests/test9/input/test.adl");
assert_module_file_ok("../../haskell/compiler/tests/test10/input/test.adl");
assert_module_file_ok("../../haskell/compiler/tests/test11/input/test.adl");
assert_module_file_ok("../../haskell/compiler/tests/test12/input/test.adl");
assert_module_file_ok("../../haskell/compiler/tests/test13/input/test.adl");
assert_module_file_ok("../../haskell/compiler/tests/test14/input/test.adl");
assert_module_file_ok("../../haskell/compiler/tests/test15/input/test.adl");
assert_module_file_ok("../../haskell/compiler/tests/test16/input/test.adl");
assert_module_file_ok("../../haskell/compiler/tests/test16/input/test.adl");
assert_module_file_ok("../../haskell/compiler/tests/test16/input/test2.adl");
assert_module_file_ok("../../haskell/compiler/tests/test17/input/test.adl");
assert_module_file_ok("../../haskell/compiler/tests/test18/input/test.adl");
assert_module_file_ok("../../haskell/compiler/tests/test19/input/test.adl");
assert_module_file_ok("../../haskell/compiler/tests/test20/input/test.adl");
assert_module_file_ok("../../haskell/compiler/tests/test21/input/test.adl");
assert_module_file_ok("../../haskell/compiler/tests/test22/input/test22a.adl");
assert_module_file_ok("../../haskell/compiler/tests/test22/input/test22b.adl");
assert_module_file_ok("../../haskell/compiler/tests/test23/input/test23.adl");
assert_module_file_ok("../../haskell/compiler/tests/test24/input/test24.adl");
assert_module_file_ok("../../haskell/compiler/tests/test25/input/admin.adl");
assert_module_file_ok("../../haskell/compiler/tests/test26/input/test26.adl");
assert_module_file_ok("../../haskell/compiler/tests/test27/input/test27.adl");
assert_module_file_ok("../../haskell/compiler/tests/test27/input/test27a.adl");
assert_module_file_ok("../../haskell/compiler/tests/test28/input/test28.adl");
assert_module_file_ok("../../haskell/compiler/tests/test29/input/test29.adl");
}

fn inp (s: &str) -> Input {
Expand Down

0 comments on commit e29d2e0

Please sign in to comment.