Compare commits

...

6 Commits

Author SHA1 Message Date
Tristan B. Velloza Kildaire 13334f22e3 Test cases
- Updated `simple_comments.t`
2024-04-16 21:22:28 +02:00
Tristan B. Velloza Kildaire cc87c8048c Comments
- Don't recognise an `@return` with an empty description
2024-04-16 21:22:17 +02:00
Tristan B. Velloza Kildaire 0b927e93e4 Test cases
- Updated `simple_comments.t`
2024-04-16 20:49:09 +02:00
Tristan B. Velloza Kildaire 87ddafe304 Comments
- Implemented parsing for the `@return`
2024-04-16 20:48:58 +02:00
Tristan B. Velloza Kildaire ad67ce6309 Parser
- Use the new `Comment` API
2024-04-16 20:11:59 +02:00
Tristan B. Velloza Kildaire 0f5ba970af Comments
- Added comment parsing
2024-04-16 20:11:55 +02:00
3 changed files with 403 additions and 12 deletions

View File

@ -445,6 +445,23 @@ public final class Parser
{
Statement ret;
/* If there are any comments available then pop them off now */
// TODO: Check if we should pop anything off of the comment
// stack here
Comment potComment;
if(hasCommentsOnStack())
{
potComment = popComment();
}
scope(exit)
{
if(potComment)
{
ret.setComment(potComment);
}
}
/* Save the name or type */
string nameTYpe = lexer.getCurrentToken().getToken();
DEBUG("parseName(): Current token: "~lexer.getCurrentToken().toString());
@ -2181,7 +2198,8 @@ public final class Parser
}
import std.container.slist : SList;
private SList!(Token) commentStack;
import tlang.compiler.symbols.comments;
private SList!(Comment) commentStack;
private void pushComment(Token commentToken)
{
// Sanity check
@ -2190,7 +2208,7 @@ public final class Parser
);
// Push it onto top of stack
commentStack.insertFront(commentToken);
commentStack.insertFront(Comment.fromToken(commentToken));
}
//TODO: Add a popToken() (also think if we want a stack-based mechanism)
private bool hasCommentsOnStack()
@ -2204,6 +2222,13 @@ public final class Parser
return walkLength(commentStack[]);
}
private Comment popComment()
{
Comment popped = commentStack.front();
commentStack.removeFront();
return popped;
}
private void parseComment()
{
WARN("parseComment(): Enter");
@ -2396,6 +2421,14 @@ public final class Parser
expect("parseStatement(): Unknown symbol: " ~ lexer.getCurrentToken().getToken());
}
// // TODO: Check if we should pop anything off of the comment
// // stack here
// if(hasCommentsOnStack())
// {
// statement.setComment(popComment());
// }
WARN("parseStatement(): Leave");
return statement;

View File

