From 5648afd950141a582b4585be8a30b7b3f808e35a Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Sun, 10 May 2026 15:23:52 +0100 Subject: Parse doc comment for struct definitions --- examples/01-struct/src/point.hob | 2 ++ .../zwobble/hobgoblin/compiler/parser/Parser.java | 28 +++++++++++++++++++--- .../parser/ParserStructDefinitionTests.java | 20 ++++++++++++++++ 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/examples/01-struct/src/point.hob b/examples/01-struct/src/point.hob index abe989d..1f392af 100644 --- a/examples/01-struct/src/point.hob +++ b/examples/01-struct/src/point.hob @@ -1,8 +1,10 @@ +/// A straight line from one point to another. struct Line { field start: Point; field end: Point; } +/// A 2D point. struct Point { field x: Int32; field y: Int32; diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java b/src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java index 88b0c5c..49464b6 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java @@ -49,8 +49,10 @@ public class Parser { static UntypedNamespaceStatementNode parseNamespaceStatement( TokenIterator tokens ) { + var docComment = parseDocComment(tokens); + if (tokens.isNext(TokenType.KEYWORD_STRUCT)) { - return parseStructDefinition(tokens); + return parseStructDefinition(tokens, docComment); } else if (tokens.isNext(TokenType.KEYWORD_SUM)) { return parseSumDefinition(tokens); } else { @@ -58,8 +60,28 @@ public class Parser { } } + private static String parseDocComment(TokenIterator tokens) { + var docComment = new StringBuilder(); + + while (tokens.isNext(TokenType.DOC_COMMENT)) { + var docCommentToken = tokens.next(TokenType.DOC_COMMENT); + var docCommentLine = docCommentToken.charSequence(); + + var firstCharIndex = 3; + while (docCommentLine.charAt(firstCharIndex) == ' ') { + firstCharIndex++; + } + + var docCommentContents = docCommentLine.subSequence(firstCharIndex, docCommentLine.length()); + docComment.append(docCommentContents); + } + + return docComment.toString(); + } + private static UntypedStructDefinitionNode parseStructDefinition( - TokenIterator tokens + TokenIterator tokens, + String docComment ) { var start = tokens.startPosition(); @@ -81,7 +103,7 @@ public class Parser { return new UntypedStructDefinitionNode( name.charSequence().toString(), fields, - "", + docComment, source ); } diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/parser/ParserStructDefinitionTests.java b/src/test/java/org/zwobble/hobgoblin/compiler/parser/ParserStructDefinitionTests.java index 9dae394..a0394ce 100644 --- a/src/test/java/org/zwobble/hobgoblin/compiler/parser/ParserStructDefinitionTests.java +++ b/src/test/java/org/zwobble/hobgoblin/compiler/parser/ParserStructDefinitionTests.java @@ -70,4 +70,24 @@ public class ParserStructDefinitionTests { )) )); } + + @Test + public void structWithDocComment() { + var source = """ + /// A 2D point. + /// + /// Positive y is up. + struct Point { + }"""; + + var node = parseString( + source, + Parser::parseNamespaceStatement + ); + + assertThat(node, instanceOf( + UntypedStructDefinitionNode.class, + has("docComment", UntypedStructDefinitionNode::docComment, equalTo("A 2D point.\n\nPositive y is up.\n")) + )); + } } -- cgit v1.2.3