|
|
|
@ -12,6 +12,7 @@ import tlang.compiler.parsing.exceptions;
|
|
|
|
|
import tlang.compiler.core : Compiler;
|
|
|
|
|
import std.string : format;
|
|
|
|
|
import tlang.compiler.modman;
|
|
|
|
|
import tlang.compiler.symbols.comments;
|
|
|
|
|
|
|
|
|
|
// TODO: Technically we could make a core parser etc
|
|
|
|
|
public final class Parser
|
|
|
|
@ -21,6 +22,14 @@ public final class Parser
|
|
|
|
|
*/
|
|
|
|
|
private LexerInterface lexer;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Stores the previous token
|
|
|
|
|
*
|
|
|
|
|
* This is updated everytime
|
|
|
|
|
* `nextToken()` is called
|
|
|
|
|
*/
|
|
|
|
|
private Token prevToken;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The associated compiler
|
|
|
|
|
*/
|
|
|
|
@ -130,6 +139,65 @@ public final class Parser
|
|
|
|
|
return findOfType(statementType, from).length != 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the current token
|
|
|
|
|
*
|
|
|
|
|
* This is a simple proxy method
|
|
|
|
|
*
|
|
|
|
|
* Returns: the `Token`
|
|
|
|
|
*/
|
|
|
|
|
private Token getCurrentToken()
|
|
|
|
|
{
|
|
|
|
|
return this.lexer.getCurrentToken();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Moves the token pointer back
|
|
|
|
|
*
|
|
|
|
|
* This is a simple proxy method
|
|
|
|
|
*/
|
|
|
|
|
private void previousToken()
|
|
|
|
|
{
|
|
|
|
|
this.lexer.previousToken();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Moves the token pointer forwards
|
|
|
|
|
*
|
|
|
|
|
* This is a proxy method BUT prior
|
|
|
|
|
* to doing the proxy call it first
|
|
|
|
|
* saves the current token into `prevToken`
|
|
|
|
|
*/
|
|
|
|
|
private void nextToken()
|
|
|
|
|
{
|
|
|
|
|
// Save current token as previous token
|
|
|
|
|
this.prevToken = this.getCurrentToken();
|
|
|
|
|
|
|
|
|
|
// Move onto next token
|
|
|
|
|
this.lexer.nextToken();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool getAssociatedComment(ref Comment comment)
|
|
|
|
|
{
|
|
|
|
|
// TODO: null check? on this.prevToken
|
|
|
|
|
|
|
|
|
|
// If the previous token was a comment
|
|
|
|
|
if
|
|
|
|
|
(
|
|
|
|
|
getSymbolType(this.prevToken) == SymbolType.SINGLE_LINE_COMMENT ||
|
|
|
|
|
getSymbolType(this.prevToken) == SymbolType.MULTI_LINE_COMMENT
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
DEBUG(format("Parsing a comment from token: '%s'", this.prevToken));
|
|
|
|
|
comment = Comment.fromToken(this.prevToken);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Parses if statements
|
|
|
|
|
*
|
|
|
|
@ -152,24 +220,24 @@ public final class Parser
|
|
|
|
|
if (getSymbolType(lexer.getCurrentToken()) == SymbolType.IF)
|
|
|
|
|
{
|
|
|
|
|
/* Pop off the `if` */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Expect an opening brace `(` */
|
|
|
|
|
expect(SymbolType.LBRACE, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Parse an expression (for the condition) */
|
|
|
|
|
currentBranchCondition = parseExpression();
|
|
|
|
|
expect(SymbolType.RBRACE, lexer.getCurrentToken());
|
|
|
|
|
|
|
|
|
|
/* Opening { */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
expect(SymbolType.OCURLY, lexer.getCurrentToken());
|
|
|
|
|
|
|
|
|
|
/* Parse the if' statement's body AND expect a closing curly */
|
|
|
|
|
currentBranchBody = parseBody();
|
|
|
|
|
expect(SymbolType.CCURLY, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Create a branch node */
|
|
|
|
|
Branch branch = new Branch(currentBranchCondition, currentBranchBody);
|
|
|
|
@ -180,30 +248,30 @@ public final class Parser
|
|
|
|
|
else if (getSymbolType(lexer.getCurrentToken()) == SymbolType.ELSE)
|
|
|
|
|
{
|
|
|
|
|
/* Pop off the `else` */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Check if we have an `if` after the `{` (so an "else if" statement) */
|
|
|
|
|
if (getSymbolType(lexer.getCurrentToken()) == SymbolType.IF)
|
|
|
|
|
{
|
|
|
|
|
/* Pop off the `if` */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Expect an opening brace `(` */
|
|
|
|
|
expect(SymbolType.LBRACE, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Parse an expression (for the condition) */
|
|
|
|
|
currentBranchCondition = parseExpression();
|
|
|
|
|
expect(SymbolType.RBRACE, lexer.getCurrentToken());
|
|
|
|
|
|
|
|
|
|
/* Opening { */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
expect(SymbolType.OCURLY, lexer.getCurrentToken());
|
|
|
|
|
|
|
|
|
|
/* Parse the if' statement's body AND expect a closing curly */
|
|
|
|
|
currentBranchBody = parseBody();
|
|
|
|
|
expect(SymbolType.CCURLY, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Create a branch node */
|
|
|
|
|
Branch branch = new Branch(currentBranchCondition, currentBranchBody);
|
|
|
|
@ -216,7 +284,7 @@ public final class Parser
|
|
|
|
|
/* Parse the if' statement's body (starting with `{` AND expect a closing curly */
|
|
|
|
|
currentBranchBody = parseBody();
|
|
|
|
|
expect(SymbolType.CCURLY, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Create a branch node */
|
|
|
|
|
Branch branch = new Branch(null, currentBranchBody);
|
|
|
|
@ -258,24 +326,24 @@ public final class Parser
|
|
|
|
|
Statement[] branchBody;
|
|
|
|
|
|
|
|
|
|
/* Pop off the `while` */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Expect an opening brace `(` */
|
|
|
|
|
expect(SymbolType.LBRACE, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Parse an expression (for the condition) */
|
|
|
|
|
branchCondition = parseExpression();
|
|
|
|
|
expect(SymbolType.RBRACE, lexer.getCurrentToken());
|
|
|
|
|
|
|
|
|
|
/* Opening { */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
expect(SymbolType.OCURLY, lexer.getCurrentToken());
|
|
|
|
|
|
|
|
|
|
/* Parse the while' statement's body AND expect a closing curly */
|
|
|
|
|
branchBody = parseBody();
|
|
|
|
|
expect(SymbolType.CCURLY, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Create a Branch node coupling the condition and body statements */
|
|
|
|
@ -303,7 +371,7 @@ public final class Parser
|
|
|
|
|
Statement[] branchBody;
|
|
|
|
|
|
|
|
|
|
/* Pop off the `do` */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Expect an opening curly `{` */
|
|
|
|
|
expect(SymbolType.OCURLY, lexer.getCurrentToken());
|
|
|
|
@ -311,24 +379,24 @@ public final class Parser
|
|
|
|
|
/* Parse the do-while statement's body AND expect a closing curly */
|
|
|
|
|
branchBody = parseBody();
|
|
|
|
|
expect(SymbolType.CCURLY, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Expect a `while` */
|
|
|
|
|
expect(SymbolType.WHILE, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Expect an opening brace `(` */
|
|
|
|
|
expect(SymbolType.LBRACE, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Parse the condition */
|
|
|
|
|
branchCondition = parseExpression();
|
|
|
|
|
expect(SymbolType.RBRACE, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Expect a semicolon */
|
|
|
|
|
expect(SymbolType.SEMICOLON, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Create a Branch node coupling the condition and body statements */
|
|
|
|
|
Branch branch = new Branch(branchCondition, branchBody);
|
|
|
|
@ -358,11 +426,11 @@ public final class Parser
|
|
|
|
|
Statement[] branchBody;
|
|
|
|
|
|
|
|
|
|
/* Pop of the token `for` */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Expect an opening smooth brace `(` */
|
|
|
|
|
expect(SymbolType.LBRACE, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Expect a single Statement */
|
|
|
|
|
// TODO: Make optional, add parser lookahead check
|
|
|
|
@ -374,7 +442,7 @@ public final class Parser
|
|
|
|
|
|
|
|
|
|
/* Expect a semi-colon, then move on */
|
|
|
|
|
expect(SymbolType.SEMICOLON, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Expect a post-iteration statement with `)` as terminator */
|
|
|
|
|
// TODO: Make optional, add parser lookahead check
|
|
|
|
@ -386,7 +454,7 @@ public final class Parser
|
|
|
|
|
|
|
|
|
|
/* Expect a closing curly and move on */
|
|
|
|
|
expect(SymbolType.CCURLY, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
DEBUG("Yo: "~lexer.getCurrentToken().toString());
|
|
|
|
|
|
|
|
|
@ -419,8 +487,8 @@ public final class Parser
|
|
|
|
|
|
|
|
|
|
/* The identifier being assigned to */
|
|
|
|
|
string identifier = lexer.getCurrentToken().getToken();
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
DEBUG(lexer.getCurrentToken());
|
|
|
|
|
|
|
|
|
|
/* Expression */
|
|
|
|
@ -435,7 +503,7 @@ public final class Parser
|
|
|
|
|
expect(terminatingSymbol, lexer.getCurrentToken());
|
|
|
|
|
|
|
|
|
|
/* Move off terminating symbol */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return assignment;
|
|
|
|
@ -449,9 +517,9 @@ public final class Parser
|
|
|
|
|
// TODO: Check if we should pop anything off of the comment
|
|
|
|
|
// stack here
|
|
|
|
|
Comment potComment;
|
|
|
|
|
if(hasCommentsOnStack())
|
|
|
|
|
if(getAssociatedComment(potComment))
|
|
|
|
|
{
|
|
|
|
|
potComment = popComment();
|
|
|
|
|
DEBUG(format("Found associated comment: %s", potComment));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
scope(exit)
|
|
|
|
@ -469,7 +537,7 @@ public final class Parser
|
|
|
|
|
/* TODO: The problem here is I don't want to progress the token */
|
|
|
|
|
|
|
|
|
|
/* Get next token */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
SymbolType type = getSymbolType(lexer.getCurrentToken());
|
|
|
|
|
|
|
|
|
|
/* If we have `(` then function call */
|
|
|
|
@ -484,7 +552,7 @@ public final class Parser
|
|
|
|
|
|
|
|
|
|
/* Expect a semi-colon */
|
|
|
|
|
expect(SymbolType.SEMICOLON, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* Either we have:
|
|
|
|
@ -509,14 +577,14 @@ public final class Parser
|
|
|
|
|
{
|
|
|
|
|
/* Expect a semicolon and consume it */
|
|
|
|
|
expect(SymbolType.SEMICOLON, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
}
|
|
|
|
|
/* If it is an arrau assignment */
|
|
|
|
|
else if(cast(ArrayAssignment)ret)
|
|
|
|
|
{
|
|
|
|
|
/* Expect a semicolon and consume it */
|
|
|
|
|
expect(SymbolType.SEMICOLON, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
}
|
|
|
|
|
/* This should never happen */
|
|
|
|
|
else
|
|
|
|
@ -552,7 +620,7 @@ public final class Parser
|
|
|
|
|
Statement[] statements;
|
|
|
|
|
|
|
|
|
|
/* Consume the `struct` that caused `parseStruct` to be called */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Expect an identifier here (no dot) */
|
|
|
|
|
string structName = lexer.getCurrentToken().getToken();
|
|
|
|
@ -563,11 +631,11 @@ public final class Parser
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Consume the name */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* TODO: Here we will do a while loop */
|
|
|
|
|
expect(SymbolType.OCURLY, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
while(true)
|
|
|
|
|
{
|
|
|
|
@ -596,7 +664,7 @@ public final class Parser
|
|
|
|
|
|
|
|
|
|
/* Should have a semi-colon and consume it */
|
|
|
|
|
expect(SymbolType.SEMICOLON, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
}
|
|
|
|
|
/* If it is an accessor */
|
|
|
|
|
else if (isAccessor(lexer.getCurrentToken()))
|
|
|
|
@ -664,7 +732,7 @@ public final class Parser
|
|
|
|
|
expect(SymbolType.CCURLY, lexer.getCurrentToken());
|
|
|
|
|
|
|
|
|
|
/* Consume the closing curly brace */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
WARN("parseStruct(): Leave");
|
|
|
|
@ -677,7 +745,7 @@ public final class Parser
|
|
|
|
|
ReturnStmt returnStatement;
|
|
|
|
|
|
|
|
|
|
/* Move from `return` onto start of expression */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
// TODO: Check if semicolon here (no expression) else expect expression
|
|
|
|
|
|
|
|
|
@ -702,7 +770,7 @@ public final class Parser
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Move off of the terminator */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
return returnStatement;
|
|
|
|
|
}
|
|
|
|
@ -715,7 +783,7 @@ public final class Parser
|
|
|
|
|
Statement[] statements;
|
|
|
|
|
|
|
|
|
|
/* Consume the `{` symbol */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* If we were able to get a closing token, `}`, then
|
|
|
|
@ -815,7 +883,7 @@ public final class Parser
|
|
|
|
|
|
|
|
|
|
/* Save and consume the init-scope */
|
|
|
|
|
InitScope initScope = getInitScope(lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Get the current token's symbol type */
|
|
|
|
|
SymbolType symbolType = getSymbolType(lexer.getCurrentToken());
|
|
|
|
@ -881,7 +949,7 @@ public final class Parser
|
|
|
|
|
|
|
|
|
|
/* Save and consume the accessor */
|
|
|
|
|
AccessorType accessorType = getAccessorType(lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* TODO: Only allow, private, public, protected */
|
|
|
|
|
/* TODO: Pass this to call for class prsewr or whatever comes after the accessor */
|
|
|
|
@ -951,7 +1019,7 @@ public final class Parser
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Consume the `(` token */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Count for number of parameters processed */
|
|
|
|
|
ulong parameterCount;
|
|
|
|
@ -976,7 +1044,7 @@ public final class Parser
|
|
|
|
|
expect("Identifier can not be path");
|
|
|
|
|
}
|
|
|
|
|
string identifier = lexer.getCurrentToken().getToken();
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Add the local variable (parameter variable) */
|
|
|
|
@ -990,7 +1058,7 @@ public final class Parser
|
|
|
|
|
else if(getSymbolType(lexer.getCurrentToken()) == SymbolType.COMMA)
|
|
|
|
|
{
|
|
|
|
|
/* Consume the `,` */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
moreArgs = true;
|
|
|
|
|
}
|
|
|
|
@ -1001,7 +1069,7 @@ public final class Parser
|
|
|
|
|
if(!moreArgs)
|
|
|
|
|
{
|
|
|
|
|
/* Consume the `)` */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
/* Error out if we were and we prematurely ended */
|
|
|
|
@ -1041,7 +1109,7 @@ public final class Parser
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
}
|
|
|
|
|
/* If no body is requested */
|
|
|
|
|
else
|
|
|
|
@ -1071,14 +1139,14 @@ public final class Parser
|
|
|
|
|
private DiscardStatement parseDiscard()
|
|
|
|
|
{
|
|
|
|
|
/* Consume the `discard` */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Parse the following expression */
|
|
|
|
|
Expression expression = parseExpression();
|
|
|
|
|
|
|
|
|
|
/* Expect a semi-colon */
|
|
|
|
|
expect(SymbolType.SEMICOLON, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Create a `discard` statement */
|
|
|
|
|
DiscardStatement discardStatement = new DiscardStatement(expression);
|
|
|
|
@ -1096,11 +1164,11 @@ public final class Parser
|
|
|
|
|
CastedExpression castedExpression;
|
|
|
|
|
|
|
|
|
|
/* Consume the `cast` */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Expect an `(` open brace */
|
|
|
|
|
expect(SymbolType.LBRACE, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Expect a type
|
|
|
|
@ -1122,7 +1190,7 @@ public final class Parser
|
|
|
|
|
|
|
|
|
|
/* Expect a `)` closing brace */
|
|
|
|
|
expect(SymbolType.RBRACE, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Get the expression to cast */
|
|
|
|
|
Expression uncastedExpression = parseExpression();
|
|
|
|
@ -1310,7 +1378,7 @@ public final class Parser
|
|
|
|
|
addRetExp(numberLiteral);
|
|
|
|
|
|
|
|
|
|
/* Get the next token */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
}
|
|
|
|
|
/* If it is a cast operator */
|
|
|
|
|
else if(symbol == SymbolType.CAST)
|
|
|
|
@ -1326,7 +1394,7 @@ public final class Parser
|
|
|
|
|
|
|
|
|
|
/* TODO: Save operator, also pass to constructor */
|
|
|
|
|
/* TODO: Parse expression or pass arithemetic (I think latter) */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
OperatorExpression opExp;
|
|
|
|
|
|
|
|
|
@ -1388,7 +1456,7 @@ public final class Parser
|
|
|
|
|
addRetExp(new StringExpression(lexer.getCurrentToken().getToken()));
|
|
|
|
|
|
|
|
|
|
/* Get the next token */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
}
|
|
|
|
|
/* If we have a `[` (array index/access) */
|
|
|
|
|
else if(symbol == SymbolType.OBRACKET)
|
|
|
|
@ -1398,9 +1466,9 @@ public final class Parser
|
|
|
|
|
DEBUG("indexTo: "~indexTo.toString());
|
|
|
|
|
|
|
|
|
|
/* Get the index expression */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
Expression index = parseExpression();
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
DEBUG("IndexExpr: "~index.toString());
|
|
|
|
|
// gprintln(lexer.getCurrentToken());
|
|
|
|
|
|
|
|
|
@ -1412,7 +1480,7 @@ public final class Parser
|
|
|
|
|
{
|
|
|
|
|
string identifier = lexer.getCurrentToken().getToken();
|
|
|
|
|
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
Expression toAdd;
|
|
|
|
|
|
|
|
|
@ -1452,13 +1520,13 @@ public final class Parser
|
|
|
|
|
else if (symbol == SymbolType.LBRACE)
|
|
|
|
|
{
|
|
|
|
|
/* Consume the `(` */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Parse the inner expression till terminator */
|
|
|
|
|
addRetExp(parseExpression());
|
|
|
|
|
|
|
|
|
|
/* Consume the terminator */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* `new` operator
|
|
|
|
@ -1466,11 +1534,11 @@ public final class Parser
|
|
|
|
|
else if(symbol == SymbolType.NEW)
|
|
|
|
|
{
|
|
|
|
|
/* Cosume the `new` */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Get the identifier */
|
|
|
|
|
string identifier = lexer.getCurrentToken().getToken();
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NewExpression toAdd;
|
|
|
|
@ -1503,7 +1571,7 @@ public final class Parser
|
|
|
|
|
Expression previousExpression = removeExp();
|
|
|
|
|
|
|
|
|
|
/* TODO: Get next expression */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
Expression item = parseExpression();
|
|
|
|
|
|
|
|
|
|
/* TODO: Construct accessor expression from both and addRetExp */
|
|
|
|
@ -1545,7 +1613,7 @@ public final class Parser
|
|
|
|
|
/* TODO: Save type */
|
|
|
|
|
string type = lexer.getCurrentToken().getToken();
|
|
|
|
|
string identifier;
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -1565,7 +1633,7 @@ public final class Parser
|
|
|
|
|
/* If we have `[` then expect a number and/or a `]` */
|
|
|
|
|
if(getSymbolType(lexer.getCurrentToken()) == SymbolType.OBRACKET)
|
|
|
|
|
{
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
SymbolType nextType = getSymbolType(lexer.getCurrentToken());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -1617,7 +1685,7 @@ public final class Parser
|
|
|
|
|
type=type~"*";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If were requested to only find a type, then stop here and return it */
|
|
|
|
@ -1650,7 +1718,7 @@ public final class Parser
|
|
|
|
|
}
|
|
|
|
|
identifier = lexer.getCurrentToken().getToken();
|
|
|
|
|
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
DEBUG("ParseTypedDec: DecisionBtwn FuncDef/VarDef: " ~ lexer.getCurrentToken().getToken());
|
|
|
|
|
}
|
|
|
|
|
/* Anything else is an error */
|
|
|
|
@ -1735,7 +1803,7 @@ public final class Parser
|
|
|
|
|
if(wantsBody)
|
|
|
|
|
{
|
|
|
|
|
/* Consume the `=` token */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Now parse an expression */
|
|
|
|
|
Expression expression = parseExpression();
|
|
|
|
@ -1790,7 +1858,7 @@ public final class Parser
|
|
|
|
|
/* Expect a `=` and consume it */
|
|
|
|
|
DEBUG(lexer.getCurrentToken());
|
|
|
|
|
expect(SymbolType.ASSIGN, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Parse the expression being assigned followed by a semi-colon `;` */
|
|
|
|
|
Expression expressionBeingAssigned = parseExpression();
|
|
|
|
@ -1826,7 +1894,7 @@ public final class Parser
|
|
|
|
|
Clazz generated;
|
|
|
|
|
|
|
|
|
|
/* Pop off the `class` */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Get the class's name (CAN NOT be dotted) */
|
|
|
|
|
expect(SymbolType.IDENT_TYPE, lexer.getCurrentToken());
|
|
|
|
@ -1836,7 +1904,7 @@ public final class Parser
|
|
|
|
|
}
|
|
|
|
|
string className = lexer.getCurrentToken().getToken();
|
|
|
|
|
DEBUG("parseClass(): Class name found '" ~ className ~ "'");
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
generated = new Clazz(className);
|
|
|
|
|
|
|
|
|
@ -1848,14 +1916,14 @@ public final class Parser
|
|
|
|
|
/* TODO: Loop until `}` */
|
|
|
|
|
|
|
|
|
|
/* Consume the inheritance operator `:` */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
while(true)
|
|
|
|
|
{
|
|
|
|
|
/* Check if it is an identifier (may be dotted) */
|
|
|
|
|
expect(SymbolType.IDENT_TYPE, lexer.getCurrentToken());
|
|
|
|
|
inheritList ~= lexer.getCurrentToken().getToken();
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Check if we have ended with a `{` */
|
|
|
|
|
if(getSymbolType(lexer.getCurrentToken()) == SymbolType.OCURLY)
|
|
|
|
@ -1867,7 +1935,7 @@ public final class Parser
|
|
|
|
|
else if(getSymbolType(lexer.getCurrentToken()) == SymbolType.COMMA)
|
|
|
|
|
{
|
|
|
|
|
/* Consume */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
}
|
|
|
|
|
/* Error out if we get anything else */
|
|
|
|
|
else
|
|
|
|
@ -1886,7 +1954,7 @@ public final class Parser
|
|
|
|
|
|
|
|
|
|
/* TODO: Here we will do a while loop */
|
|
|
|
|
expect(SymbolType.OCURLY, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
Statement[] statements;
|
|
|
|
|
|
|
|
|
@ -1917,7 +1985,7 @@ public final class Parser
|
|
|
|
|
|
|
|
|
|
/* Should have a semi-colon and consume it */
|
|
|
|
|
expect(SymbolType.SEMICOLON, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
}
|
|
|
|
|
/* If it is a class */
|
|
|
|
|
else if(symbolType == SymbolType.CLASS)
|
|
|
|
@ -1987,7 +2055,7 @@ public final class Parser
|
|
|
|
|
parentToContainer(generated, statements);
|
|
|
|
|
|
|
|
|
|
/* Pop off the ending `}` */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
WARN("parseClass(): Leave");
|
|
|
|
|
|
|
|
|
@ -2165,14 +2233,14 @@ public final class Parser
|
|
|
|
|
Statement statement;
|
|
|
|
|
|
|
|
|
|
/* Consume the star `*` */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
ulong derefCnt = 1;
|
|
|
|
|
|
|
|
|
|
/* Check if there is another star */
|
|
|
|
|
while(getSymbolType(lexer.getCurrentToken()) == SymbolType.STAR)
|
|
|
|
|
{
|
|
|
|
|
derefCnt+=1;
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Expect an expression */
|
|
|
|
@ -2180,14 +2248,14 @@ public final class Parser
|
|
|
|
|
|
|
|
|
|
/* Expect an assignment operator */
|
|
|
|
|
expect(SymbolType.ASSIGN, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Expect an expression */
|
|
|
|
|
Expression assigmentExpression = parseExpression();
|
|
|
|
|
|
|
|
|
|
/* Expect a semicolon */
|
|
|
|
|
expect(SymbolType.SEMICOLON, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
// FIXME: We should make a LHSPiinterAssignmentThing
|
|
|
|
|
statement = new PointerDereferenceAssignment(pointerExpression, assigmentExpression, derefCnt);
|
|
|
|
@ -2196,50 +2264,18 @@ public final class Parser
|
|
|
|
|
|
|
|
|
|
return statement;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
import std.container.slist : SList;
|
|
|
|
|
import tlang.compiler.symbols.comments;
|
|
|
|
|
private SList!(Comment) commentStack;
|
|
|
|
|
private void pushComment(Token commentToken)
|
|
|
|
|
{
|
|
|
|
|
// Sanity check
|
|
|
|
|
assert(getSymbolType(commentToken) == SymbolType.SINGLE_LINE_COMMENT ||
|
|
|
|
|
getSymbolType(commentToken) == SymbolType.MULTI_LINE_COMMENT
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Push it onto top of stack
|
|
|
|
|
commentStack.insertFront(Comment.fromToken(commentToken));
|
|
|
|
|
}
|
|
|
|
|
//TODO: Add a popToken() (also think if we want a stack-based mechanism)
|
|
|
|
|
private bool hasCommentsOnStack()
|
|
|
|
|
{
|
|
|
|
|
return getCommentCount() != 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private ulong getCommentCount()
|
|
|
|
|
{
|
|
|
|
|
import std.range : walkLength;
|
|
|
|
|
return walkLength(commentStack[]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Comment popComment()
|
|
|
|
|
{
|
|
|
|
|
Comment popped = commentStack.front();
|
|
|
|
|
commentStack.removeFront();
|
|
|
|
|
return popped;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void parseComment()
|
|
|
|
|
{
|
|
|
|
|
WARN("parseComment(): Enter");
|
|
|
|
|
|
|
|
|
|
Token curCommentToken = lexer.getCurrentToken();
|
|
|
|
|
|
|
|
|
|
pushComment(curCommentToken);
|
|
|
|
|
// pushComment(curCommentToken);
|
|
|
|
|
|
|
|
|
|
// TODO: Do something here like placing it on some kind of stack
|
|
|
|
|
DEBUG("Comment is: '"~curCommentToken.getToken()~"'");
|
|
|
|
|
lexer.nextToken(); // Move off comment
|
|
|
|
|
nextToken(); // Move off comment
|
|
|
|
|
|
|
|
|
|
WARN("parseComment(): Leave");
|
|
|
|
|
}
|
|
|
|
@ -2443,11 +2479,11 @@ public final class Parser
|
|
|
|
|
|
|
|
|
|
Expression[] arguments;
|
|
|
|
|
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Expect an opening brace `(` */
|
|
|
|
|
expect(SymbolType.LBRACE, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* If next token is RBRACE we don't expect arguments */
|
|
|
|
|
if(getSymbolType(lexer.getCurrentToken()) == SymbolType.RBRACE)
|
|
|
|
@ -2473,7 +2509,7 @@ public final class Parser
|
|
|
|
|
/* If comma expect more */
|
|
|
|
|
else if(getSymbolType(lexer.getCurrentToken()) == SymbolType.COMMA)
|
|
|
|
|
{
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
/* TODO: If rbrace after then error, so save boolean */
|
|
|
|
|
}
|
|
|
|
|
/* TODO: Add else, could have exited on `;` which is invalid closing */
|
|
|
|
@ -2485,7 +2521,7 @@ public final class Parser
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
WARN("parseFuncCall(): Leave");
|
|
|
|
|
|
|
|
|
@ -2497,11 +2533,11 @@ public final class Parser
|
|
|
|
|
ExternStmt externStmt;
|
|
|
|
|
|
|
|
|
|
/* Consume the `extern` token */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Expect the next token to be either `efunc` or `evariable` */
|
|
|
|
|
SymbolType externType = getSymbolType(lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Pseudo-entity */
|
|
|
|
|
Entity pseudoEntity;
|
|
|
|
@ -2536,7 +2572,7 @@ public final class Parser
|
|
|
|
|
|
|
|
|
|
/* Expect a semicolon to end it all and then consume it */
|
|
|
|
|
expect(SymbolType.SEMICOLON, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
externStmt = new ExternStmt(pseudoEntity, externType);
|
|
|
|
|
|
|
|
|
@ -2617,14 +2653,14 @@ public final class Parser
|
|
|
|
|
WARN("parseImport(): Enter");
|
|
|
|
|
|
|
|
|
|
/* Consume the `import` keyword */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Get the module's name */
|
|
|
|
|
expect(SymbolType.IDENT_TYPE, lexer.getCurrentToken());
|
|
|
|
|
string moduleName = lexer.getCurrentToken().getToken();
|
|
|
|
|
|
|
|
|
|
/* Consume the token */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* All modules to be imported */
|
|
|
|
|
string[] collectedModuleNames = [moduleName];
|
|
|
|
@ -2633,7 +2669,7 @@ public final class Parser
|
|
|
|
|
while(getSymbolType(lexer.getCurrentToken()) == SymbolType.COMMA)
|
|
|
|
|
{
|
|
|
|
|
/* Consume the comma `,` */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Get the module's name */
|
|
|
|
|
expect(SymbolType.IDENT_TYPE, lexer.getCurrentToken());
|
|
|
|
@ -2641,12 +2677,12 @@ public final class Parser
|
|
|
|
|
collectedModuleNames ~= curModuleName;
|
|
|
|
|
|
|
|
|
|
/* Consume the name */
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Expect a semi-colon and consume it */
|
|
|
|
|
expect(SymbolType.SEMICOLON, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Perform the actual import */
|
|
|
|
|
doImport(collectedModuleNames);
|
|
|
|
@ -2669,15 +2705,15 @@ public final class Parser
|
|
|
|
|
|
|
|
|
|
/* Expect `module` and module name and consume them (and `;`) */
|
|
|
|
|
expect(SymbolType.MODULE, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Module name may NOT be dotted (TODO: Maybe it should be yeah) */
|
|
|
|
|
expect(SymbolType.IDENT_TYPE, lexer.getCurrentToken());
|
|
|
|
|
string moduleName = lexer.getCurrentToken().getToken();
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
expect(SymbolType.SEMICOLON, lexer.getCurrentToken());
|
|
|
|
|
lexer.nextToken();
|
|
|
|
|
nextToken();
|
|
|
|
|
|
|
|
|
|
/* Initialize Module */
|
|
|
|
|
modulle = new Module(moduleName);
|
|
|
|
@ -2731,7 +2767,7 @@ public final class Parser
|
|
|
|
|
prog.setEntryModule(curModEnt, modulle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* TODO: We should add `lexer.hasTokens()` to the `lexer.nextToken()` */
|
|
|
|
|
/* TODO: We should add `lexer.hasTokens()` to the `nextToken()` */
|
|
|
|
|
/* TODO: And too the `getCurrentTokem()` and throw an error when we have ran out rather */
|
|
|
|
|
|
|
|
|
|
/* We can have an import or vardef or funcdef */
|
|
|
|
|