@ -5,6 +5,78 @@ module tlang.compiler.symbols.comments;
import std.string : startsWith, split, strip, stripLeft;
import std.array : join;
import tlang.misc.logging;
import std.string : format;
public enum DocType
{
PARAM,
THROWS,
RETURNS
}
public struct ParamDoc
{
string param;
string description;
}
public struct ReturnsDoc
{
string description;
public string getDescription()
{
return this.description;
}
}
public struct ExceptionDoc
{
string description;
}
private union DocContent
{
ParamDoc param;
ReturnsDoc returns;
ExceptionDoc exception;
}
public struct DocStr
{
private DocType type;
private DocContent content;
public enum DocType getType()
{
return this.type;
}
public static DocStr param(string name, string description)
{
DocStr dstr;
dstr.type = DocType.PARAM;
dstr.content.param = ParamDoc(name, description);
return dstr;
}
public ExceptionDoc getExceptionDoc()
{
assert(this.type == DocType.THROWS);
return content.exception;
}
}
private struct CommentParts
{
string bdy;
DocStr[] strs;
}
private class CommentParser
{
private string source;
@ -15,8 +87,10 @@ private class CommentParser
private string commentPart;
private string extract()
private CommentParts extract()
{
CommentParts parts;
string buildUp;
if(this.source.startsWith("/**"))
@ -65,9 +139,231 @@ private class CommentParser
// Now put it all together in a new-line seperate string
buildUp = join(lines, "\n");
// Set the body parts
parts.bdy = join(stripOutDocLines(lines));
// TODO: DO @param stuff here
DocStr[] docStrs;
foreach(string line; onlyParams(lines))
{
DocStr ds;
if(extractDocLine(line, ds))
{
docStrs ~= ds;
DEBUG(format("Converted docline '%s' to: %s", line, ds));
}
}
parts.strs = docStrs;
}
return buildUp;
return parts;
}
private bool extractDocLine(string line, ref DocStr ds)
{
string buildUp;
bool foundType = false;
ulong i = 0;
bool getch(ref char c)
{
if(i < line.length)
{
c = line[i];
return true;
}
return false;
}
void prog()
{
i++;
}
char c;
bool parseParam(ref string paramName, ref string paramDescription)
{
bool gotParamName = false;
string foundParamName;
bool gotParamDescription = false;
string foundParamDescription;
while(getch(c))
{
if(c == ' ')
{
prog;
continue;
}
else if(!gotParamName)
{
while(getch(c) && c != ' ')
{
foundParamName ~= c;
prog;
}
// TODO: Validate name?
gotParamName = true;
}
else
{
while(getch(c))
{
foundParamDescription ~= c;
prog;
}
gotParamDescription = true;
}
}
if(gotParamName && gotParamDescription)
{
paramName = foundParamName;
paramDescription = foundParamDescription;
return true;
}
else
{
return false;
}
}
bool parseReturn(ref string returnDescription)
{
string gotDescription;
bool foundDescription;
while(getch(c))
{
if(c == ' ' && !foundDescription)
{
prog;
continue;
}
gotDescription ~= c;
prog;
foundDescription = true;
}
if(foundDescription)
{
returnDescription = gotDescription;
return true;
}
else
{
return false;
}
}
while(getch(c))
{
if(c == ' ')
{
prog();
continue;
}
else if(c == '@' && !foundType)
{
string paramType;
prog();
while(getch(c) && c != ' ')
{
paramType ~= c;
prog();
}
// @param
if(paramType == "param")
{
string paramName, paramDescr;
if(parseParam(paramName, paramDescr))
{
DocStr tmp;
tmp.type = DocType.PARAM;
tmp.content.param = ParamDoc(paramName, paramDescr);
ds = tmp;
return true;
}
else
{
return false;
}
}
// @return
else if (paramType == "return")
{
string returnDescr;
if(parseReturn(returnDescr))
{
DEBUG("hool");
DocStr tmp;
tmp.type = DocType.RETURNS;
tmp.content.returns = ReturnsDoc(returnDescr);
ds = tmp;
return true;
}
else
{
return false;
}
}
// Unknown @<thing>
else
{
return false;
}
}
else
{
return false;
}
}
return false;
}
// TODO: Use niknaks filter
private string[] onlyParams(string[] input)
{
string[] withDoc;
foreach(string i; input)
{
if(stripLeft(i).startsWith("@"))
{
withDoc ~= i;
}
}
return withDoc;
}
// TODO: Use niknaks filter
private string[] stripOutDocLines(string[] input)
{
string[] withoutDoc;
foreach(string i; input)
{
if(!stripLeft(i).startsWith("@"))
{
withoutDoc ~= i;
}
}
return withoutDoc;
}
}
@ -86,14 +382,16 @@ unittest
* there
*/`;
CommentParser parser = new CommentParser(source);
string comment = parser.extract();
CommentParts comment = parser.extract();
writeln(format("Comment: '%s'", comment));
// *cast(int*)0 = 1;
assert(" Hello\n there" == comment);
assert(" Hello\n there" == comment.bdy);
}
import tlang.compiler.lexer.core.tokens : Token;
/**
* Represents a comment
* which can be attached
@ -101,16 +399,65 @@ unittest
*/
public final class Comment
{
private string content;
private CommentParts content;
this(string content)
private this(CommentParts content)
{
// TODO: Parse the comment into text but annotated section
this.content = content;
}
public static Comment fromToken(Token commentToken)
{
return fromText(commentToken.getToken());
}
private static Comment fromText(string text)
{
// TODO: Inline this behavior here
CommentParser parser = new CommentParser(text);
return new Comment(parser.extract());
}
public string getContent()
{
return this.content;
return this.content.bdy;
}
public DocStr[] getDocStrings()
{
return this.content.strs;
}
public ParamDoc[string] getAllParamDocs()
{
// TODO: Use niknaks
ParamDoc[string] d;
foreach(DocStr i; getDocStrings())
{
if(i.type == DocType.PARAM)
{
ParamDoc pDoc = i.content.param;
d[pDoc.param] = pDoc;
}
}
return d;
}
public bool getReturnDoc(ref ReturnsDoc retDoc)
{
// TODO: Use niknaks flter
foreach(DocStr d; getDocStrings())
{
if(d.type == DocType.RETURNS)
{
retDoc = d.content.returns;
return true;
}
}
return false;
}
}

View File

@ -1,13 +1,24 @@
module simple_comments;
int i;
int p;
/**
* Other comment
*/
/**
* Returns 0
* Takes two inputs, does nothing with
them and then returns 0 nonetheless
*
* @param x This is the first input
*@param y This is the second input
* @param niks this r e a l l y doesn't do anything
* @return Just the value 0
*/
int zero()
int zero(int x, int y)
{
return 0;
}
@ -19,6 +30,6 @@ int zero()
int main()
{
int k = zero();
*(cast(int*)0) = zero();
*(cast(int*)0) = zero(0);
return 0;
}