- Added `allowVarDec` and `allwFuncDef` to `parseTypedDeclaration()` as default arguments with `true` as their default values
- If `allowFuncDef` is true then parse a function
- If `allowVarDec` is `true` then allow a variable definition
- If `allowVarDec` is true but we have an assignment and `wantsBody` is false then throw an error
- NOTE: A fix for `parseTypedDeclaration()` is needed for this to work

Tests

- Updated `simple_extern.t` to include an `extern evar`
This commit is contained in:
Tristan B. Velloza Kildaire 2023-01-19 08:08:41 +02:00
parent aa11af5bba
commit d288440e18
2 changed files with 77 additions and 35 deletions

View File

@ -1304,7 +1304,7 @@ public final class Parser
return retExpression[0]; return retExpression[0];
} }
private TypedEntity parseTypedDeclaration(bool wantsBody = true) private TypedEntity parseTypedDeclaration(bool wantsBody = true, bool allowVarDec = true, bool allowFuncDef = true)
{ {
gprintln("parseTypedDeclaration(): Enter", DebugType.WARNING); gprintln("parseTypedDeclaration(): Enter", DebugType.WARNING);
@ -1346,55 +1346,89 @@ public final class Parser
gprintln("ParseTypedDec: SymbolType=" ~ to!(string)(symbolType)); gprintln("ParseTypedDec: SymbolType=" ~ to!(string)(symbolType));
if (symbolType == SymbolType.LBRACE) if (symbolType == SymbolType.LBRACE)
{ {
funcDefPair pair = parseFuncDef(wantsBody); // Only continue is function definitions are allowed
if(allowFuncDef)
{
funcDefPair pair = parseFuncDef(wantsBody);
generated = new Function(identifier, type, pair.bodyStatements, pair.params); generated = new Function(identifier, type, pair.bodyStatements, pair.params);
import std.stdio; import std.stdio;
writeln(to!(string)((cast(Function)generated).getVariables())); writeln(to!(string)((cast(Function)generated).getVariables()));
// Parent the parameters of the function to the Function // Parent the parameters of the function to the Function
parentToContainer(cast(Container)generated, cast(Statement[])pair.params); parentToContainer(cast(Container)generated, cast(Statement[])pair.params);
// Parent the statements that make up the function to the Function // Parent the statements that make up the function to the Function
parentToContainer(cast(Container)generated, pair.bodyStatements); parentToContainer(cast(Container)generated, pair.bodyStatements);
}
else
{
expect("Function definitions not allowed");
}
} }
/* Check for semi-colon (var dec) */ /* Check for semi-colon (var dec) */
else if (symbolType == SymbolType.SEMICOLON) else if (symbolType == SymbolType.SEMICOLON)
{ {
nextToken(); // Only continue if variable declarations are allowed
gprintln("ParseTypedDec: VariableDeclaration: (Type: " ~ type ~ ", Identifier: " ~ identifier ~ ")", if(allowVarDec)
DebugType.WARNING); {
gprintln("Semi: "~to!(string)(getCurrentToken()));
nextToken();
gprintln("Semi: "~to!(string)(getCurrentToken()));
gprintln("ParseTypedDec: VariableDeclaration: (Type: " ~ type ~ ", Identifier: " ~ identifier ~ ")",
DebugType.WARNING);
generated = new Variable(type, identifier); generated = new Variable(type, identifier);
}
else
{
expect("Variables declarations are not allowed.");
}
} }
/* Check for `=` (var dec) */ /* Check for `=` (var dec) */
else if (symbolType == SymbolType.ASSIGN) else if (symbolType == SymbolType.ASSIGN)
{ {
nextToken(); // Only continue if variable declarations are allowed
if(allowVarDec)
{
// Only continue if assignments are allowed
if(wantsBody)
{
nextToken();
/* Now parse an expression */ /* Now parse an expression */
Expression expression = parseExpression(); Expression expression = parseExpression();
VariableAssignment varAssign = new VariableAssignment(expression); VariableAssignment varAssign = new VariableAssignment(expression);
/** /**
* The symbol that returned us from `parseExpression` must * The symbol that returned us from `parseExpression` must
* be a semi-colon * be a semi-colon
*/ */
expect(SymbolType.SEMICOLON, getCurrentToken()); expect(SymbolType.SEMICOLON, getCurrentToken());
nextToken(); nextToken();
gprintln("ParseTypedDec: VariableDeclarationWithAssingment: (Type: " gprintln("ParseTypedDec: VariableDeclarationWithAssingment: (Type: "
~ type ~ ", Identifier: " ~ identifier ~ ")", DebugType.WARNING); ~ type ~ ", Identifier: " ~ identifier ~ ")", DebugType.WARNING);
Variable variable = new Variable(type, identifier); Variable variable = new Variable(type, identifier);
variable.addAssignment(varAssign); variable.addAssignment(varAssign);
varAssign.setVariable(variable); varAssign.setVariable(variable);
generated = variable; generated = variable;
}
else
{
expect("Variable assignments+declarations are not allowed.");
}
}
else
{
expect("Variables declarations are not allowed.");
}
} }
else else
{ {
@ -1796,14 +1830,16 @@ public final class Parser
{ {
// TODO: (For one below)(we should also disallow somehow assignment) - evar // TODO: (For one below)(we should also disallow somehow assignment) - evar
// We now parse function definition but with wantsBody false // We now parse function definition but with `wantsBody` set to false
pseudoEntity = parseTypedDeclaration(false); // indicating no body should be allowed.
pseudoEntity = parseTypedDeclaration(false, false, true);
} }
/* External variable symbol */ /* External variable symbol */
else if(externType == SymbolType.EXTERN_EVAR) else if(externType == SymbolType.EXTERN_EVAR)
{ {
// TODO: Implement me // We now parse a variable declaration but with the `wantsBody` set to false
assert(false); // indicating no assignment should be allowed.
pseudoEntity = parseTypedDeclaration(false, true, false);
} }
/* Anything else is invalid */ /* Anything else is invalid */
else else
@ -1811,6 +1847,11 @@ public final class Parser
expect("Expected either extern function (efunc) or extern variable (evar)"); expect("Expected either extern function (efunc) or extern variable (evar)");
} }
// TODO: If we are doing all this semi-colon stuff in `parseTypedDecaration()` then we ought
// ... to put the below code in there. Compare body ending `}` and nextToken()'ing it
// ... to a vardec finishing on `;` and then returning to `parseName()` which does nothing
// ... we could seem how we go about this, perhaps body is the exception case, and we should
// ... be nextToken()'ing and before that exoecting in `parseName()` and here, `parseExtern()'
/* Expect a semicolon to end it all and then consume it */ /* Expect a semicolon to end it all and then consume it */
expect(SymbolType.SEMICOLON, getCurrentToken()); expect(SymbolType.SEMICOLON, getCurrentToken());
nextToken(); nextToken();

View File

@ -1,6 +1,7 @@
module simple_extern; module simple_extern;
extern efunc uint write(uint fd, ubyte* buffer, uint count); extern efunc uint write(uint fd, ubyte* buffer, uint count);
extern evar int stdin;
void test() void test()
{ {